A sample project for demonstrating micro-contracts functionality.
- Node.js 18+
- npm
# Install dependencies
npm install
npm run install:all
# Start development servers (server + frontend)
npm run dev- Server: http://localhost:3001
- Frontend: http://localhost:5173
| Command | Description |
|---|---|
npm run dev |
Start server (3001) and frontend (5173) concurrently |
npm run server:dev |
Start server only |
npm run frontend:dev |
Start frontend only |
| Command | Description |
|---|---|
npm run generate |
Regenerate all code from OpenAPI spec |
| Command | Description |
|---|---|
npm run lint |
Run OpenAPI lint + TypeScript lint |
npm run lint:openapi |
Lint source OpenAPI spec (before generation) |
npm run lint:openapi:generated |
Lint generated OpenAPI spec (after generation) |
npm run lint:ts |
ESLint for TypeScript/TSX |
| Command | Description |
|---|---|
npm run build |
Full build (contract + server + frontend) |
npm run build:contract |
Type-check contract packages |
npm run build:server |
Build server |
npm run build:frontend |
Build frontend |
# Run all checks
npx micro-contracts check
# Run specific checks only
npx micro-contracts check --only lint,typecheck
# Skip specific checks
npx micro-contracts check --skip allowlistnpm run checkThis runs the following in sequence:
lint:openapi- Lint source OpenAPI specgenerate- Regenerate codelint:openapi:generated- Lint generated OpenAPI speclint:ts- TypeScript lintbuild- Full build
examples/
├── spec/ # OpenAPI specs & templates
│ ├── spectral.yaml # Global lint rules
│ ├── default/templates/ # Code generation templates (see below)
│ ├── _shared/
│ │ ├── openapi/ # Shared schemas
│ │ └── overlays/ # Cross-module overlays
│ ├── core/
│ │ ├── openapi/core.yaml # Core module spec
│ │ └── overlays/ # Module-specific overlays
│ └── billing/
│ ├── openapi/billing.yaml # Billing module spec
│ └── overlays/
├── packages/
│ ├── contract/ # Generated contract (internal)
│ └── contract-published/ # Generated contract (public API)
├── server/src/ # Server implementation
│ ├── core/
│ │ ├── domains/ # Domain implementations
│ │ ├── overlays/ # Overlay handlers
│ │ └── routes.generated.ts # Generated routes
│ └── billing/
├── frontend/src/ # Frontend implementation
│ ├── core/api.generated.ts # Generated API client
│ └── billing/api.generated.ts
├── micro-contracts.config.yaml # Generator configuration
└── micro-contracts.guardrails.yaml # AI guardrails configuration
The spec/default/templates/ directory contains Handlebars templates for generating code under server/ and frontend/.
| File | Generated File | Description |
|---|---|---|
fastify-routes.hbs |
server/src/{module}/routes.generated.ts |
Fastify route definitions. Generates HTTP endpoints from OpenAPI and dispatches to Domain methods |
fetch-client.hbs |
frontend/src/{module}/api.generated.ts |
Frontend HTTP client. Executes fetch with the same signature as Domain API |
overlay-adapter.hbs |
server/src/{module}/overlayAdapter.generated.ts |
Overlay execution runtime. Extracts overlay parameters from requests and executes handlers |
overlay-stubs.hbs |
(first time only) server/src/{module}/overlays.ts |
Skeleton implementation of overlay handlers. Used as initial implementation scaffold |
domain-stubs.hbs |
(first time only) server/src/{module}/domains/*.ts |
Skeleton implementation of Domain classes. Used as initial implementation scaffold |
| Target | Command | Description |
|---|---|---|
spec/default/templates/ |
micro-contracts init |
Creates initial Handlebars template files |
packages/contract/ |
micro-contracts generate |
Directly generates type definitions, validators, and Domain interfaces |
server/, frontend/ |
micro-contracts generate |
Generated from Handlebars templates. Customizable |
All templates are created by micro-contracts init.
# Initialize a new project
npx micro-contracts init
# The following are created:
# spec/default/templates/
# ├── fastify-routes.hbs
# ├── fetch-client.hbs
# ├── domain-stubs.hbs
# ├── overlay-adapter.hbs
# └── overlay-stubs.hbsTemplates can be customized for project-specific requirements:
- Module-specific templates: Place in
spec/{module}/templates/to apply only to that module - Default templates:
spec/default/templates/applies to all modules (fallback when no module-specific template exists)
spec/
├── default/templates/ # Common to all modules (fallback)
│ └── fastify-routes.hbs
└── billing/templates/ # billing module only (priority)
└── fastify-routes.hbs # billing-specific customization
The following variables are available in templates:
{{routes}}- Array of route information{{domains}}- Array of Domain information{{contractPackage}}- Path to contract package{{domainsPath}}- Path to Fastify's domains object{{extensionInfo}}- Overlay information- Other Handlebars helpers (
uppercase,camelCase,pascalCase,kebabCase,snakeCase,eq,if,each, etc.)
The following is an auto-generated list of APIs from OpenAPI spec.
| Module | Method | Path | Summary | Public | Middleware | Implementation |
|---|---|---|---|---|---|---|
| core | GET | /api/users | Get users list | ✅ | requireAuth | UserDomain.getUsers |
| core | POST | /api/users | Create new user | ✅ | requireAuth | UserDomain.createUser |
| core | GET | /api/users/{id} | Get user by ID | ✅ | requireAuth | UserDomain.getUserById |
| core | PUT | /api/users/{id} | Update user | requireAuth | UserDomain.updateUser | |
| core | DELETE | /api/users/{id} | Delete user | requireAuth, requireAdmin | UserDomain.deleteUser | |
| core | GET | /api/tenant/data | Get tenant-scoped data | requireAuth, tenantIsolation, rateLimit | TenantDomain.getData | |
| core | POST | /api/tenant/data | Create tenant data | requireAuth, tenantIsolation, rateLimit | TenantDomain.createData | |
| core | GET | /api/admin/stats | Get system statistics | requireAuth, requireAdmin | AdminDomain.getStats | |
| core | POST | /api/admin/users/{id}/suspend | Suspend user account | requireAuth, requireAdmin | AdminDomain.suspendUser | |
| core | GET | /api/health | Health check | ✅ | HealthDomain.check | |
| billing | GET | /api/billing/invoices | List all invoices | ✅ | requireAuth, tenantIsolation | Billing.getInvoices |
| billing | POST | /api/billing/invoices | Create a new invoice | ✅ | requireAuth, tenantIsolation | Billing.createInvoice |
| billing | GET | /api/billing/invoices/{id} | Get invoice by ID | ✅ | requireAuth, tenantIsolation | Billing.getInvoiceById |
| billing | POST | /api/billing/invoices/{id}/pay | Pay an invoice | ✅ | requireAuth, tenantIsolation | Billing.payInvoice |
The following cautions are defined in spec/_shared/overlays/middleware.overlay.yaml.
[WARNING]
Send the Authorization header in Bearer <token> format.
Accessing without a token returns 401 Unauthorized.
[CRITICAL]
Endpoints using tenantIsolation middleware require
the X-Tenant-Id header to be sent.
Missing header returns 400 Bad Request.
[INFO]
For endpoints with rateLimit middleware,
check the X-RateLimit-Remaining response header.
When limit is exceeded, 429 Too Many Requests is returned
with Retry-After header indicating retry time.
[WARNING]
Endpoints with requireAdmin middleware are accessible
only to users with admin role (role: admin).
Non-admin users receive 403 Forbidden.
The following is an excerpt from the actual overlay definition. The cautions above are synced from this definition.
# Cross-cutting concerns overlay
# Injects parameters and responses based on x-middleware markers
overlay: 1.0.0
info:
title: Middleware Extension Overlay
version: 1.0.0
description: |
This overlay injects cross-cutting concerns based on x-middleware markers:
- requireAuth: Adds Authorization header + 401 response
- requireAdmin: Adds 401 + 403 responses
- tenantIsolation: Adds X-Tenant-Id header + 400 response
- rateLimit: Adds X-RateLimit-Limit header + 429 response
# Cautions (implementation notes)
# This data is auto-synced to README.md via embedoc
x-micro-contracts-cautions:
- id: auth-token-format
severity: warning
title: "Auth Token Format"
message: |
Send the `Authorization` header in `Bearer <token>` format.
Accessing without a token returns 401 Unauthorized.
- id: tenant-isolation
severity: error
title: "Tenant Isolation Requirement"
message: |
Endpoints using `tenantIsolation` middleware require
the `X-Tenant-Id` header to be sent.
Missing header returns 400 Bad Request.
- id: rate-limit-handling
severity: info
title: "Rate Limit Handling"
message: |
For endpoints with `rateLimit` middleware,
check the `X-RateLimit-Remaining` response header.
When limit is exceeded, 429 Too Many Requests is returned
with `Retry-After` header indicating retry time.
- id: admin-endpoints
severity: warning
title: "Admin Endpoint Access Control"
message: |
Endpoints with `requireAdmin` middleware are accessible📄 Source: spec/_shared/overlays/middleware.overlay.yaml (lines 1-45)
# Health check
curl http://localhost:3001/api/health
# Users (requires auth)
curl -H "Authorization: Bearer test" http://localhost:3001/api/users
# Admin stats (requires admin auth)
curl -H "Authorization: Bearer admin" http://localhost:3001/api/admin/stats# Get invoices (requires auth + tenant)
curl -H "Authorization: Bearer test" -H "X-Tenant-Id: tenant-1" \
http://localhost:3001/api/billing/invoices
# Create invoice
curl -X POST -H "Authorization: Bearer test" -H "X-Tenant-Id: tenant-1" \
-H "Content-Type: application/json" \
-d '{"userId":"1","amount":99.99}' \
http://localhost:3001/api/billing/invoicesEdit spec/{module}/openapi/*.yaml
npm run lint:openapi # Lint spec
npm run generate # Generate code
npm run lint:openapi:generated # Lint generated spec- Server: Implement domain logic in
server/src/{module}/domains/ - Overlay: Implement overlay handlers in
server/src/{module}/overlays/
npm run lint:ts # TypeScript lint
npm run build # Build
npm run dev # Verify operation# Update README.md with embedoc
npx embedoc buildThis project uses embedoc to automatically sync information from OpenAPI spec and overlay files to README.md.
embedoc.config.yaml- embedoc configurationembeds/- Embed scripts
| Section | Source | Embed |
|---|---|---|
| API Endpoints | spec/*/openapi/*.yaml |
api_list |
| Middleware Cautions | spec/_shared/overlays/middleware.overlay.yaml |
overlay_cautions |
| Code Snippets | Any file | code_snippet |
# Update embedoc markers in README.md
npx embedoc build
# Verify changes
git diff README.mdMIT