One notes module, two callers

This workspace exists to prove one claim: a module whose rules depend on nothing but the framework's core runs unchanged wherever it is needed.

examples/reusable-notes/
├── notes-module/     the capability: model, rules, service, ports
├── apps/api/         an Axum REST application over it
└── apps/report/      a command-line job over it — no web server at all

The module knows nothing about HTTP, HTML, or a database. Applications choose a store and an adapter around it.

What it demonstrates

  • The contract is the seam. Notes and the repository port come from the module; the API and the CLI each depend on the module, never on each other.
  • Transport in the adapter only. Axum types appear in apps/api and nowhere else; the CLI needs no HTTP stack to reuse the same rules.
  • Validation once. CreateNote implements the framework's Validate trait, so REST input and CLI input are checked by the same code.

What to steal

  • Put the capability in its own crate with a small port surface, then write callers as thin adapters — the second caller costs almost nothing.
  • Keep the store behind a trait so tests run against the in-memory implementation while production picks a real one.