Show navigation
Architecture
These pages explain the durable, cross-cutting mechanisms that span multiple packages or feature areas — the repo-wide answer to "whenever we need X, we do it this way". Area-specific features live under their own sections (for example resources or esbabbler).
| Page | What it covers |
|---|---|
| Write once | A mechanism written once over the description every case already has — a new case is one declaration, never a change to it |
| Cross-product layer model | How the products link together — identity, resources, datasets, publishing, events |
| Resources | The standard for product persistence and surface — resource model, capabilities, factory |
| Datasets | The standard for serving tabular data — contract, DatasetProvider capability, row cap |
| Publishing | The Publishable capability — versioned publish copy + rate-limited public read |
| Auth | better-auth OAuth setup, session middleware, and the authed procedure chain |
| Agent access | One MCP endpoint over an API key, serving every tRPC procedure whose meta opts in |
| Azure services | Azure service ownership, the storage split, event flows, and the real-time layer model |
| Environment | Environment detection across the three Nuxt runtime contexts |
| File uploads | The two-step Azure Blob SAS upload pattern and upload procedure inventory |
| Large documents | Past one request body a document moves between browser and Blob Storage; the server validates, and carries one only to sync a save |
| Serialization | How class instances survive the three transport paths (Azure Table, Nuxt payload, tRPC) |
| Compression | zstd for every format we own — a foreign format keeps its counterparty's codec |
| Compressed JSON blobs | Every JSON blob stored as a zstd frame served with Content-Encoding: zstd, through one writer and one reader |
| Client data access | The useQuery + useMutation primitives — non-blocking fetch, optimistic apply, staleness |
| Async operations | Concurrency by declaration — reads are latest-wins, writes queue, nothing drops silently |
| Caching | One cached-read primitive, invalidated by tag when a write says what it changed |
| Persisted data — latest shape only | No legacy-shape schemas or migration code — parse the latest shape or reset |
| No compatibility debt | A wrong name, shape or deployed identity is corrected in place — never aliased |
| Content token rewriting | Finding tokens in authored content — self-delimiting matches, one pass, converge on read |
| Monorepo tooling | pnpm workspace orchestration, virrun routing, publishing, installs, and CI job shape |
| Build pipeline | One bundler, shared build presets, and an external list derived from each manifest |
| Nuxt module packages | A workspace package that is a Nuxt module — its entry loaded from source at configuration time, its runtime built unbundled, fixture-app tests |
| Agent configuration | The vendor-neutral .agents tree, its .claude alias, and what stays out of the docs |
| Engineering loops | How work moves — the product, change, code-health and knowledge loops, where work enters, and what runs next |
| Server testing | tRPC router test wiring — in-memory DB, mocked Azure services, controlled auth session |
| Test harness workarounds | Every shim the suite carries for a runner gap, the probe that retires it, and what its removal deletes |
| Lint toolchain | Oxlint as the one repo-wide pass, ESLint behind it for what oxlint cannot parse, and the blocker table a bump reads |
| Third-party reachability | Whether a third party works for a reader is asked of their network, never guessed from language or place |
| Dependency admission | What a third-party package must earn to stay — the three real costs, the admission test, the stop list |
| Dialog shell | One dialog shell — StyledDialog owns the card, the body slot and the actions row |
| Destructive confirmation | One shared delete dialog for what cannot be undone — UiConfirmDialog, the answer it owns, the type-the-name guard |
| Singleton dialogs | Store-driven singleton dialogs — one mounted dialog per feature, never one per list item |
| Navigation | NuxtLink/navigateTo for every link — never a raw anchor — and instant docs routing |
| Persist then notify | Guard, persist, notify — then best-effort bookkeeping that can never fail the caller |
| Notifications | One typed event, one Function, fanned out to the surfaces its type declares |
| Conditional writes | A write derived from a read is conditional on that version, and a lost race re-applies |
| Blob lifecycle ownership | Every blob prefix's naming discipline and single teardown owner per lifecycle event |
| No polling | Polling banned repo-wide — every wait is event-driven or awaits a completion handle |
| No manual recovery | Failed async work retries itself on an event, with an attempt cap and a quarantine |
| Null vs undefined | One absent-value sentinel in app-owned code — null survives only in boundary shapes |
| Module boundaries | The app's three import zones — shared/ may never reach into the client-only app tree |
| Generated artifacts | A script's output lives under generated/ in its consumer, one file per entity, committed and never hand-edited — and never in an authored file |
| Browser execution | Where app/ runs — persisted state, a client-only phase, and the one use left for checkIsServer |
| Search | One search stack — command palette scopes + useAutoSearch/useCursorSearcher |
| Rate limiting | Postgres-backed budgets shared across instances, enforced in the authed middleware |
| Security posture | The app's nuxt-security configuration — CSP, permissions policy, and what is off and why |
| Security review | How a change is read for security, and the register of trust boundaries already verified |
| UI library | The app's own UI library on Vuetify 0 — three layers, the import boundary, the component catalogue and the app shell |
| Page layout | From the route to the pixels — the layout a page picks, its drawers, the width and the height, and who draws each surface |
| Design language | How every interface is drawn — the palette tokens, the design styles, the surfaces, type, state, motion and the document chrome |
| Simplest reader first | Every surface written for the least technical reader — one way through, no plumbing, numbered steps in the words on screen |
| Context menus | One context menu for everything with actions of its own — right-click, long press or the keyboard, fed its overflow button's items |
| Nested interactions | A click lands on one thing — a link or control inside a clickable row acts alone, and user links open a new tab with no opener |
| Enforcement ladder | A rule that must hold everywhere is held by construction, then one primitive, then lint, then a test, and prose only when nothing above can |
| Command palette | One palette on Ctrl+K and one registry of commands — shortcuts bound while their surface is mounted, a surface's search as a scope |
| Schema forms | A form generated from a Zod schema — JSON Forms lays it out, the library draws it, the Zod schema validates it |
| Calendar | The date grid, the date field and the event calendar — plain days over the platform's Temporal, laid out after Outlook |
| Design sources | Where the look and behaviour are looked up — reference products, design systems, usability and accessibility references |
| Responsive layout | One breakpoint scale feeding both Vuetify 0's breakpoints and UnoCSS |
| Date and time display | Every rendered date is a NuxtTime — the reader's locale and timezone, no mismatch |
| Polyfills | A global a supported browser lacks — a deferred head script ahead of the bundle, one per global, each with its retirement |
| Section navigation | One scrollspy for every sidebar that tracks scrolled content, plus the rail that follows it |
| Third-party document adapters | A library holding the live document is handed a replacement — otherwise it writes the old one back |
Cross-cutting standards we decided against are recorded in rejected — check it before proposing a new one. Ones we chose not to build yet, each with a revisit trigger, are in deferred.
Shipped log
- UI library — every interface moved off Vuetify onto the app's own library over Vuetify 0's headless primitives, one product area at a time, and Vuetify, its Nuxt module and its UnoCSS preset left the repository with their configuration; what stayed is one theme system, one way to build a control, and a headless dependency only the library imports. → UI library
Scroll to top