Examples & reference landscapes
Example repositories demonstrating the Project-Stack-Resource (PSR) model in action.
Official reference repositories
Clone and run these complete TDK landscapes locally with a single command via the TDK CLI:
tdk project example # base reference stack tdk project user-management # enterprise governance demo tdk project erp # 100-service scale fixture tdk project restaurant # restaurant ops demo tdk project saas # SaaS dashboard + checkout starter
Each one clones straight into ./<name> (use --path <dir> to pick a different folder), so you're one cd and tdk up away from a running stack. Prefer plain git? Use the links below instead:
tdk-example
Minimal PSR demonstration: 1 project, 2 stacks (identity & appointment), and 4 resources using Hono, Vite, and Bun.
Clone on GitHub Enterprise governance demotdk-user-management
Enterprise identity governance: 3 stacks (admin, portal, compliance), 6 resources, SCIM 2.0 provisioning, OIDC PKCE, and SIEM workers.
Clone on GitHub Restaurant ops demotdk-restaurant-example
Restaurant operations landscape: 3 stacks (guest, kitchen, operations), 6 resources, live reservation flow, kitchen worker, menu API, and floor app.
Clone on GitHub Scale fixturetdk-erp-system
A scale fixture, not a business app: 100 small generated services across 7 ERP-style domains, each answering /health. Healthy through Traefik about 8 minutes after tdk up on a clean CI runner.
tdk-saas-starter
2 stacks (app, billing), 4 resources, a live account dashboard, and a checkout button wired to a real endpoint.
Clone on GitHubVue and managed-services examples
Two smaller repositories. One is the shortest path to a Vue frontend; the other runs an identity provider, a queue and email locally, the services that usually only exist in a cloud account.
tdk-ecommerce-example
A Vue 3 storefront with search, a cart and checkout, and a Hono catalog API that prices orders in integer cents and refuses to oversell. One stack, two resources, no database. Needs TDK 1.3.75 or newer.
Clone on GitHub Identity, queue and emailtdk-auth-queue-email-example
Sign in, request a report, and a worker emails you a CSV. An OIDC issuer stands in for Auth0 or Cognito, NATS JetStream for SQS (with retry on failure) and Mailpit for SES. Two stacks, four resources, plus NATS and Mailpit.
Clone on GitHubA Vue storefront
tdk resource storefront-web --type frontend --framework vue --stack store writes "framework": "vue" into the manifest. That one field makes TDK generate the Vue Vite config and a TypeScript config without React's JSX setting. Docker, nginx, Traefik and Tilt are shared with React frontends.
Managed services, run locally
Each managed service is an ordinary resource or container, and the app depends on an interface, not on a vendor. reports-api checks tokens against a JWKS URL, so pointing it at a real tenant is a params change. The Queue interface has a NATS implementation and redelivers a job when the worker fails. The Mailer sends SMTP into Mailpit, which shows what a recipient would get.
The stand-ins are not the real services: the emulator is not a security product (hard-coded users, no MFA or redirect flow), and JetStream differs from SQS in ordering and dead-letter behavior. The README lists what it does not do.
Restaurant operations landscape
The newest reference repo splits the host stand, kitchen pass, menu state, and floor control into independently runnable resources.
A restaurant stack that feels like a live service.
Run reservations, kitchen pacing, menu availability, and the floor view as separate TDK resources.
Reservation API manifest
{
"appName": "reservation-api",
"appType": "backend",
"stack": "guest",
"port": 4100,
"dependsOn": [],
"healthCheck": {
"enabled": true,
"path": "/health"
},
"features": []
}
100-service scale fixture (ERP-style)
A stress test for the PSR model: 100 small generated services named after ERP domains, each answering /health. It shows that discovery, image builds, routing and health checks keep working at this size. The services contain no real business logic.
100 small services. 7 domains. One command.
On a clean CI runner all 100 backends were healthy through Traefik in 472 s, images built from scratch. A weekly CI job repeats the boot (latest measured run).
General Ledger API manifest
{
"appName": "general-ledger-api",
"domain": "finance",
"appType": "backend",
"stack": "finance",
"port": 4010,
"apiPath": "/api/general-ledger",
"dependencies": [],
"healthCheck": {
"enabled": true,
"path": "/health"
}
}
Enterprise user management landscape
A multi-stack, zero-trust identity system featuring SCIM 2.0 provisioning, OAuth2/OIDC PKCE, and asynchronous background audit stream workers.
Admin directory API (SCIM 2.0)
{
"appName": "user-admin-api",
"appType": "backend",
"stack": "admin",
"port": 4010,
"dependsOn": [],
"healthCheck": {
"enabled": true,
"path": "/health"
},
"featuresEnabled": ["prisma"]
}
OAuth2 / OIDC self-service portal API
{
"appName": "user-portal-api",
"appType": "backend",
"stack": "portal",
"port": 4020,
"dependsOn": [],
"healthCheck": {
"enabled": true,
"path": "/health"
},
"featuresEnabled": ["prisma"]
}
Asynchronous audit & SIEM worker
{
"appName": "user-audit-worker",
"appType": "worker",
"stack": "compliance",
"port": 4031,
"dependsOn": ["user-audit-api"],
"healthCheck": {
"enabled": true,
"path": "/health"
},
"featuresEnabled": ["prisma"]
}
SaaS starter
Two stacks: app (account dashboard) and billing (checkout). The checkout page lists billing-api in dependsOn, so the API starts first and the frontend gets its URL without extra config.
{
"appName": "billing-api",
"appType": "backend",
"stack": "billing",
"port": 4210,
"featuresEnabled": ["prisma"],
"dependsOn": [],
"healthCheck": {
"enabled": true,
"path": "/health"
}
}
{
"appName": "checkout-app",
"appType": "frontend",
"stack": "billing",
"port": 3001,
"basePath": "/checkout-app",
"dependsOn": ["billing-api"],
"healthCheck": {
"enabled": true,
"path": "/"
}
}
Manifest patterns
These manifests aren't from a reference repo. They're short patterns that use only fields the engine reads. The configuration reference lists every field.
Frontend and backend
dependsOn starts catalog-api before the frontend and writes its URL into the frontend's generated env. basePath serves the app at /shop.
{
"appName": "web-app",
"appType": "frontend",
"stack": "storefront",
"port": 3000,
"basePath": "/shop",
"dependsOn": ["catalog-api"]
}
{
"appName": "catalog-api",
"appType": "backend",
"stack": "storefront",
"port": 4000,
"featuresEnabled": ["prisma"],
"dependsOn": []
}
Workers with replicas
replicas: 3 runs transcode-worker-1 to -3. The schema requires workers to enable nats. The workers list media-migrator in dependsOn, so the Prisma migrations run before any worker starts.
{
"appName": "transcode-worker",
"appType": "worker",
"stack": "media",
"port": 4300,
"featuresEnabled": ["nats", "redis"],
"dependsOn": ["media-migrator"],
"replicas": 3
}
{
"appName": "media-migrator",
"appType": "migrator",
"stack": "media",
"featuresEnabled": ["prisma"]
}
Realtime gateway
A websocket gateway on NATS and Redis. healthCheckPath overrides the default /health probe.
{
"appName": "realtime-gateway",
"appType": "backend",
"stack": "realtime",
"port": 4400,
"featuresEnabled": ["nats", "redis", "websocket"],
"dependsOn": [],
"healthCheckPath": "/healthz"
}
Start one stack
Pass a stack name to tdk up to start only that stack's resources. Add --dry-run to list them without starting anything.
tdk up media --dry-run # list what would start tdk up media # start the media stack only
Project layout
Every reference repo uses the same shape: one folder per stack, one folder per resource. Discovery reads services/*/*, the path set in .tdk/project.json.
my-project/ ├── .tdk/project.json # discovery paths, phases, optional infra └── services/ ├── storefront/ # stack │ ├── catalog-api/ # resource │ │ ├── service.json │ │ └── .autogenerated/ # Dockerfile, tsconfig, Vite config, AGENTS.md │ └── web-app/ │ └── service.json └── media/ ├── media-migrator/ │ └── service.json └── transcode-worker/ └── service.json
Brownfield rescue
An existing monorepo with 31 service folders and only 12 manifests. For every folder without a service.json, discovery builds a manifest from the folder's path, so all of them boot. The output below is illustrative.
$ tdk up [discovery] scanned 31 directories · 12 manifests found [synthesis] 19 manifests synthesized from structure [generate] local files for 31 discovered services [health] 31/31 resources healthy
Guidance for AI assistants
Each resource's .autogenerated/ folder gets an AGENTS.md that tells coding assistants the files there are generated and must be changed through service.json, not edited by hand. With the premium bundle, TDK also writes a C4 model of the running topology to .tilt/c4-model.json.
services/<stack>/<resource>/.autogenerated/AGENTS.md # don't-edit notice for assistants .tilt/c4-model.json # C4 model (premium)
All reference repositories
Browse them on GitHub: tdk-example (base PSR stack), tdk-user-management (enterprise governance demo with SCIM 2.0 and OIDC PKCE), tdk-restaurant-example (restaurant ops demo), tdk-erp-system (100-service scale fixture across 7 ERP-style domains), tdk-saas-starter (SaaS dashboard and checkout), tdk-ecommerce-example (Vue storefront) and tdk-auth-queue-email-example (identity, queue and email, all local).
Or skip the browser: tdk project example, tdk project user-management, tdk project restaurant, tdk project erp, or tdk project saas clones the first five from the CLI. The last two are a plain git clone away; then run tdk project and tdk up.