Architecture decision records

ADR Decision Status
001 A module is a folder, not a class
A module is just a directory under app/ — no decorated class, no registration object.
accepted
002 No DI container; wiring is plain ES imports
Cross-module wiring is plain import statements; Bun's module system is the container.
accepted
003 Encapsulation = a public-API boundary check at build
A module may only be imported via its index.ts; deeper imports are build errors.
accepted
004 No decorators, no reflect-metadata
Handlers are plain functions in a routes map — no decorator machinery.
accepted
005 No new request lifecycle; reuse compose()
Module handlers run in the existing middleware chain; no new phases.
accepted
006 Validation, jobs, persistence stay libraries
Call Zod, an ORM, the job primitives directly — the framework doesn't wrap them.
accepted
007 Shared state has an explicit owner and a frozen mutation window
One owner, one mutation window, one freeze point per shared structure.
draft
008 The module dependency graph must be a DAG
Inter-module cycles are a hard build failure, detected by patties graph.
draft
009 What's out of scope, and what stays untouched
No DI, decorators, or scopes; the existing SSR/islands/UI surface is unaffected.
accepted

Open questions

① Route prefixing

Do module routes self-declare full paths (as shown), or does the build prefix them with the module name (/billing/...)? Self-declared is more flexible; auto-prefix is more enforced. Leaning self-declared, with collision detection at merge.

② Module root convention

Is the boundary rule scoped to app/*, or configurable for nested feature trees? How are path aliases (@billing) resolved by the check?

③ Packaging the boundary check

Is the check part of the build macro, a standalone patties CLI command, or also a Biome/lint rule for editor feedback? Likely the macro is the gate; a lint rule is a nice-to-have.

④ Relationship to patties' file routes

patties already has file-based routing for pages. Do module routes.ts maps coexist with that, or is this an alternate convention for API-first apps? (The "two front doors" question.)

Cross-cutting risks

Recorded here, not on the roadmap — these are standing concerns the design must hold to, each tied to a decision above.

Boundary check completeness

Resolving relative paths, path aliases, and re-export barrels correctly so the check (ADR-003) neither false-positives nor is trivially dodged. Scoped and tested as part of Epic 1.

Two front doors

patties would offer both file-based page routing and module routes.ts maps. The docs must make "use this for API-first / service-heavy apps" obvious, not confusing — see open question .

Route prefixing call

Self-declared full paths vs build-applied module prefixes — open question . Decide before the macro API is committed.

Staying thin

Pressure to grow this into DI / scopes / decorators. The whole value is that it doesn't — keep it convention + one macro (ADR-009).

Patties design specifications · a design exploration · User docs