Skip to content

Coding Standards

What reviewers enforce. These are the day-to-day rules; the architecture pages explain why.

Definition of Done

A change is done when all of these hold:

  • Implemented to standards.
  • Unit + smoke tests green (+ integration/E2E where relevant).
  • Security & lint gates pass.
  • Performance budget respected.
  • Docs / ADR updated ("if it isn't documented, it isn't done").
  • Observability added for new surfaces.
  • Migrations expand-contract and promoted to both Supabase projects.
  • Tracker (QRS-###) updated.
  • Verified end-to-end in-app, not just via tests.

The hard rules [ENFORCED]

RuleMeaning
No supabase.from() in src/Reads → RPC in hooks; writes → EF in services. Data Access.
No inline EF namesEF names come from a per-feature EDGE_FN map (UPPER_SNAKE_CASE).
One Supabase clientsrc/lib/supabaseClient.ts; no second createClient; no hardcoded prod fallback URL.
Tier boundariespublic ⇏ user,admin; user ⇏ admin. Features import UI from their tier's components/ui/.
Zero hard-coded colorsIn class strings (chart stroke/fill excepted). Theme via cn() + isLight/tokens.
No per-page theme branchingLight/dark driven centrally.
RLS on every user-facing tablePlus the EF as primary write gate.

Naming conventions [ENFORCED]

ThingConventionExample
ComponentPascalCaseMenuItemCard.jsx
Hookuse + camelCaseuseDigitalMenu.js
ServicecamelCase + ServicemenuService.ts
Tablesnake_casedigital_menus
RPCget_{entity} / get_{feature}_summaryget_public_menu
Edge Functionkebab domain-action / domain-noun-verbmanage-profile, public_page_ops_cache_refresh
EDGE_FN keyUPPER_SNAKE_CASEMANAGE_PROFILE
MigrationYYYYMMDDHHMMSS_name.sql20260710134136_baseline_schema_from_prod.sql
Tracker idQRS-###QRS-042

Consistency

  • New code reads like surrounding code — match idiom, structure, naming.
  • No speculative abstractions; no "temporary" hacks on release branches.
  • No regressions. Surface bugs/debt/risks and confirm before non-trivial or cross-cutting changes.
  • Validate each step (tests/build) before the next.

TypeScript [ENFORCED — TS-first]

  • .ts/.tsx for logic; keep UI glue idiomatic.
  • Shared, platform-agnostic core (types, Zod schemas, contracts, pure logic) — no react-dom/DOM imports — so web and future native both consume it.
  • Convert .js/.jsx opportunistically during retrofit.

Lint & hooks

  • Flat config eslint.config.mjs — keeps no-undef / import/no-self-import as errors; some noisy rules disabled deliberately (read the inline comments before re-enabling).
  • Husky pre-commit runs type-check && lint (project-wide). Planned: lint-staged + affected tests.
  • Planned guardrail rules: no from() in src/, no inline EF names, no second createClient, tier import boundaries, no hard-coded colors, no per-page theme branching, + eslint-plugin-sonarjs / eslint-plugin-security.

Principal-Architect stance

Evaluate every change as a Principal Solution Architect: surface better alternatives, call out debt/risk, and log every confirmed finding to the tracker (QRS-###) — log-after-confirmation, never fix-and-forget.