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).

PageWhat it covers
Write onceA mechanism written once over the description every case already has — a new case is one declaration, never a change to it
Cross-product layer modelHow the products link together — identity, resources, datasets, publishing, events
ResourcesThe standard for product persistence and surface — resource model, capabilities, factory
DatasetsThe standard for serving tabular data — contract, DatasetProvider capability, row cap
PublishingThe Publishable capability — versioned publish copy + rate-limited public read
Authbetter-auth OAuth setup, session middleware, and the authed procedure chain
Agent accessOne MCP endpoint over an API key, serving every tRPC procedure whose meta opts in
Azure servicesAzure service ownership, the storage split, event flows, and the real-time layer model
EnvironmentEnvironment detection across the three Nuxt runtime contexts
File uploadsThe two-step Azure Blob SAS upload pattern and upload procedure inventory
Large documentsPast one request body a document moves between browser and Blob Storage; the server validates, and carries one only to sync a save
SerializationHow class instances survive the three transport paths (Azure Table, Nuxt payload, tRPC)
Compressionzstd for every format we own — a foreign format keeps its counterparty's codec
Compressed JSON blobsEvery JSON blob stored as a zstd frame served with Content-Encoding: zstd, through one writer and one reader
Client data accessThe useQuery + useMutation primitives — non-blocking fetch, optimistic apply, staleness
Async operationsConcurrency by declaration — reads are latest-wins, writes queue, nothing drops silently
CachingOne cached-read primitive, invalidated by tag when a write says what it changed
Persisted data — latest shape onlyNo legacy-shape schemas or migration code — parse the latest shape or reset
No compatibility debtA wrong name, shape or deployed identity is corrected in place — never aliased
Content token rewritingFinding tokens in authored content — self-delimiting matches, one pass, converge on read
Monorepo toolingpnpm workspace orchestration, virrun routing, publishing, installs, and CI job shape
Build pipelineOne bundler, shared build presets, and an external list derived from each manifest
Nuxt module packagesA workspace package that is a Nuxt module — its entry loaded from source at configuration time, its runtime built unbundled, fixture-app tests
Agent configurationThe vendor-neutral .agents tree, its .claude alias, and what stays out of the docs
Engineering loopsHow work moves — the product, change, code-health and knowledge loops, where work enters, and what runs next
Server testingtRPC router test wiring — in-memory DB, mocked Azure services, controlled auth session
Test harness workaroundsEvery shim the suite carries for a runner gap, the probe that retires it, and what its removal deletes
Lint toolchainOxlint as the one repo-wide pass, ESLint behind it for what oxlint cannot parse, and the blocker table a bump reads
Third-party reachabilityWhether a third party works for a reader is asked of their network, never guessed from language or place
Dependency admissionWhat a third-party package must earn to stay — the three real costs, the admission test, the stop list
Dialog shellOne dialog shell — StyledDialog owns the card, the body slot and the actions row
Destructive confirmationOne shared delete dialog for what cannot be undone — UiConfirmDialog, the answer it owns, the type-the-name guard
Singleton dialogsStore-driven singleton dialogs — one mounted dialog per feature, never one per list item
NavigationNuxtLink/navigateTo for every link — never a raw anchor — and instant docs routing
Persist then notifyGuard, persist, notify — then best-effort bookkeeping that can never fail the caller
NotificationsOne typed event, one Function, fanned out to the surfaces its type declares
Conditional writesA write derived from a read is conditional on that version, and a lost race re-applies
Blob lifecycle ownershipEvery blob prefix's naming discipline and single teardown owner per lifecycle event
No pollingPolling banned repo-wide — every wait is event-driven or awaits a completion handle
No manual recoveryFailed async work retries itself on an event, with an attempt cap and a quarantine
Null vs undefinedOne absent-value sentinel in app-owned code — null survives only in boundary shapes
Module boundariesThe app's three import zones — shared/ may never reach into the client-only app tree
Generated artifactsA 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 executionWhere app/ runs — persisted state, a client-only phase, and the one use left for checkIsServer
SearchOne search stack — command palette scopes + useAutoSearch/useCursorSearcher
Rate limitingPostgres-backed budgets shared across instances, enforced in the authed middleware
Security postureThe app's nuxt-security configuration — CSP, permissions policy, and what is off and why
Security reviewHow a change is read for security, and the register of trust boundaries already verified
UI libraryThe app's own UI library on Vuetify 0 — three layers, the import boundary, the component catalogue and the app shell
Page layoutFrom the route to the pixels — the layout a page picks, its drawers, the width and the height, and who draws each surface
Design languageHow every interface is drawn — the palette tokens, the design styles, the surfaces, type, state, motion and the document chrome
Simplest reader firstEvery surface written for the least technical reader — one way through, no plumbing, numbered steps in the words on screen
Context menusOne context menu for everything with actions of its own — right-click, long press or the keyboard, fed its overflow button's items
Nested interactionsA 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 ladderA 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 paletteOne palette on Ctrl+K and one registry of commands — shortcuts bound while their surface is mounted, a surface's search as a scope
Schema formsA form generated from a Zod schema — JSON Forms lays it out, the library draws it, the Zod schema validates it
CalendarThe date grid, the date field and the event calendar — plain days over the platform's Temporal, laid out after Outlook
Design sourcesWhere the look and behaviour are looked up — reference products, design systems, usability and accessibility references
Responsive layoutOne breakpoint scale feeding both Vuetify 0's breakpoints and UnoCSS
Date and time displayEvery rendered date is a NuxtTime — the reader's locale and timezone, no mismatch
PolyfillsA global a supported browser lacks — a deferred head script ahead of the bundle, one per global, each with its retirement
Section navigationOne scrollspy for every sidebar that tracks scrolled content, plus the rail that follows it
Third-party document adaptersA 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

Details

Command palette

Keyboard shortcuts