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.
Package manager
Section titled “Package manager”bun / bunx only. Use npm / npx only when truly required (a tool that breaks under Bun).
bun install # install workspace depsbun add foo # add to current packagebun --filter @repo/api ... # run a task in a specific workspacebunx some-cli # one-shot exec without installpackageManager: [email protected] is pinned at the root package.json.
Patched dependencies
Section titled “Patched dependencies”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.
Filenames
Section titled “Filenames”kebab-case everywhere — lead-row.tsx, use-dashboard.ts, property-card.svelte, auth-client.ts.
Identifiers inside files stay PascalCase / camelCase as the language conventions dictate:
export function LeadRow({ lead }: { lead: Lead }) { ... }This applies to:
- All source files in
apps/*andpackages/*. - All MDX/MD files in this docs site.
| Surface | Library |
|---|---|
| Web | @lucide/svelte |
| Native mobile | SF Symbols (iOS) / Material icons (Compose) |
Env files
Section titled “Env files”Never read .env.local. Treat it as opaque per-developer secrets. Read .env.example and ask the developer to confirm values. See Settings → Secrets.
i18n compile (web)
Section titled “i18n compile (web)”After editing apps/svelte-web/messages/{en,es}.json:
cd apps/svelte-web && bunx @inlang/paraglide-js compile \ --project ./project.inlang \ --outdir ./src/lib/paraglideThe 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)).
i18n locale mapping
Section titled “i18n locale mapping”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(notPENDING).InquiryStatusisNEW | CONTACTED | IN_PROGRESS | CLOSED | CONVERTED(not generic CRUD states).
Database resets
Section titled “Database resets”cd packages/database && bun run db:resetThis drops the schema, then replays the ordered migration chain:
0001_extensions_and_id_functions.ts(PostGIS + ID-generator functions)0002_baseline_schema.ts(tables, fromsql/0002_baseline_schema.sql)0003_triggers_and_functions.ts(triggers + RLS policies + aggregator functions)- 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.
Working notes
Section titled “Working notes”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).
Commit signature
Section titled “Commit signature”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.onErrorso 5xx from non-tRPC paths still land in Sentry.
By JPSimplicity
Section titled “Simplicity”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.
When to consult agent context
Section titled “When to consult agent context”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.