StellFlow Frontend
The web app for StellFlow, a payroll / invoice / escrow platform for
freelancers and clients that settles in USDC on Stellar. This is the
Next.js 16 App Router front end: a marketing landing page, a Freighter
wallet-connect and onboarding flow, and a dashboard for invoices,
milestone escrows, analytics and notifications. The escrow contract lives in
stellflow-smartcontract
and the REST API in
stellflow-backend; see
How the three repos fit together.
⚠️ Status: UI prototype with a live, read-only link to the contract.
Builds, runs, and is deployed to Vercel. Two things are real: the
Freighter connect step, and the escrow-contract panel, which reads
get_admin / is_paused / get_version / get_escrow_ttl / get_escrow
from the deployed testnet contract over Soroban RPC on every page load.
Everything else in the dashboard runs on in-memory sample data, labelled
as such on every page. No Stellar transaction is ever built, signed or
submitted; the axios client in app/lib/api/ has no callers and doesn't
match the backend's routes; "auth" is a set of localStorage flags. The
table below says exactly what is wired. See Known issues
and SECURITY.md before relying on any of it.
What's wired and what isn't
| Area | Status | Where | Notes |
|---|
| Landing page | ✅ real | app/page.tsx, app/components/landing/ | The former metrics strip is now the live contract panel; the hero mock-up is labelled "Illustrative preview" |
Escrow contract reads (admin, paused, version, TTL, latest ledger, get_escrow lookup) | ✅ real, live | app/lib/soroban.ts, app/components/ContractStatus.tsx | Read-only simulation over Soroban RPC from the browser; on / and /dashboard/escrows. No signing |
| Freighter connect | ✅ real | app/lib/freighter.ts, app/components/WalletModal.tsx | requestAccess + getNetwork; address and network go to localStorage |
| Albedo / WalletConnect | ❌ stub | WalletModal.tsx:89-93 | Buttons exist; clicking navigates without a session (#50) |
| Session / route guards | ⚠️ client-only | app/lib/walletSession.ts, app/components/AuthGuard.tsx | localStorage flags, no server session; hydration error for returning users (#48) |
| Onboarding (4 steps, zod) | ✅ real | app/components/OnboardingForm.tsx | Stores nothing but an onboarded flag |
| Invoices — create, list, filter, sort, paginate, bulk actions | ✅ real, in-memory | app/lib/invoiceStore.ts, app/components/Invoice*.tsx | Seeded with 5 sample invoices in demo mode, labelled "sample data"; lost on reload (#52) |
| Invoice "Pay Now" | ❌ stub | app/dashboard/invoices/[id]/page.tsx:92 | Shows a success toast, does nothing (#57) |
| Escrows — 5-step wizard, list, detail with state diagram | ⚠️ in-memory, simulated | app/components/escrow/, app/lib/escrowStore.ts | Wizard fakes signing with setTimeout and a random tx hash (#47) |
| Escrow fund / release / refund / dispute | ❌ absent |
Stack
| |
|---|
| Framework | Next.js 16.2 (App Router, Turbopack), React 19.2, TypeScript 5 strict |
| Styling | Tailwind CSS 4 with design tokens as CSS variables in app/globals.css; clsx + tailwind-merge; framer-motion; lucide-react icons |
| State | zustand 5 (persist for UI, theme and notifications); localStorage for the wallet session |
| Forms | react-hook-form 7 + zod 4 |
| Stellar | @stellar/freighter-api 6 for connect/sign; @stellar/stellar-sdk 17 for Soroban RPC simulation (app/lib/soroban.ts) and the Horizon client |
| Data | axios 1 client in app/lib/api/ (unused); recharts 3; date-fns 4 |
| Tests | vitest 4 + @testing-library/react + jsdom; Playwright (e2e/) against a production build |
| Deploy | Vercel (vercel.json), live at https://stellflow.vercel.app |
The version of Next.js in node_modules ships its own docs at
node_modules/next/dist/docs/; read those rather than older tutorials
(AGENTS.md says the same to AI assistants).
Prerequisites
- Node.js 20 or later and npm
- The Freighter browser extension, set to
Testnet, if you want to go past the landing page in a browser. The
test suite does not need it.
That's all. There is no database, and no backend has to be running.
以上为 README 的开头部分。其余内容请阅读原文。 查看完整 README ↗