ADRs capture decisions that shape Rhitta. Each is short by design — read in under two minutes, link from PRs and code.
- Numbered sequentially. Never renumber; supersede with a new ADR if needed.
- Status is one of:
Proposed,Accepted,Superseded by NNNN,Deprecated. - ADR-0005 retains its number for continuity with the audited EmberForge codebase.
| # | Title | One-liner |
|---|---|---|
| 0001 | pnpm workspaces | Plain pnpm workspaces over Nx/Turborepo for v0 |
| 0002 | Hexagonal architecture | Ports and adapters for every external concern |
| 0003 | Module DI pattern | composeRoot / registerXModule per feature module |
| 0004 | Zod as sole validator | One validation system, shared via @rhitta/contracts |
| 0005 | DB seam through repos | All DB access funnels through repository files |
| 0006 | Three-package design system | tokens + design-system-web + design-system-mobile |
| 0007 | TanStack Form everywhere | One form library on web and mobile |
| 0008 | Ignite-themed mobile styling | No NativeWind on mobile |
| 0009 | Encore.ts + Docker default | API runs on Encore.ts, ships as Docker |
| 0010 | Fixed versioning | All @rhitta/* packages share one version |
| 0011 | Lint-enforced architectural boundaries | @rhitta/biome-config/api-app bans direct DB/vendor SDK imports outside infra/ / adapters/ |
| 0012 | Two-layer tokens + dual theme | Primitive + semantic layers, light + dark from day 1 |
| 0013 | @rhitta/contracts package shape |
Per-domain folders + per-subpath exports + three-shapes-per-entity boundary |
| 0014 | Asymmetric JSX transform | jsx: preserve on web, jsx: react-jsx on mobile |
| 0015 | Single Encore service + multi-module | One api service; modules are the only boundary in v0 |
| 0016 | Drizzle ORM | Canonical repository tool with SQL-first migrations |
| 0017 | Belt-and-braces validation | Encore TS-derived wire validation + explicit Zod runtime parse |
| 0018 | Domain errors + central mapper | Typed DomainError hierarchy mapped to HTTP status in one file |
| 0019 | SSR-first web app | apps/web renders server-side first; auth-gated routes resolve before HTML |
| 0020 | Encore-generated API client | Canonical typed client at apps/web/src/lib/api-client/; banned to bypass |
| 0021 | Centralized realtime hook factory | All realtime subscriptions via useRealtimeSubscription; raw transports banned outside lib/realtime/ |
| 0022 | Radix Primitives (not Themes) | Design-system-web wraps unstyled Radix Primitives with Tailwind v4 + design-tokens semantic CSS vars |
| 0023 | Expo Router on mobile | File-based routing mirroring web; single auth gate at _authenticated/_layout.tsx |
| 0024 | Zustand replaces MobX | Mobile UI state via Zustand; MST stripped by the overlay |
| 0025 | Mobile post-install overlay | npx ignite-cli new + idempotent rhitta-overlay.sh patches generated files |
| 0026 | Platform-correct test runners | Mobile tests on jest-expo; web/api on Vitest — different problems, ecosystem-correct tools |
| 0027 | create-rhitta vendored scaffold | Public unscoped CLI vendors the whole monorepo; keeps @rhitta/*, rewrites project ids; independent version |
- Take the next free number (
ls docs/adr→ highest+ 1). - Copy the template below.
- Keep the four sections short — bullets are fine.
- Link from the PR that introduces the decision and from any code the ADR governs.
# ADR NNNN: Title
## Status
Proposed | Accepted | Superseded by NNNN | Deprecated
## Context
What problem this solves, what alternatives were considered.
## Decision
The decision in one paragraph.
## Consequences
What this enables and what it costs.