Monorepo with Next.js PWA frontend and FastAPI GraphQL backend.
apps/web— frontend (Vercel target)apps/api— backend (Railway target)infra/sql— migrations/seedsdocs— architecture and scope docs
- Operations live in
apps/web/graphql/**/*.graphql. - Committed API schema:
apps/api/schema.graphql(source of truth for codegen on Vercel). - Generated types and documents:
apps/web/graphql/generated/graphql.ts.
When you change the Strawberry schema or add operations:
- After API schema changes (API venv active):
pnpm schema:export— refreshesapps/api/schema.graphql, thenpnpm codegen(or one shot:pnpm codegen:all). pnpm codegen— regenerates TypeScript from the committed schema (also runs automatically beforepnpm --filter web build; no Python required).
Watch mode during frontend work: pnpm --filter web codegen:watch.
See docs/testing.md. Quick commands:
pnpm test:web— Vitest (unit + component)pnpm test:e2e— Playwrightpnpm test:api— pytest (Postgres + seed required)
- Database: use your Supabase Postgres URL in
apps/api/.envasDATABASE_URL(Session pooler or direct connection from the Supabase dashboard). Optionally, for a fully local Postgres instead, rundocker compose up -d— default DB name in compose ismytripspots. - Web:
- copy
apps/web/.env.exampletoapps/web/.env.local pnpm installpnpm dev:web
- copy
- API:
- copy
apps/api/.env.exampletoapps/api/.env - use a venv (recommended; on Debian/Ubuntu system Python often blocks
pip installwithout a venv):- from repo root:
python3 -m venv .venvthensource .venv/bin/activate pip install -e ./apps/api
- from repo root:
- run from
apps/api(so.envis picked up):uvicorn main:app --reload --port 8000
or without activating venv:../.venv/bin/python -m uvicorn main:app --reload --port 8000
- copy
Apply SQL files in order:
infra/sql/0001_init.sqlinfra/sql/0002_seed.sql
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYCLERK_SECRET_KEYNEXT_PUBLIC_API_GRAPHQL_URL
DATABASE_URLCLERK_JWKS_URLCLERK_ISSUERCORS_ALLOWED_ORIGINS(required whenAPP_ENV=production— your Vercel / site origin(s), comma-separated)R2_ACCESS_KEY_IDR2_SECRET_ACCESS_KEYR2_BUCKETR2_ENDPOINT_URLUPLOAD_MAX_MB
Recommended media settings:
UPLOAD_MAX_MB=4(server hard cap)- web client auto-compresses images to WebP near 3MB before upload
- Project → Settings → General
- Root Directory:
apps/web(required; not the monorepo root) - Framework Preset: Next.js (auto-detected or set manually)
- Output Directory: leave empty (for Next.js, Vercel uses
.nextautomatically). If it is set topublic, clear it — otherwise you will get No Output Directory named "public".
- Root Directory:
- Build & Development: you can leave commands at defaults — they come from
apps/web/vercel.json(installfrom the repo root +pnpm --filter web build). - Commit
pnpm-lock.yamlat the repository root.
CLI: run from the app directory so the Next.js project is picked up: cd apps/web && npx vercel (or after linking with the correct Root Directory in the dashboard).
- root directory:
apps/api - apply
apps/api/railway.json - start command handled by config
- See docs/vps-deploy.md — shared Postgres in
/opt/infra, GHCR images, Caddy reverse proxy - Release: push tag
prod-N→ GitHub Actions buildsghcr.io/andreydos/mytripspots-{web,api}:prod-N - VPS compose template:
deploy/vps/docker-compose.yml