All commands run from the repo root unless noted.

Common commands

CommandWhat it does
pnpm installInstall all workspace deps
pnpm run devBoot frontend + backend together (turbo run dev)
pnpm run buildBuild all apps
pnpm run lintTypecheck all apps
pnpm db:upStart local Postgres (Docker, detached)
pnpm db:downStop local Postgres
pnpm db:generateGenerate a Drizzle migration from schema changes
pnpm db:migrateApply pending migrations
pnpm db:pushPush schema directly (dev shortcut, skips migrations)
pnpm db:studioOpen Drizzle Studio
Target a single app: pnpm --filter frontend <script> or pnpm --filter backend <script>.

Environment files

.env files are git-ignored. Commit .env.example-style docs instead if values need sharing. The frontend reads NEXT_PUBLIC_API_URL; the backend reads DATABASE_URL, Clerk keys, and CORS_ORIGIN.

Backend dev notes

Backend dev uses tsx watch — no build step in dev. pnpm --filter backend build emits to apps/backend/dist. Turbo caches build and lint; dev and start are persistent and uncached.

Troubleshooting

A previous dev server is still holding the port. Free it with lsof -nP -tiTCP:3000 -sTCP:LISTEN | xargs kill (swap the port as needed), or change the -p flag in apps/frontend/package.json and update CORS_ORIGIN to match.
If the dev server panics with Failed to restore task data or Unable to open static sorted file ... .sst, the Turbopack disk cache was corrupted (usually from an unclean shutdown). Delete the cache and restart: rm -rf apps/frontend/.next. Stop dev servers with Ctrl-C rather than kill -9 to avoid recurrence.