Architecture

Every request walks the same path: the adapter never sees SQL, and the implementation never sees HTML.

  1. 01clientBrowser formNative POST, works without JS
  2. 02adaptertask-adapter-htmxParse input, map errors to status codes
  3. 03contracttask-contractTasks trait: list and change
  4. 04implementationtask-impl-timescaleService rules over the typed repository
  5. 05databaseTimescaleDBScoped to the authenticated identity

The slices

Two slices — project and task — repeat the same triad, and one composition root selects the concrete pieces:

examples/htmx-starter/
crates/project-contract/contractProject, rules, Projects, ProjectRepository
crates/project-impl-timescale/implementationProject service and SQL repository
crates/project-adapter-htmx/adapterPages, forms, handlers
crates/task-contract/contractTask, TaskChange, rules, Tasks, TaskRepository
crates/task-impl-timescale/implementationTaskService and SQL repository
crates/task-adapter-htmx/adapterRoutes, pages, forms
servers/web/compositionSelects the concrete implementations and adapters

Dependencies point inward

The adapters depend on their contracts only; the implementations depend on the same contracts; neither depends on the other. servers/web is the only crate that names everything.