Appearance
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]
| Rule | Meaning |
|---|---|
No supabase.from() in src/ | Reads → RPC in hooks; writes → EF in services. Data Access. |
| No inline EF names | EF names come from a per-feature EDGE_FN map (UPPER_SNAKE_CASE). |
| One Supabase client | src/lib/supabaseClient.ts; no second createClient; no hardcoded prod fallback URL. |
| Tier boundaries | public ⇏ user,admin; user ⇏ admin. Features import UI from their tier's components/ui/. |
| Zero hard-coded colors | In class strings (chart stroke/fill excepted). Theme via cn() + isLight/tokens. |
| No per-page theme branching | Light/dark driven centrally. |
| RLS on every user-facing table | Plus the EF as primary write gate. |
Naming conventions [ENFORCED]
| Thing | Convention | Example |
|---|---|---|
| Component | PascalCase | MenuItemCard.jsx |
| Hook | use + camelCase | useDigitalMenu.js |
| Service | camelCase + Service | menuService.ts |
| Table | snake_case | digital_menus |
| RPC | get_{entity} / get_{feature}_summary | get_public_menu |
| Edge Function | kebab domain-action / domain-noun-verb | manage-profile, public_page_ops_cache_refresh |
EDGE_FN key | UPPER_SNAKE_CASE | MANAGE_PROFILE |
| Migration | YYYYMMDDHHMMSS_name.sql | 20260710134136_baseline_schema_from_prod.sql |
| Tracker id | QRS-### | 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/.tsxfor 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/.jsxopportunistically during retrofit.
Lint & hooks
- Flat config
eslint.config.mjs— keepsno-undef/import/no-self-importas errors; some noisy rules disabled deliberately (read the inline comments before re-enabling). - Husky
pre-commitrunstype-check && lint(project-wide). Planned:lint-staged+ affected tests. - Planned guardrail rules: no
from()insrc/, no inline EF names, no secondcreateClient, 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.