Project-specific instructions for AI coding agents working in this repo. Read this before making changes. See CLAUDE.md, README.md, CONTRIBUTING.md, and docs/README.md for the current project overview and architecture decisions. docs/refactor-plan.md is historical context for the completed Go split, not current-state guidance.
- What it is: exponential — a Linear-style issue tracker (issues, projects, cycles, initiatives, triage, inbox).
- Architecture: split monorepo with Go headless API, Next.js web UI, generated TypeScript SDK, and TS CLI.
- Backend:
apps/apiGo + chi + pgx/sqlc + SQL migrations, deployed as an ECS service behind ALB/api/*. - Frontend:
apps/webNext.js 16 App Router UI-only app that consumes the generated SDK/headless API. - Auth: first-party Go auth. Do not reintroduce Kratos, Better Auth, NextAuth, or password auth without an explicit new plan.
- Tests: Vitest/unit, Go tests, and Playwright E2E. Required before merge/push when code changes.
make check— typecheck + Biome lint/format + Go/API/deploy/OpenAPI guards. Run after every code change.make test— Go API tests + Vitest unit tests.make test-e2e— Playwright E2E. Run before manual testing for QA.make all— check + test.npm run dev/pnpm dev— start the web app only (no Go API;/api/*proxies will 502 without the API running).make dev-full— full host stack in one command: Docker services + migrations, Go API (:7016), and web (:7015).make dev-api— Go API in host mode with hot reload (air; falls back togo runifairis not installed).make codegen— regenerate sqlc queries + Go OpenAPI stubs + TS SDK after changingopenapi.yamlor SQL.docker compose -f docker-compose.dev.yml up -d— local Postgres, Redis, API, web, Mailhog.- Pre-commit hook (lefthook) auto-runs
biome --write+gofmt -won staged files; it is not a substitute formake check.
apps/api/— Go API, auth, handlers, OpenAPI strict server stubs, sqlc queries, migrations runner.apps/web/— Next.js UI.apps/web/src/app/api/should remain empty/nonexistent; runtime API/auth/billing/database work belongs inapps/api.apps/cli/— CLI consuming the generated SDK.packages/proto/openapi.yaml— public API contract.packages/proto/migrations/— SQL migrations.packages/sdk/— generated TypeScript SDK plus small hand-written helpers.infra/— Docker/ECS deployment definitions.scripts/— validation, OpenAPI, deploy, smoke-test helpers.
- TypeScript strict: no
any, noas unknown asshortcuts. Add real types. - Go code: keep handlers small, use context-aware DB calls, return RFC 7807-style JSON problems for API errors.
- OpenAPI first: every Go business endpoint must be represented in
packages/proto/openapi.yaml; regenerate SDK/stubs when the contract changes. - One feature per commit, with a short, descriptive message.
- Never weaken or delete tests to make them pass. Fix the code, not the test.
- Run
make check && make testbefore every commit. - Run
make test-e2ebefore declaring UI/runtime flows verified. - Out of scope: paywalls, subscription checkout, payment collection, and hosted SaaS billing flows. Do not add these without an explicit approved plan. Existing workspace billing/settings and Stripe webhook surfaces are current product/admin code; do not remove or expand them casually.
- Preserve the terminal/editorial redesign. Do not revert or delete redesign/theme code from the
308371clineage. - Tailwind utility classes; theme tokens live in
apps/web/tailwind.config.tsand CSS variables inapps/web/src/app/globals.css/apps/web/src/app/editorial-theme.css. - Prefer existing tokens over hard-coded hex values.
- Radix primitives wrap interactive UI. Reuse before introducing a new component library.
- Keyboard-first: every interaction should be reachable by keyboard and/or command palette where appropriate.
- Dark mode is class-based. Style for both modes.
make check— typecheck + lint + architecture/deploy guards.make test— Go + unit tests.make test-e2e— E2E with local dev stack.- For UI changes, open the affected page in a browser and exercise both the golden path and at least one edge case.
- For deployment changes, run
scripts/deploy-ecs.shwithRUN_PROD_SMOKE=trueand verify ECS/ALB state.
Local API:
curl -X POST http://localhost:7016/v1/<endpoint> \
-H "Authorization: Bearer <dev-api-key-or-pat>" \
-H "Content-Type: application/json" \
-d '{ ... }'Through local web proxy:
curl http://localhost:7015/api/healthzSDK:
pnpm --filter @namuh-eng/expn-sdk testCLI:
pnpm --filter @namuh-eng/expn-cli test- AWS CLI configured via
~/.aws/credentials. .envholds local/deploy credentials; copy from.env.examplewhen needed.- Default local frontend port: 7015.
- Default local backend port: 7016.
- Infrastructure provisioning:
bash scripts/preflight.sh. - ECS deploy/smoke:
RUN_PROD_SMOKE=true scripts/deploy-ecs.sh.
- Fix it in source. Don't paper over it in tests.
- Group fixes for one feature into a single commit after
make check && make testpasses. - Commit message:
fix: <one-line description>.