Skip to content

Examples and Guidance

This page is the canonical guide to the runnable examples maintained in the repository. The source of truth is now the root examples/ directory, not docs/examples/ and not legacy one-file demos.

Recommended mental model: start from decorator-based business code, declare an entry method with @application, attach startup settings with @configure(...), then call main() directly.
See also: Getting Started, Build & Run, Parameter System Guide, Testing & Verification

  1. examples/minimal_app/ — the shortest public entrypoint
  2. examples/controller_service_inject/ — business layering with @service, @controller, and Inject()
  3. examples/middleware_and_module/ — when an explicit @module boundary is worth adding on top of the entry method
  4. examples/parameter_handling/ — controller-method parameter binding with Path, Query, and Body
  5. examples/testing_flow/ — testing through main.get_asgi_app() without a real server process

Example map

Example Teaches Run command Source
examples/minimal_app/ Minimal app structure with @application + @configure(...) + main() python -m examples.minimal_app View on GitHub
examples/controller_service_inject/ Service/controller split and type-led Inject() wiring python -m examples.controller_service_inject View on GitHub
examples/middleware_and_module/ Module boundary ownership and middleware pipeline extension python -m examples.middleware_and_module View on GitHub
examples/parameter_handling/ Path, Query, and Body on controller methods python -m examples.parameter_handling View on GitHub
examples/testing_flow/ Public-API test flow with ASGI dispatch python -m pytest examples/testing_flow/test_app.py -q View on GitHub
examples/static_files_and_spa/ Declarative StaticFiles mounts + SPA fallback (engine-neutral) python -m examples.static_files_and_spa View on GitHub

Why the examples were restructured

Older examples could accidentally push developers toward a manual app-registration mindset. The current example set intentionally keeps Cullinan's own concept front and center:

  • business-first decorators instead of explicit app wiring
  • an entry method as the default entrypoint
  • @module only when structure needs an explicit runtime boundary
  • Inject() as the default injection path when the type contract is clear
  • parameter binding on controller methods instead of raw request plumbing
  • testing via public APIs instead of internal bootstrap shortcuts

Notes

  • The root examples/README.md file mirrors this learning path for repository readers.
  • You can browse the tracked source set directly from examples/.
  • tests/integration/test_examples_public_guides.py smoke-tests the maintained examples.
  • If you are learning Cullinan for the first time, start with examples/minimal_app/ and then continue to examples/controller_service_inject/.