Skip to content

Monorepo

These apply everywhere unless a nested CLAUDE.md overrides. The canonical source is the repo-root CLAUDE.md (agent context); this page is the human-readable companion.

bun / bunx only. Use npm / npx only when truly required (a tool that breaks under Bun).

Terminal window
bun install # install workspace deps
bun add foo # add to current package
bun --filter @repo/api ... # run a task in a specific workspace
bunx some-cli # one-shot exec without install

packageManager: [email protected] is pinned at the root package.json.

Dependency patches use bun’s built-in bun patch (never patch-package): bun patch <pkg> → edit the printed node_modules copy → bun patch --commit '<path>'. The diff lands in root patches/ and registers under patchedDependencies in the root package.json + bun.lock — commit all three together. There are no patched dependencies today.

kebab-case everywherelead-row.tsx, use-dashboard.ts, property-card.svelte, auth-client.ts.

Identifiers inside files stay PascalCase / camelCase as the language conventions dictate:

src/features/leads/lead-row.tsx
export function LeadRow({ lead }: { lead: Lead }) { ... }

This applies to:

  • All source files in apps/* and packages/*.
  • All MDX/MD files in this docs site.
SurfaceLibrary
Web@lucide/svelte
Native mobileSF Symbols (iOS) / Material icons (Compose)

Never read .env.local. Treat it as opaque per-developer secrets. Read .env.example and ask the developer to confirm values. See Settings → Secrets.

After editing apps/svelte-web/messages/{en,es}.json:

Terminal window
cd apps/svelte-web && bunx @inlang/paraglide-js compile \
--project ./project.inlang \
--outdir ./src/lib/paraglide

The CLI’s default --outdir is ./src/paraglide, which is wrong for this repo. Vite is configured for ./src/lib/paraglide — if you compile to the default, new keys land in a stale tree the app doesn’t import and bun run check fails with “Property does not exist on type messages”.

Native mobile reads JSON catalogs directly — no compile step. The shared i18n/{user,agent}/{en,es}.json sources are fanned out to each app by bun scripts/sync-native-i18n.ts (see Conventions → Mobile (Native)).

Map 'es''es-MX' for Intl.NumberFormat / Intl.DateTimeFormat so you get comma thousands separators:

const fmt = new Intl.NumberFormat(locale === 'es' ? 'es-MX' : 'en-US');

Read packages/database/src/enums.ts (const-object values) and packages/database/src/generated/db.ts (column types) before using any enum value. Recurring bug:

  • Tour.status = REQUESTED (not PENDING).
  • InquiryStatus is NEW | CONTACTED | IN_PROGRESS | CLOSED | CONVERTED (not generic CRUD states).
Terminal window
cd packages/database && bun run db:reset

This drops the schema, then replays the ordered migration chain:

  1. 0001_extensions_and_id_functions.ts (PostGIS + ID-generator functions)
  2. 0002_baseline_schema.ts (tables, from sql/0002_baseline_schema.sql)
  3. 0003_triggers_and_functions.ts (triggers + RLS policies + aggregator functions)
  4. Valkey FLUSHDB

The chain is strictly ordered for a reason: the 0001 ID-generator functions must exist before 0002 creates tables whose ID columns default to generate_*_id(), otherwise those column defaults blow up. The db:reset script replays the migrations in order rather than dropping and recreating in one atomic step, so the functions, triggers, and dbgenerated() defaults all come back intact.

See packages/database/scripts/db-reset.ts for the implementation.

Never commit /context/. It’s local-only working notes — design principles, style guide drafts, in-flight feature specs. Gitignored at the repo root.

The committed equivalents are *.FEATURE.md files next to canonical code (see docs/README.md — three-tier model).

Literal By JP line at the bottom of every commit body. No Claude Co-Authored-By trailers.

fix(api): capture non-tRPC errors via Hono app.onError to Sentry
The new apps/api host wraps tRPC errors via the procedure middleware,
but plain Hono routes (e.g. /api/health) bypassed it. Wire app.onError
so 5xx from non-tRPC paths still land in Sentry.
By JP

Minimal, targeted changes. Don’t add features, refactor, or abstract beyond what the task requires. Three similar lines is better than a premature abstraction. No half-finished implementations.

The CLAUDE.md files at the repo root and per-app are Claude Code instructions — they encode the same conventions, often with more depth and “why” context. If a rule on this page surprises you, the matching CLAUDE.md likely has the backstory.