An API-first personal finance platform built as a monorepo. The web client is a thin React SPA that consumes a typed JSON API. Developers can provision API keys to build their own tools.
🚀 Quick Start Guide - Get running in 5 minutes with the interactive setup wizard
- API-first: Stable /v1 JSON endpoints backed by Zod schemas with autogenerated OpenAPI 3.1 contract
- Secure by design: Auth.js authentication with JWT sessions, Upstash Redis rate limiting (10 req/min on auth endpoints), structured audit logging
- Thin client: React SPA calls public API exclusively; no direct DB access or secrets in web app
- Portable: Pure client-side architecture enables easy wrapping with Capacitor for mobile deployment
- Operationally simple: Vercel deploys, serverless-friendly jobs, reproducible migrations
✅ Phase 1 Complete: Monorepo infrastructure with pnpm workspaces, Turborepo, TypeScript, Biome, Vitest, and Playwright
✅ Phase 2 Complete: Authentication with Auth.js, JWT sessions, httpOnly cookies, Google OAuth, magic links
✅ Phase 3 Complete: API Key Management with Bearer token auth and scope enforcement
🚧 Phase 3.5 In Progress: Architecture refactor to Service/Repository pattern for cleaner code organization
⏸️ Phase 4 Planned: Plaid Integration for bank connections (not yet started)
See .scope/project_plan.md for detailed roadmap.
.
├── apps/
│ ├── api/ # Hono API server exposing /v1 routes
│ └── web/ # Thin React SPA (Vite)
├── packages/
│ ├── auth/ # Auth.js adapters, PAT hashing, RBAC scopes
│ ├── core/ # Domain logic (billing, ledgers, limits)
│ ├── database/ # Prisma schema + migrations + client exports
│ ├── design-system/ # Custom React components with Tailwind CSS
│ ├── observability/ # Logging, tracing, audit emitters
│ ├── rate-limit/ # Upstash helpers
│ ├── sdk/ # Generated OpenAPI client
│ └── types/ # Zod contracts shared across layers
└── tooling/ # CI workflows and scripts (future)
- Hono 4 on Node adapter serving /v1 routes
- Zod for validation with OpenAPI generation
- Prisma 6 with Neon-hosted Postgres
- Auth.js for authentication with JWT sessions (30-day expiration)
- Upstash Redis for rate limiting (sliding window algorithm)
- Pino for structured logging
- Vitest for unit/integration tests
- Vite + React 19 (pure SPA, no SSR)
- React Router for client-side routing
- Tailwind CSS for styling
- TanStack Query for API state management
- Playwright for E2E testing
- pnpm workspaces for package management
- Turborepo for build orchestration
- Biome for linting and formatting
- tsup for package bundling
- Node.js 20+
- pnpm 9+
- PostgreSQL database (or Neon account)
- Clone the repository:
git clone <repository-url>
cd superbasic-finance- Install dependencies:
pnpm install- Set up environment variables:
Option A: Interactive Setup (Recommended)
pnpm tsx tooling/scripts/setup-env.tsThis wizard will walk you through configuring:
- Database (Neon Postgres)
- Authentication secrets
- Rate limiting (Upstash Redis)
- OAuth (Google)
- Email (Resend)
Option B: Manual Setup
# Copy example files
cp apps/api/.env.example apps/api/.env.local
cp apps/web/.env.example apps/web/.env.local
cp packages/database/.env.example packages/database/.env.local
# Edit .env.local files with your actual values
# - AUTH_URL (base URL for Auth.js, e.g., http://localhost:3000)
# - AUTH_TRUST_HOST (set to true in development)
# - UPSTASH_REDIS_REST_URL (optional, for rate limiting)
# - UPSTASH_REDIS_REST_TOKEN (optional, for rate limiting)
# - GOOGLE_CLIENT_ID (optional, for Google OAuth)
# - GOOGLE_CLIENT_SECRET (optional, for Google OAuth)
# - EMAIL_SERVER (optional, for magic link authentication)
# - EMAIL_FROM (optional, sender address for magic links)
# Note: GitHub OAuth deferred to Phase 16- Generate Prisma client:
pnpm db:generate- Run database migrations:
pnpm db:migrate- Build all packages:
pnpm build- Start development servers:
pnpm devThe API will be available at http://localhost:3000 and the web client at http://localhost:5173.
Authentication:
POST /v1/register- Create new user accountPOST /v1/login- Authenticate and receive session cookiePOST /v1/logout- Clear session cookieGET /v1/me- Get current user profile (requires authentication)
API Key Management:
POST /v1/tokens- Create new API key (session auth required)GET /v1/tokens- List all API keys (session auth required)DELETE /v1/tokens/:id- Revoke API key (session auth required)PATCH /v1/tokens/:id- Update API key name (session auth required)
Health:
GET /v1/health- API health check
See the API Authentication Guide for detailed documentation on Bearer token authentication and token management.
# Start all apps in development mode
pnpm dev
# Start specific app only
pnpm dev --filter=api
pnpm dev --filter=web# Build all packages and apps
pnpm build
# Build specific package/app
pnpm build --filter=api
pnpm build --filter=@repo/core# Run all unit tests
pnpm test
# Run unit tests in watch mode
pnpm test:watch
# Run E2E tests (starts servers automatically)
pnpm --filter=@repo/web test:e2e:run
# Run specific E2E test file
pnpm --filter=@repo/web test:e2e:run auth.spec.ts
# Run E2E tests with UI mode
pnpm --filter=@repo/web test:e2e:run -- --ui
# Manual E2E testing (faster for development)
# Terminal 1: pnpm --filter=@repo/api dev:test
# Terminal 2: pnpm --filter=@repo/web dev
# Terminal 3: pnpm --filter=@repo/web test:e2e# Lint all packages
pnpm lint
# Type check all packages
pnpm typecheck
# Format code with Biome
pnpm format# Generate Prisma client
pnpm db:generate
# Run migrations (options: test, local, prod)
pnpm db:migrate --target local
# Seed database (options: test, local, prod)
pnpm db:seed --target local
# Reset database (wipes data and reseeds)
pnpm db:reset --target local# Generate OpenAPI spec (future)
pnpm api:docs
# Generate SDK from OpenAPI spec (future)
pnpm sdk:generatePrisma schema, migrations, and client exports. All database access goes through this package.
Shared Zod schemas for API contracts. Used by both API and web client for type safety.
Auth.js configuration, PAT utilities, and RBAC scope definitions.
Domain logic including billing, ledgers, and limits. Pure functions that can be tested in isolation.
Generated OpenAPI client for consuming the API. Will be auto-generated from the OpenAPI spec.
Logging and tracing utilities using Pino and Sentry.
Upstash Redis helpers for rate limiting API endpoints.
Custom React components built with Tailwind CSS. No third-party UI libraries.
- Create a feature branch from
main - Make your changes in the appropriate package or app
- Run
pnpm lintandpnpm typecheckto verify code quality - Run
pnpm testto ensure tests pass - Run
pnpm buildto verify everything compiles - Commit your changes and open a pull request
All data access happens through the public API. The web client never directly accesses the database or contains sensitive secrets. This enables:
- Easy mobile app development with Capacitor
- Third-party integrations via API keys
- Clear separation of concerns
The React SPA is purely client-side with no server-side rendering. All business logic lives in the API or shared packages. This keeps the client simple and portable.
Financial data is never deleted or mutated. All changes are recorded as new ledger entries, providing a complete audit trail.
All data is scoped to workspaces with row-level security policies. Users can belong to multiple workspaces with different roles.
- Location: Colocated with source code (
*.test.tsfiles) - Framework: Vitest with coverage reporting
- Scope: Core business logic, utilities, and API handlers
- Run:
pnpm testorpnpm test:watch
- Location:
apps/api/src/**/*.test.ts - Framework: Vitest with test database
- Scope: API endpoints with real database interactions
- Database: Separate test database configured in
apps/api/.env.test
- Location:
apps/web/e2e/ - Framework: Playwright with Chromium
- Scope: Complete user flows from browser perspective
- Coverage: Authentication flows (registration, login, session, logout)
- Run:
pnpm --filter=@repo/web test:e2e:run
The E2E test script automatically:
- Starts API server with test database
- Starts web dev server
- Waits for both to be ready
- Runs tests
- Cleans up servers on completion
See apps/web/e2e/README.md for detailed E2E testing documentation.
SuperBasic Finance supports multiple authentication methods:
- Traditional email and password authentication
- Passwords hashed with bcrypt (cost factor 10)
- JWT sessions stored in httpOnly cookies (30-day expiration)
Configure OAuth providers for social login:
Google OAuth:
- Create OAuth app in Google Cloud Console
- Add authorized redirect URI:
http://localhost:3000/v1/auth/callback/google - Copy client ID and secret to
.env.local - See OAuth Setup Guide for detailed step-by-step instructions
Configure email provider for passwordless authentication:
- Choose an email service (Resend, SendGrid, or Postmark recommended)
- Obtain SMTP credentials
- Add
EMAIL_SERVERandEMAIL_FROMto.env.local - Format:
smtp://username:password@smtp.example.com:587
- Personal access tokens (PATs) for programmatic API access
- SHA-256 hashed before storage
- Scope-based permissions (read:transactions, write:budgets, etc.)
- See API Authentication Guide for details
- ✅ Auth.js authentication with JWT sessions (httpOnly cookies, 30-day expiration)
- ✅ Google OAuth integration with CSRF protection
- ✅ Magic link authentication with rate limiting (3 per hour per email)
- ✅ Passwords hashed with bcrypt (cost factor 10)
- ✅ Rate limiting on auth endpoints (10 req/min per IP) via Upstash Redis
- ✅ Personal access tokens (PATs) with SHA-256 hashing
- ✅ Bearer token authentication for programmatic API access
- ✅ Scope-based permissions system (read:transactions, write:budgets, etc.)
- ✅ Comprehensive audit logging for auth and API key events
- ✅ CORS configured for cross-origin cookie support
- � Row-level security policies in Postgres - Phase 6
- 🔮 Additional OAuth providers (GitHub, Apple) - Phase 16
- � Stripe webhook signatures - Phase 7
- API: Vercel with Node.js runtime (production ready)
- Web: Vercel as static SPA (production ready)
- Database: Neon Postgres with branch isolation
mainbranch → Productiondevbranch → Development + Preview deployments
- Redis: Upstash for rate limiting
- Jobs: Future Phase 5 (Upstash QStash for background processing)
Deployment Guides:
- Vercel Deployment Guide - Complete deployment walkthrough
- Neon Branch Setup - Database branch configuration
- Quick Start - Get running in 5 minutes with interactive setup
- OAuth Setup - Configure Google OAuth authentication
- Neon Setup - Database branch configuration
- Vercel Deployment - Deploy to production
- PWA Setup - Progressive Web App configuration
- API Authentication - Complete auth guide (sessions, OAuth, magic links, API keys)
- Plaid Setup - Bank integration setup (Phase 4 - not yet implemented)
- E2E Testing - End-to-end testing guide
- Project Plan - Complete roadmap and phase breakdown
- Current Phase - Active phase status and tasks
- Steering Docs - Architecture and best practices
- Follow the code style enforced by Biome
- Write tests for new features
- Update documentation as needed
- Keep PRs focused and reasonably sized
- Reference requirements in commit messages
[Add your license here]
[Add support information here]