LancePay/
├── app/ # Next.js App Router
│ ├── (auth)/ # Auth route group (no layout)
│ │ ├── login/page.tsx
│ │ └── signup/page.tsx
│ ├── (dashboard)/ # Dashboard route group (with sidebar)
│ │ ├── layout.tsx
│ │ ├── page.tsx # /dashboard
│ │ ├── invoices/
│ │ │ ├── page.tsx # /dashboard/invoices
│ │ │ ├── new/page.tsx # /dashboard/invoices/new
│ │ │ └── [id]/page.tsx # /dashboard/invoices/:id
│ │ ├── withdrawals/
│ │ │ └── page.tsx # /dashboard/withdrawals
│ │ └── settings/
│ │ └── page.tsx # /dashboard/settings
│ ├── pay/
│ │ └── [invoiceId]/page.tsx # Public payment page
│ ├── api/ # API Routes
│ │ ├── auth/
│ │ ├── user/
│ │ ├── invoices/
│ │ ├── bank-accounts/
│ │ ├── withdrawals/
│ │ ├── pay/
│ │ └── webhooks/
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Landing page
│ └── globals.css
│
├── modules/ # Feature modules
│ ├── auth/
│ │ ├── components/
│ │ ├── hooks/
│ │ └── types.ts
│ ├── dashboard/
│ │ ├── components/
│ │ ├── hooks/
│ │ └── types.ts
│ ├── invoices/
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── actions.ts
│ │ └── types.ts
│ ├── payments/
│ │ ├── components/
│ │ ├── hooks/
│ │ └── types.ts
│ ├── withdrawals/
│ │ ├── components/
│ │ ├── hooks/
│ │ └── types.ts
│ └── settings/
│ ├── components/
│ ├── hooks/
│ └── types.ts
│
├── components/ # Shared UI components
│ ├── ui/ # Base components (Button, Input, etc.)
│ ├── layout/ # Layout components (Sidebar, Navbar)
│ └── common/ # Common components (Logo, LoadingSpinner)
│
├── lib/ # Shared utilities
│ ├── db.ts # Prisma client
│ ├── auth.ts # Privy server helpers
│ ├── redis.ts # Upstash Redis
│ ├── blockchain.ts # Viem/Alchemy helpers
│ ├── utils.ts # General utilities
│ └── validations.ts # Zod schemas
│
├── hooks/ # Shared hooks
│ └── use-toast.ts
│
├── types/ # Global types
│ └── index.ts
│
├── prisma/
│ └── schema.prisma # Database schema
│
└── docs/
├── DEVOPS.md
└── MODULES.md
- Purpose: Handle authentication with Privy (Google OAuth)
- Components: LoginButton, AuthGuard, UserMenu
- Hooks: useAuth, useUser, useWallet
- No conflicts: Only module that interacts with Privy SDK
- Purpose: Main dashboard UI after login
- Components: BalanceCard, RecentTransactions, QuickActions, StatsGrid
- Hooks: useBalance, useRecentActivity
- Depends on: Auth (for user data)
- Purpose: Invoice CRUD and management
- Components: InvoiceList, InvoiceForm, InvoiceCard, PaymentLinkShare
- Hooks: useInvoices, useCreateInvoice, useInvoice
- Actions: createInvoice, updateInvoice, deleteInvoice
- Depends on: Auth (for user context)
- Purpose: Public payment page for clients
- Components: PaymentPage, OnrampWidget, PaymentSuccess
- Hooks: usePaymentStatus
- No auth required: Public-facing
- Purpose: Bank withdrawals and history
- Components: WithdrawalModal, BankSelector, ExchangeRateDisplay, WithdrawalHistory
- Hooks: useWithdrawals, useExchangeRate, useBankAccounts
- Depends on: Auth, Settings (for bank accounts)
- Purpose: User profile and bank account management
- Components: ProfileForm, BankAccountList, AddBankAccountModal
- Hooks: useProfile, useBankAccountMutations
- Depends on: Auth
| Module | API Routes | Auth Required |
|---|---|---|
| Auth | /api/auth/*, /api/webhooks/privy |
No (webhooks) |
| Dashboard | /api/user/balance, /api/user/profile |
Yes |
| Invoices | /api/invoices/* |
Yes |
| Payments | /api/pay/[id] |
No (public) |
| Withdrawals | /api/withdrawals/*, /api/exchange-rate |
Yes |
| Settings | /api/bank-accounts/* |
Yes |
- Module isolation: Each module has its own
types.ts- no shared types between modules - API ownership: Each API route belongs to one module only
- Component naming: Prefix with module name if exported (e.g.,
InvoiceCard, notCard) - Hook naming: Include module context (e.g.,
useInvoices, notuseList) - Shared code: Goes in
lib/orcomponents/ui/- never in modules