This is the authoritative control surface for all coding agents. Read this first.
apps/web/ Next.js 16 frontend (App Router, Tailwind v4, shadcn/ui)
services/api/ FastAPI backend (layered: types/config/repo/service/runtime)
packages/shared/ Shared TypeScript types
docs/ System of record (features, workflows, security, reliability)
docs/exec-plans/ Execution plans and tech debt tracker
infra/railway/ Deployment config
When this repo is used as the foundation for a new app, the following pieces are part of the starter contract — keep them. Adapt only what the new use case actually requires.
Keep as-is (do not strip, rename, or replace)
- UI kit / design system.
apps/web/src/components/ui/(shadcn primitives), the design tokens inapps/web/src/app/globals.css, and the/designreference page. Build new screens with these primitives; never edit the generatedcomponents/ui/files directly. Restyling happens through tokens inglobals.css. - File Explorer.
/filesroute,apps/web/src/app/files/, andapps/web/src/components/files/. The Files sidebar entry inapps/web/src/components/layout/app-sidebar.tsxstays. - Upload.
/uploadroute,apps/web/src/app/upload/, andapps/web/src/components/upload/. The Upload sidebar entry stays. - The sidebar nav itself (Dashboard, Upload, Files, Settings, plus the Design System utility link).
Adapt to the new use case
- Dashboard.
/route andapps/web/src/components/dashboard/(stats cards, upload chart, recent uploads table) are illustrative defaults. Replace them with metrics, charts, and tables that reflect what the new app actually does (e.g. transcripts processed, embeddings indexed, classifications run). New aggregations must flow through the sameruntime -> service -> repolayering and be exposed via TanStack Query hooks inapps/web/src/lib/queries.ts— no bareuseEffect + fetch. - Update
docs/features/dashboard.mdin the same PR as any dashboard change (see §9).
Why this contract exists
- The UI kit, Files, and Upload pages are the reusable B2-backed scaffolding that makes this a starter kit — stripping them defeats the purpose. The dashboard is the only screen explicitly designed to be rewritten per app.
Backend layering: types -> config -> repo -> service -> runtime
- No backward imports across layers
- No
boto3outsiderepo/ - No business logic in route handlers (
runtime/) - All external APIs wrapped in
repo/adapters - All request/response data validated at boundary (Pydantic models)
- No shared mutable state across layers
Frontend: shadcn/ui components in src/components/ui/ are generated — never modify them.
Data fetching: every API call flows through TanStack Query hooks in apps/web/src/lib/queries.ts. No bare useEffect + fetch patterns. New endpoints touch three files: runtime/<router>.py, lib/api-client.ts, lib/queries.ts.
- DRY — do not duplicate logic, types, or constants. Extract shared code only when used in 2+ places.
- Structured JSON logging only — no
print()statements - No raw SDK calls outside
repo/layer - Files stay under 300 lines
- Tests added or updated for every behavior change
- Docs updated in same PR as code changes
- Lint clean before merge
- Prefer boring, composable libraries over clever abstractions
- No implicit type assumptions — use typed models
| Rule | Enforced by |
|---|---|
| No backward imports | tests/test_structure.py::test_no_backward_imports |
| No boto3 outside repo/ | tests/test_structure.py::test_boto3_only_in_repo |
| File size < 300 lines | tests/test_structure.py::test_file_size_limits |
| All layers exist | tests/test_structure.py::test_all_layers_exist |
| No bare print() | ruff rule T20 |
| Import ordering | ruff rule I001 |
| Frontend strict equality | eslint rule eqeqeq |
| No unused vars | eslint + ruff rules |
# Run
pnpm dev # start both frontend and backend
pnpm dev:web # frontend only
pnpm dev:api # backend only
# Test & Lint
pnpm lint # frontend lint (eslint)
pnpm build # frontend type check + build
pnpm lint:api # backend lint (ruff)
pnpm test:api # backend tests (pytest)
pnpm check:structure # structural boundary tests
pnpm test:e2e # Playwright e2e tests- Read this file first.
- Review ARCHITECTURE.md before structural changes.
- For non-trivial changes, create a plan in
docs/exec-plans/active/. - Implement the smallest coherent change.
- Run:
pnpm lint && pnpm lint:api && pnpm test:api && pnpm check:structure - Update docs in the same PR (see §9).
- Move completed plans to
docs/exec-plans/completed/. - Only change files relevant to the task. No drive-by improvements.
See docs/dev-workflows.md for full details.
| Change Type | Update Location |
|---|---|
| Feature logic, inputs, outputs, tests | docs/features/<feature>.md |
| User journeys | docs/app-workflows.md |
| System layout, deployments | ARCHITECTURE.md |
| Dev or testing process | docs/dev-workflows.md |
| Setup or scope changes | README.md |
| Security changes | docs/SECURITY.md |
| Reliability changes | docs/RELIABILITY.md |
| Active work plans | docs/exec-plans/active/ |
| Known tech debt | docs/exec-plans/tech-debt-tracker.md |
If documentation and implementation conflict, update docs in the same PR. Documentation rot destroys agent reliability.
| Topic | Location |
|---|---|
| System layout, data flows, boundaries | ARCHITECTURE.md |
| Feature docs | docs/features/ |
| User journeys | docs/app-workflows.md |
| Engineering workflows and testing | docs/dev-workflows.md |
| Security principles | docs/SECURITY.md |
| Reliability expectations | docs/RELIABILITY.md |
| Execution plans | docs/exec-plans/ |
| Tech debt | docs/exec-plans/tech-debt-tracker.md |
- Prefer boring, stable libraries
- Prefer small PRs over large changes
- Add tests with every change
- Never bypass lint rules without explicit instruction
- Ask before making destructive or irreversible changes