mockd is a local-first API response mock server for frontend and QA workflows.
Start here if this is your first time:
docs/first-time-user-guide.md
It provides:
- file-based route configuration (YAML/JSON)
- dynamic route matching with conditions and priority
- weighted responses with delay and error injection
- safe templating with null-prototype rendered objects to avoid prototype-pollution side effects
- optional request/response JSON Schema validation
- live request logs in terminal, REST, and WebSocket streams
- read-only dashboard at
/__mock__/
- Node.js 22.x (
.nvmrcis pinned to22) - pnpm 10+
pnpm installpnpm dev -- init --path ./mock.config.yaml
pnpm dev -- start --config ./mock.config.yaml --host 127.0.0.1 --port 43101Open:
- dashboard:
http://127.0.0.1:43101/__mock__/ - health:
http://127.0.0.1:43101/__mock__/health - request logs:
http://127.0.0.1:43101/__mock__/requests
mockd start prints:
- server URL
- effective mock base URL (includes
server.basePathwhen configured) - dashboard URL
Scenario:
- A frontend team is building checkout screens, but payment/order APIs are not ready yet.
- They need realistic API behavior now (success, latency, occasional failures).
Create or replace mock.config.yaml:
version: 1
server:
basePath: /api
routes:
- id: get-order
method: GET
path: /orders/:id
responses:
- status: 200
headers:
content-type: application/json
body:
id: "{{params.id}}"
amount: 1299
currency: INR
status: pending
- id: create-payment
method: POST
path: /payments
requestSchema:
type: object
additionalProperties: false
required: [orderId, method]
properties:
orderId:
type: string
method:
type: string
oneOf: [card, upi]
responses:
- status: 201
delayMs:
min: 200
max: 800
headers:
content-type: application/json
body:
paymentId: "pay-{{now}}"
orderId: "{{body.orderId}}"
status: processing
errors:
- probability: 0.2
status: 500
body:
error: temporary payment failure
- id: payment-status
method: GET
path: /payments/:id/status
responses:
- status: 200
headers:
content-type: application/json
body:
paymentId: "{{params.id}}"
status: completednode dist/cli/index.js start --config ./mock.config.yaml --host 127.0.0.1 --port 43101If your app already calls /api/*, route /api to http://127.0.0.1:43101.
Vite example:
import { defineConfig } from 'vite';
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://127.0.0.1:43101',
changeOrigin: false
}
}
}
});curl http://127.0.0.1:43101/api/orders/ord-1
curl -X POST http://127.0.0.1:43101/api/payments -H "content-type: application/json" -d '{"orderId":"ord-1","method":"upi"}'- Dashboard:
http://127.0.0.1:43101/__mock__/ - Request logs:
curl "http://127.0.0.1:43101/__mock__/requests?limit=20"
curl "http://127.0.0.1:43101/__mock__/requests?source=mock&limit=20"- Frontend can complete checkout UI before backend is delivered.
- QA can test both happy-path and failure-path behaviors immediately.
- Request/response schema catches invalid payload shapes early.
- Same config can be reused in local development, QA, and CI.
pnpm dev -- --help
pnpm dev -- init --path ./mock.config.yaml
pnpm dev -- start --config ./mock.config.yaml --host 127.0.0.1 --port 43101
pnpm dev -- routes --config ./mock.config.yaml
pnpm dev -- test GET '/users/1?includePosts=true' --headers 'x-env:dev' --config ./mock.config.yaml
pnpm dev -- test GET '/users/1' --query 'includePosts=true' --query 'debug=1' --headers 'x-env:dev' --headers 'x-mode:preview' --body '{"name":"Ada"}' --apply-delay --config ./mock.config.yamlCLI behavior:
--headersand--querysupport repeated flags.mockd testexits with error for no match or schema validation failures.mockd routesprints effective paths (includesserver.basePathwhen configured).- exit codes:
0: success1: runtime/config/validation failure2: invalid CLI arguments
GET /__mock__/health: service status and versionGET /__mock__/requests: latest request log events (ring buffer). Optional?limit=<n>returns the latestnevents and?source=<mock|built-in|no-match|error|unknown>filters by source.WS /__mock__/ws: live request streamGET /__mock__/: dashboard assets
WebSocket messages:
{ "type": "hello", "connectedAt": "..." }{ "type": "snapshot", "events": [...] }{ "type": "request-log", "event": {...} }
Minimum config:
version: 1
routes:
- id: get-user
method: GET
path: /users/:id
responses:
- status: 200Full reference: docs/config.reference.md
First-time onboarding: docs/first-time-user-guide.md
Application integration guide: docs/how-to-use-with-applications.md
How it works + benefits: docs/how-mockd-works-and-benefits.md
Recipe library: docs/recipes/README.md
Live showcase demo: docs/showcase-demo.md
server.basePath can prefix mock routes (for example /api) while built-in endpoints remain at /__mock__/....
Schema validation behavior:
requestSchemaviolations return400Problem Details witherrors.responseSchemaviolations return500Problem Details witherrors.- invalid route schemas fail fast during route compilation/startup.
- redacted request headers (default):
authorization,cookie,set-cookie,x-api-key server.redactHeadersis applied to request event logs and structured server loggingserver.redactHeadersmatching is case-insensitive; values are normalized to lowercase- request/response body preview truncation based on
server.maxBodyBytes - RFC 7807 Problem Details for built-in and mock runtime errors
- Fastify helmet security headers enabled
pnpm lint
pnpm test
pnpm buildGitHub Actions CI runs lint, test, and build on Node 22.
Workflow file: .github/workflows/ci.yml
Build image:
docker build -t mockd:local .Run container (mount config):
docker run --rm -p 43101:43101 -v "$(pwd)/mock.config.yaml:/app/mock.config.yaml:ro" mockd:localThe image entrypoint runs:
node dist/cli/index.js start --config /app/mock.config.yaml --host 0.0.0.0 --port 43101Docker Compose example (includes healthcheck and optional sample app integration):
docker compose up -d mockd
docker compose --profile example-app up -dSee: docs/how-to-use-with-applications.md
