Stitch route definitions
server:
openapi: src/server/stitch.yaml
client:
openapi: src/ui/stitch.yamlApp route definition paths can point to a Stitch file. Stitch is the YAML composition layer: it keeps route definitions split across focused files, then merges them into the single document that Dinner or Forge reads.
Stitch Settings
- server.openapi
- Backend route definition path. App passes the resolved document to Dinner for API route registration.
- client.openapi
- Frontend route definition path. App passes the resolved document to Forge for page, layout, and controller discovery.
server.openapi
server.openapi points to the backend Stitch file. A Stitch file has one top-level stitch array; each entry is a YAML file or glob pattern merged into the final backend route definition document.
stitch:
- openapi/base.yaml
- openapi/modules/**/*.yaml
- openapi/components/**/*.yamlserver.openapi file split
Split backend route YAML by feature area. The feature file should own its module, base path, operations, controller names, and actions. Shared schemas and shared responses belong under components.
src/server/
stitch.yaml
openapi/
base.yaml
modules/
users.yaml
billing.yaml
admin.yaml
health.yaml
components/
schemas/
user.yaml
invoice.yaml
responses/
errors.yaml
controller/
users.controller.ts
billing.controller.ts- base.yaml
- Shared OpenAPI metadata and API-wide middleware. Keep global concerns here.
- modules/users.yaml
- User routes such as list, create, profile, and detail endpoints.
- modules/billing.yaml
- Billing routes such as checkout, invoices, plans, and subscription updates.
- modules/admin.yaml
- Admin-only API routes. Keep privileged endpoints grouped together.
- components/schemas/*.yaml
- Reusable request and response schemas referenced by feature modules.
- components/responses/*.yaml
- Shared response shapes such as validation errors and unauthorized errors.
server.openapi base file
Put shared document metadata and API-wide middleware in the backend base file. Feature modules merge into this document after the base file.
openapi: 3.0.0
info:
title: Example API
version: 1.0.0
paths:
x-middleware:
- api.authserver.openapi feature module
A backend feature module groups related API routes under one basePath. Here, / becomes /api/users/, and /{id} becomes /api/users/{id}.
module:
users:
basePath: /api/users
paths:
/:
get:
x-controller: users.controller
x-action: list
summary: List users
/{id}:
get:
x-controller: users.controller
x-action: get
summary: Get one userserver.controllers
Dinner resolves backend x-controller relative to server.controllers. With server.controllers: src/server/controller, x-controller: users.controller loads src/server/controller/users.controller.ts, then x-action calls the matching method.
import { Component, LoadAs } from "@noego/ioc";
import type { Request, Response } from "express";
type ControllerArgs = {
req: Request;
res: Response;
};
@Component({ scope: LoadAs.Scoped })
export default class UsersController {
async list({ res }: ControllerArgs) {
return res.json([{ id: "1", name: "Ada Lovelace" }]);
}
async get({ req, res }: ControllerArgs) {
return res.json({ id: req.params.id, name: "Ada Lovelace" });
}
}Controller resolution rules
Dinner resolves x-controller relative to server.controllers. The value is treated as a relative file path without extension. Dinner first appends .js and falls back to .ts. Nested folders are valid — use forward slashes in the YAML value exactly as they appear on disk.
| server.controllers | x-controller | Resolved file |
|---|---|---|
| src/server/controller | users.controller | src/server/controller/users.controller.ts |
| src/server/controller | admin/users.controller | src/server/controller/admin/users.controller.ts |
| src/server/controller | billing/invoice.controller | src/server/controller/billing/invoice.controller.ts |
| dist/server/controller | health.controller | dist/server/controller/health.controller.js |
When a project grows, controllers are usually grouped by domain. Keep the folder structure inside server.controllers flat or nested however you prefer — just reference the correct relative path in x-controller.
module:
admin:
basePath: /api/admin
paths:
/users:
get:
x-controller: admin/users.controller
x-action: list
summary: List admin users
/users/{id}:
get:
x-controller: admin/users.controller
x-action: get
summary: Get one admin userclient.openapi
client.openapi points to the frontend Stitch file. Forge reads the merged route definitions to discover pages, layouts, loaders, and controllers.
stitch:
- openapi/base.yaml
- openapi/pages/**/*.yaml
- openapi/components/**/*.yamlclient.openapi file split
Split frontend route YAML by product area. Frontend route files should name the page view, layout stack, and optional page controller for that area.
src/ui/
stitch.yaml
openapi/
base.yaml
pages/
public.yaml
dashboard.yaml
settings.yaml
admin.yaml
layout/
public.svelte
app.svelte
pages/
landing/main.svelte
dashboard/main.svelte
settings/main.svelte
controllers/
settings_controller.svelte.ts- base.yaml
- Shared UI route metadata and fallback view.
- pages/public.yaml
- Public pages such as landing, docs, pricing, login, and signup.
- pages/dashboard.yaml
- Authenticated product pages that share the app layout.
- pages/settings.yaml
- Settings pages and their page controllers.
- pages/admin.yaml
- Admin UI routes and their admin layout stack.
client.openapi base file
Put shared UI route metadata in the frontend base file. The fallback view is used when Forge cannot match a frontend route.
openapi: 3.0.0
info:
title: Example UI
version: 1.0.0
x-fallback-view: error/404.svelteclient.openapi page routes
Forge resolves x-view, x-layout, and frontend x-controller relative to client.componentDir. If client.componentDir is src/ui, these paths point into src/ui/pages, src/ui/layout, and src/ui/controllers.
paths:
/settings:
get:
summary: Settings page
x-view: pages/settings/main.svelte
x-layout:
- layout/app.svelte
x-controller: controllers/settings_controller.svelte.tsMerge Rules
- paths
- Entries are resolved relative to the Stitch file, not the project root.
- order
- Files merge in list order. Glob matches are sorted before they are merged.
- objects
- Objects deep-merge, so separate files can contribute different keys to the same document.
- overrides
- Later values override earlier values for the same key. Arrays are replaced rather than concatenated.
Who interprets each field
- stitch
- Read by Stitch. Lists YAML files and globs to merge.
- module.*.basePath
- Read by Dinner and Forge. Prefixes every route in that module.
- paths
- Read by Dinner and Forge. Defines route paths and HTTP operations.
- x-controller + x-action
- Backend: Dinner resolves a controller class and calls the named method.
- x-view
- Frontend: Forge resolves the Svelte view relative to client.componentDir.
- x-layout
- Frontend: Forge renders layouts outside-in before rendering the view.
- x-controller
- Frontend: Forge may resolve an optional page controller relative to client.componentDir.
- x-middleware
- Backend route middleware is resolved by Dinner. See the Dinner middleware guide for implementation details.
Who Uses The Result
- App
- Resolves the configured route definition path from noego.config.yml.
- Stitch
- Merges the listed YAML files into one route definition document.
- Dinner
- Processes backend modules, base paths, controllers, actions, validation, and route middleware.
- Forge
- Processes frontend route definition metadata such as views, layouts, and page controllers.