Files
Compass/CLAUDE.md

6.2 KiB

CLAUDE.md

Guidance for Claude Code working in this repo. Keep this file lean — per-package details live in each package's own CLAUDE.md. Detailed prose lives under docs/.

Project

Compass (compassmeet.com) — transparent platform for forming deep, authentic 1-on-1 connections. Yarn-workspaces monorepo: Next.js web, Express API, Capacitor Android shell, shared TS packages. Backed by Supabase (Postgres), Firebase (auth + media), Vercel (web), Google Cloud (API).

Workspaces

Path What it is Read first
web/ Next.js + React + Tailwind frontend web/CLAUDE.md
backend/api/ Express REST + WebSocket server backend/api/CLAUDE.md
backend/shared/ Backend-only utils (DB, websockets, monitoring) backend/shared/CLAUDE.md
backend/email/ React-email templates + send helpers backend/email/CLAUDE.md
backend/scripts/ One-off scripts (migrations, maintenance) backend/scripts/CLAUDE.md
backend/supabase/ Per-table SQL reference + type-regen makefile backend/supabase/CLAUDE.md
common/ Types + pure utils shared by web and backend common/CLAUDE.md
supabase/ Active migrations + local-stack config supabase/CLAUDE.md
android/ Capacitor WebView wrapper around the web build android/CLAUDE.md

Import boundaries (load-bearing)

  • web and backend/* import from common/*. common never imports from web or backend/*.
  • Anything in backend/* may import from backend/shared. backend/shared never imports from sibling backend packages.
  • Keep common's dependency footprint small.

Cross-cutting commands

Run from the repo root. Package manager is yarn (yarn install --frozen-lockfile).

yarn dev              # web + API against the shared remote dev DB (visit http://localhost:3000)
yarn dev:isolated     # web + API + local Supabase + Firebase emulators (needs Docker, Supabase CLI, Java 21+, Firebase CLI)
yarn lint             # ESLint across all packages
yarn lint-fix
yarn typecheck        # tsc --noEmit across all packages
yarn prettier
yarn test             # Jest unit + integration across all workspaces
yarn test:coverage
yarn test:e2e         # Playwright E2E (spins up services)
yarn test:e2e:dev     # Playwright against an already-running dev server

Single workspace / single test (the workspace test script already passes --config, so append Jest args):

yarn --cwd=common test
yarn --cwd=backend/api test path/to/file.unit.test.ts
yarn --cwd=web test -t "renders profile card"

Database:

./scripts/migrate.sh supabase/migrations/<file>.sql   # apply a migration to dev
yarn --cwd=backend/api regen-types-dev                # rebuild common/src/supabase/schema.ts

Adding an API endpoint (3 files across 2 packages)

  1. Schema — add entry (method, authed, Zod props, returns) in common/src/api/schema.ts.
  2. Handlerexport const x: APIHandler<'endpoint-name'> in backend/api/src/<verb>-<resource>.ts.
  3. Register — add to the handlers map in backend/api/src/app.ts (~line 583).

Frontend then calls it via useAPIGetter('endpoint-name', props) (client) or api('endpoint-name', props) (server-side). Full details in backend/api/CLAUDE.md and web/CLAUDE.md.

Database access

  • Backend: createSupabaseDirectClient() from shared/supabase/init — raw SQL via pg-promise.
  • Frontend: db from web/lib/supabase/db — Supabase JS client (PostgREST). Web cannot run raw SQL.
  • Never string-concatenate SQL. Use helpers in shared/supabase/utils (insert, update, updateData, bulkUpsert, ...) or compose with renderSql/select/from/where from shared/supabase/sql-builder. SQL is lowercase by convention.

Cross-cutting conventions

  • Timestamps: Date everywhere in TS, TIMESTAMPTZ in Postgres (pg-promise converts). Zod handles Date↔string serialization across the wire. When persisting Date to localStorage, convert string back to Date on load.
  • Logging: debug() from common/logger (or log from shared/monitoring/log on the backend). Never console.log.
  • No sleep() for "eventual consistency" — rely on transactional integrity (see backend/api/src/create-user-and-profile.ts).
  • Don't split into multiple API calls when data can be batched in one transaction (e.g. fetch profile options together).
  • Lodash (keyBy, uniq, uniqBy, ...) over hand-rolled loops/Sets.
  • i18n: useT() from web/lib/locale, then t('key', 'English fallback'). Translation JSON in common/messages/. Details in docs/internationalization.md.
  • Scripts that mutate backend state or schema are run by the human, not Claude.
  • When editing files, do NOT remove comments or commented-out code.

Docs

Architecture and patterns: docs/knowledge.md, docs/architecture.md, docs/development.md. Frontend: docs/next-js.md, docs/react.md, docs/filters.md. Database: docs/database-schema.md, docs/database-connection-pooling.md, docs/performance-optimization.md. Cross-cutting: docs/internationalization.md, docs/profile-fields.md, docs/testing.md, docs/logging-monitoring.md, docs/troubleshooting.md.