- Runtime: Bun
- Framework: React Router v7 (Remix-style)
- Database: PostgreSQL with Drizzle ORM
- UI: Tailwind CSS + shadcn/ui components
- Testing: Vitest (unit), Playwright (E2E)
- Linting: Biome
app/
├── components/ # React components (shadcn/ui in ui/)
├── db/ # Database schema, migrations, connection
├── repositories/ # Data access layer (Drizzle queries)
├── services/ # Business logic
├── routes/ # React Router routes (file-based routing)
├── schemas/ # Zod validation schemas
└── lib/ # Utilities
e2e/ # Playwright E2E tests
plans/ # Design and implementation plans
docs/ # GitHub Pages (landing page only)
| Command | Purpose |
|---|---|
bun run dev |
Start dev server |
bun run build |
Production build |
bun run typecheck |
Type check |
bun run check:fix |
Lint and format (Biome) |
bun test |
Unit tests (watch mode) |
bun run test:e2e |
E2E tests (Playwright) |
bun run db:generate |
Generate migration from schema changes |
bun run db:migrate |
Run pending migrations |
- Modify schema in
app/db/schema.ts - Run
bun run db:generateto create migration - Run
bun run db:migrateto apply - Add
--> statement-breakpointbetween SQL statements in migrations (required for PGLite E2E tests)
- Unit tests: Co-locate with source files as
*.test.ts(x) - E2E tests: In
e2e/directory, use PGLite (setTEST_PGLITE=true) - Run
bun run test:e2eto regenerate landing page screenshots
- Use existing shadcn/ui components from
app/components/ui/ - Repository pattern for database access (see
app/repositories/) - Zod schemas for form validation (see
app/schemas/) - Prefer server-side data loading in route loaders
Plans and design documents should be saved to plans/ (not docs/).
The docs/ folder is reserved for GitHub Pages content.
When developing with Claude Code, these MCP servers are configured:
| Server | Use For |
|---|---|
| postgres | Query database directly, inspect data |
| github | Create issues/PRs, check CI status |
| memory | Store context across sessions |
| context7 | Look up library documentation |