- Project root structure and monorepo configuration
- Documentation suite (PRD, Architecture, API, Database, Development, AgentMemory, Decisions, Changelog)
- Backend scaffold: Express + TypeScript + Drizzle ORM
- Frontend scaffold: Astro + TypeScript + Tailwind CSS + Nano Stores
- Database schema (users, groups, group_members, expenses, expense_participants, settlements)
- Core middleware (error handling, auth, validation)
- Route structure + all API endpoints
- Services (balance calculation, settlement simplification, UPI links, invite codes)
- Utility modules (JWT, config, invite code generation)
- Nano Stores (auth, groups, polling)
- All UI pages (Landing, Login, Complete Profile, Dashboard, Create Group, Join Group, Group Details, Add Expense, Edit Expense, Profile, 404)
- Phase 1: Authentication — Firebase Authentication (Google Provider), Firebase Admin SDK verification, user profile management
- Phase 2: Groups — CRUD, join/leave, invite codes, member management
- Phase 3: Expenses — CRUD with equal/custom splits, participant validation
- Phase 4: Balance calculation — dynamic computation, greedy debt simplification, UPI deep links, settlement recording
- Phase 5: Server-Sent Events — real-time updates via SSE, in-memory event bus, auto-reconnect with token refresh
- Phase 6: Security — Zod validation, rate limiting, parameterized queries, consistent error format
- Product Improvements — User-scoped suggested payments filtering, editable display name in profile, open-source GitHub navbar button, and global glassmorphic footer
- Tests for critical business logic (18 tests across 3 test files)
- None
- Firebase SDK adds ~152KB to client bundle (31KB gzipped)
getStaticPathswarning on dynamic group page (expected for SSR with Astro)- Frontend stores are defined but not yet deeply integrated with all page scripts
getFirebaseToken()infirebase.tsstill has a fallback observer path for first-time calls — consider fully removing after verifying cached path works in all browsers- SSE connections are stored in-memory (module-level Map) — will not survive server restart. The auto-reconnect mechanism handles this transparently.
- Replace in-memory SSE event bus with Redis pub/sub for horizontal scaling
- Add SSE endpoint for dashboard (
GET /api/me/events) to provide real-time group list updates - Add caching for balance calculation on large groups
- Add integration tests with test database
- Add CI/CD pipeline configuration
- Service worker scope: currently set to root (
/) — verify sub-path deployment behavior - Consider server-side caching for the
/api/dashboardendpoint (e.g., 30s TTL with invalidation on group/expense changes)
- Dashboard load uses a single
/api/dashboardendpoint instead of two separate API calls, halving Firebase token verification overhead - N+1 query pattern in
GET /api/groupswas eliminated by using a correlated subquery for member counts - 8 database indexes added via migration
0001_add_performance_indexesto accelerate foreign key lookups - Frontend
getFirebaseToken()caches tokens at module scope to avoid re-subscribing toonAuthStateChangedon every request - Real-time updates use SSE instead of polling: zero idle API requests, immediate push on data changes
- SSE broadcasts full group state after mutations — one DB query per mutation serves all connected clients
- Refresh-on-focus strategy handles consistency without periodic polling
The service worker is only active in production builds. To test PWA features:
# Build and preview
npm run build && npm run previewThe service worker will register on first visit and precache all static assets. The install prompt appears after the SW is activated and the manifest is parsed by the browser.
node scripts/generate-pwa-icons.mjsRegenerates all PWA icons in public/ from the SVG template. Run this if the logo design changes.