Skip to content

Project Anatomy

A Routa project has a clean split: files under src/ are yours to write, and files under .routa/ are derived from them. Knowing which side a file is on tells you whether to edit it, review it, or regenerate it.

Routa reads your source, validates it, and writes what it learned into .routa/. Nothing flows the other way — .routa/ never changes your source. That is why generated files are safe to delete and regenerate, and why they still belong in version control: they let checks, the runtime, and CI agree on the contract without re-deriving it.

  • Directorysrc/
    • routa.ts application configuration, required
    • Directoryroutes/
      • middleware.ts optional, applies to everything below
      • Directorystatus/
        • route.ts
        • schemas.ts
        • route.test.ts
  • Directory.routa/
    • routes.gen.ts
    • manifest.json
    • openapi-baseline.json
  • openapi.yaml
  • package.json
  • tsconfig.json
  • biome.json

The application configuration, exported as a default createRouta() call. It sets the host, port, logger, and lifecycle-header behavior. Routa treats a missing src/routa.ts as a fatal project error, so the file must exist even when it sets no options.

One file per URL path, owning every HTTP method for that path. The directory structure maps to URL segments. See Routing for the full set of file naming conventions.

Zod schemas for the routes beside them. Routa treats schemas.ts as a schema module rather than a route, and it checks that exported schema names are unique across the project so generated OpenAPI component names never collide.

Middleware that applies to every route in that folder and below. A middleware.ts at src/routes/ covers the whole API; one at src/routes/admin/ covers only that subtree.

Generated route metadata: paths, methods, middleware chains, provided context keys, reject outcomes, groups, and segments. It also augments core types so createRouteRoot("/users") knows the context available at that path.

A record of every file Routa generated, with its source operation ID, kind, and content hash. Scaffolding compares against this to tell whether regenerating a file would be an update, a no-op, a conflict with your edits, or a removal.

The accepted OpenAPI contract. routa openapi check compares the current generated document against it to detect drift, and routa openapi breaking uses it to detect removed operations and newly required inputs.

Present when you scaffold from a contract. It is a source document you own, not a generated one; Routa reads it during routa scaffold and never writes to it.

  • check, generate, and build write generated metadata only inside .routa/. dev may also stub empty route files under src/. create-routa-ts and routa scaffold intentionally create source files.
  • Validation runs before generation. A failing check leaves the previous metadata in place rather than writing a half-valid file.
  • Generated metadata is deterministic. The same source produces byte-identical output, so a .routa/ diff always means a real contract change.

Services, use cases, domain models, persistence, authentication logic, authorization rules, and configuration all live in your application. Routa has no opinion about where you put them; the examples use src/services/ and src/middleware/ only as a convention.