Unified container for running WireMock or Mockoon CLI, both sharing the same mock structure. Includes a control panel (API + Dashboard) for managing mocks, projects, recordings, logs, and database snapshots visually.
- Node.js 24
- npm 10+
- Docker (optional, for mock engines and database containers)
- PostgreSQL client tools (
pg_dump,psql) if you want real PostgreSQL snapshot/restore
graph LR
subgraph "π¦ Monorepo (npm workspaces)"
Shared["@stubrix/shared\n(TypeScript types)"]
API["@stubrix/api\n(NestJS 11)"]
DBUI["@stubrix/db-ui\n(Database microfrontend)"]
UI["@stubrix/ui\n(React 19 + Vite)"]
end
subgraph "π³ Docker Container"
EP["Entrypoint"]
EP -->|"MOCK_ENGINE=wiremock"| WM["WireMock\n(Java)"]
EP -->|"MOCK_ENGINE=mockoon"| MK["Mockoon CLI\n(Node.js)"]
CV["Converter"] -.->|"auto-converts\non startup"| MK
end
subgraph "πΎ Shared Mock Structure"
MP["mappings/*.json"]
FF["__files/*"]
end
UI -->|"consumes db-ui"| DBUI
UI -->|"fetch /api/*"| API
UI -->|"WebSocket /ws/logs"| API
DBUI -->|"fetch /api/db + /api/projects/*/databases/configs"| API
API -->|"HTTP /__admin/*"| WM
Shared -->|"types"| API
Shared -->|"types"| DBUI
Shared -->|"types"| UI
API -->|"fs read/write"| MP
WM <-->|"reads/writes"| MP
CV <-->|"reads"| MP
style Shared fill:#6366f1,color:#fff,stroke:#4f46e5
style API fill:#e0234e,color:#fff,stroke:#be123c
style DBUI fill:#7c3aed,color:#fff,stroke:#6d28d9
style UI fill:#61dafb,color:#1a1a2e,stroke:#38bdf8
style WM fill:#2d6a4f,color:#fff,stroke:#40916c
style MK fill:#e76f51,color:#fff,stroke:#f4a261
style CV fill:#457b9d,color:#fff,stroke:#1d3557
style EP fill:#6c757d,color:#fff,stroke:#495057
style MP fill:#264653,color:#e6e6e6,stroke:#2a9d8f
style FF fill:#264653,color:#e6e6e6,stroke:#2a9d8f
Canonical format is WireMock (
mappings/+__files/) β the simplest and most universal. When Mockoon is activated, the converter automatically generates the native format from mappings.
stubrix/
βββ packages/
β βββ shared/ Shared TypeScript types (@stubrix/shared)
β β βββ src/types/ Project, Mock, Log, Recording, Status
β βββ api/ NestJS control plane backend (@stubrix/api)
β β βββ src/
β β βββ projects/ Project CRUD + JSON persistence
β β βββ mocks/ Mock CRUD + WireMock integration
β β βββ recording/ Start/stop/snapshot recording
β β βββ logs/ REST + WebSocket (Socket.IO)
β β βββ status/ Engine health + mock counts
β β βββ engine/ WireMock reset + status
β β βββ databases/ Engines, database info, snapshots, project configs
β βββ db-ui/ Database microfrontend (@stubrix/db-ui)
β β βββ src/
β β βββ components/ Database widgets and forms
β β βββ hooks/ Database state and project context
β β βββ lib/ Database API client
β β βββ pages/ Databases page
β βββ ui/ React dashboard (@stubrix/ui)
β βββ src/
β βββ pages/ Dashboard, Projects, Mocks, Recording, Logs, Databases
β βββ components/ Layout, Badge, shared UI
β βββ lib/ API client, WebSocket client, utils
β
βββ mocks/ Canonical mock structure
β βββ mappings/ Route definitions (JSON)
β βββ __files/ Response body files
βββ dumps/ Snapshot output and database metadata
β βββ postgres/
β βββ mysql/
β βββ sqlite/
β βββ .snapshot-metadata.json
β βββ .project-databases.json
β
βββ scripts/
β βββ converter.js WireMock <-> Mockoon converter
β βββ entrypoint.sh Smart Docker entrypoint
β βββ record.sh Recording helper (Admin API)
β βββ import-from-recording.sh Import mocks from container
β
βββ Dockerfile Multi-engine Docker image
βββ docker-compose.yml 4 profiles available
βββ Makefile CLI shortcuts for everything
βββ .env.example Environment variable reference
The control panel provides a visual interface for managing the entire mock lifecycle β no manual JSON editing or curl commands required.
graph TD
subgraph "π₯οΈ Dashboard UI"
PP["π Projects\n(list + create)"]
DP["π Dashboard\n(stats + quick actions)"]
MP["π Mocks\n(list + search + delete)"]
ME["βοΈ Mock Editor\n(create/edit form)"]
RP["π₯ Recording\n(start/stop controls)"]
DBP["ποΈ Databases\n(project configs + snapshots)"]
LP["π Logs\n(real-time table)"]
end
subgraph "βοΈ API Endpoints"
P["/api/projects"]
M["/api/projects/:id/mocks"]
R["/api/projects/:id/recording"]
DBC["/api/projects/:id/databases/configs"]
DB["/api/db/*"]
L["/api/logs"]
S["/api/status"]
E["/api/engine"]
WS["/ws/logs (WebSocket)"]
end
PP -->|"click project"| DP
DP -->|"View Mocks"| MP
DP -->|"Record"| RP
DP -->|"Manage Databases"| DBP
MP -->|"New/Edit"| ME
LP -.->|"Socket.IO"| WS
PP --> P
MP --> M
ME --> M
RP --> R
DBP --> DBC
DBP --> DB
LP --> L
DP --> S
style PP fill:#6366f1,color:#fff,stroke:#4f46e5
style DP fill:#6366f1,color:#fff,stroke:#4f46e5
style MP fill:#6366f1,color:#fff,stroke:#4f46e5
style ME fill:#6366f1,color:#fff,stroke:#4f46e5
style RP fill:#6366f1,color:#fff,stroke:#4f46e5
style DBP fill:#7c3aed,color:#fff,stroke:#6d28d9
style LP fill:#6366f1,color:#fff,stroke:#4f46e5
| Layer | Technology |
|---|---|
| API | NestJS 11 + Express, WebSockets (Socket.IO) |
| UI | React 19 + Vite, TailwindCSS, Lucide icons, React Router |
| Shared | TypeScript lib consumed by both API and UI |
| Validation | class-validator + class-transformer with nested DTOs |
# Use the project Node version
asdf install
asdf current
# Install dependencies (from project root)
npm install
# Build everything
npm run build
# Start API (port 9090)
npm run dev:api
# Start UI dev server (port 5173, proxies to API)
npm run dev:uiThe UI dev server proxies
/api/*and/ws/*to the API atlocalhost:9090. In production, the UI builds directly intopackages/api/public/for single-container serving.
cp .env.example .envEdit as needed:
# Mock server port (host + container)
MOCK_PORT=8081
# Real API URL (for recording/proxy)
PROXY_TARGET=https://api.example.com
# CORS allowed origins (comma-separated, or * for all)
CORS_ORIGIN=*
# PostgreSQL
PG_HOST=localhost
PG_PORT=5442
PG_USER=postgres
PG_PASSWORD=postgres
PG_DATABASE=postgres
# MySQL
MYSQL_HOST=localhost
MYSQL_PORT=3307
MYSQL_USER=stubrix
MYSQL_PASSWORD=stubrix
MYSQL_DATABASE=stubrix
# SQLite (optional)
SQLITE_DB_PATH=
# Snapshot directory
DUMPS_DIR=./dumpsThe
.envfile is automatically loaded byMakefile,docker-compose, and scripts.
make buildmake wiremock # or
make mockooncurl http://localhost:8081/api/health
# β {"status": "ok", "engine": "mock-server"}To change the port without editing
.env:MOCK_PORT=9090 make wiremock
The Databases Module is now part of the main NestJS API and exposed in the dashboard through the @stubrix/db-ui microfrontend.
graph LR
User["π€ User"] --> UI["π₯οΈ Databases Page\n@stubrix/ui + @stubrix/db-ui"]
subgraph "Project Context"
Project["Active Project"]
Configs["Project DB Configs\n.project-databases.json"]
Meta["Snapshot Metadata\n.snapshot-metadata.json"]
end
subgraph "API"
ProjectRoutes["/api/projects/:projectId/databases/configs"]
DbRoutes["/api/db/*"]
end
subgraph "Engines"
PG["PostgreSQL"]
MY["MySQL"]
SQ["SQLite"]
end
UI --> Project
UI --> ProjectRoutes
UI --> DbRoutes
ProjectRoutes --> Configs
DbRoutes --> Meta
DbRoutes --> PG
DbRoutes --> MY
DbRoutes --> SQ
style UI fill:#7c3aed,color:#fff,stroke:#6d28d9
style Project fill:#0f766e,color:#fff,stroke:#115e59
style Configs fill:#1d4ed8,color:#fff,stroke:#1e40af
style Meta fill:#1d4ed8,color:#fff,stroke:#1e40af
style PG fill:#2563eb,color:#fff,stroke:#1d4ed8
style MY fill:#ea580c,color:#fff,stroke:#c2410c
style SQ fill:#475569,color:#fff,stroke:#334155
- Multi-engine discovery:
- PostgreSQL
- MySQL
- SQLite
- Project-scoped database configurations
- Project-scoped snapshot metadata
- Database inspection by engine and project
- Snapshot creation and restore
| Engine | List / Info | Snapshot | Restore |
|---|---|---|---|
| PostgreSQL | Real | Real (pg_dump) |
Real (psql) |
| MySQL | Real | Placeholder | Placeholder |
| SQLite | Real | Placeholder | Placeholder |
Database state is persisted in the dumps/ directory:
dumps/.project-databases.json- project-scoped database configurations
dumps/.snapshot-metadata.json- snapshot metadata including
projectId
- snapshot metadata including
dumps/postgres/,dumps/mysql/,dumps/sqlite/- generated snapshot files
GET /api/projects/:projectId/databases/configsGET /api/projects/:projectId/databases/configs/:idPOST /api/projects/:projectId/databases/configsDELETE /api/projects/:projectId/databases/configs/:id
GET /api/db/enginesGET /api/db/databases?projectId=...GET /api/db/engines/:engine/databases?projectId=...GET /api/db/databases/:name/info?projectId=...GET /api/db/engines/:engine/databases/:name/info?projectId=...
GET /api/db/snapshots?projectId=...POST /api/db/snapshotsPOST /api/db/engines/:engine/snapshotsPATCH /api/db/snapshots/:nameDELETE /api/db/snapshots/:namePOST /api/db/snapshots/:name/restorePOST /api/db/engines/:engine/snapshots/:name/restore
- The dashboard selects an active project.
- Project database configs are loaded from
/api/projects/:projectId/databases/configs. - Database listing and inspection send
projectIdto/api/db/*routes. - Snapshot creation includes
projectIdin metadata. - Snapshot listing is filtered by
projectId.
sequenceDiagram
participant U as User
participant UI as Databases UI
participant API as NestJS API
participant CFG as Project Config Store
participant ENG as Database Engine
U->>UI: Select active project
UI->>API: GET /api/projects/:projectId/databases/configs
API->>CFG: Read project configs
CFG-->>API: Config list
API-->>UI: Preferred engine/database
U->>UI: Inspect databases
UI->>API: GET /api/db/engines/:engine/databases?projectId=...
API->>ENG: Resolve driver + project context
ENG-->>API: Databases / info
API-->>UI: Project-aware result
- Open the dashboard and go to
Databases. - Select the active project.
- Create a database config for that project.
- Inspect available databases for the selected engine.
- Create snapshots in the context of the active project.
- Restore PostgreSQL snapshots when needed.
To use real PostgreSQL dump/restore, your environment must provide:
pg_dumppsql
The module uses the following variables:
PG_HOSTPG_PORTPG_USERPG_PASSWORDPG_DATABASE
sequenceDiagram
participant U as User
participant UI as Databases UI
participant API as DbSnapshotsService
participant PGD as pg_dump
participant PSQL as psql
participant FS as dumps/postgres
U->>UI: Create snapshot
UI->>API: POST /api/db/engines/postgres/snapshots
API->>PGD: pg_dump --clean --if-exists --file <snapshot.sql> <database>
PGD-->>API: SQL dump generated
API->>FS: Persist snapshot file + metadata
API-->>UI: Snapshot created
U->>UI: Restore snapshot
UI->>API: POST /api/db/engines/postgres/snapshots/:name/restore
API->>PSQL: psql --file <snapshot.sql> <database>
PSQL-->>API: Restore completed
API-->>UI: Restore finished
# 1. install dependencies
npm install
# 2. build all packages
npm run build
# 3. start the API
npm run dev:api
# 4. start the UI
npm run dev:uiThen in the UI:
- Create or select a project.
- Open
Databases. - Add a PostgreSQL config for the project.
- Create a snapshot.
- Confirm the dump file exists in
dumps/postgres/. - Restore the snapshot to a valid PostgreSQL database.
The most important feature. Allows creating mocks automatically from a real API.
sequenceDiagram
participant App as Your App / Browser
participant WM as Mock Server<br/>(localhost:8081)
participant API as Real API<br/>(api.example.com)
Note over WM: RECORD mode active
App->>WM: GET /api/users
WM->>API: GET /api/users (proxy)
API-->>WM: 200 OK [{...}]
WM-->>App: 200 OK [{...}]
Note over WM: Auto-saves:<br/>mappings/api_users_get.json<br/>__files/body-api_users.json
App->>WM: POST /api/orders
WM->>API: POST /api/orders (proxy)
API-->>WM: 201 Created {...}
WM-->>App: 201 Created {...}
Note over WM: Auto-saves:<br/>mappings/api_orders_post.json
Note over App,API: After stopping recording,<br/>mocks work fully offline
Everything passing through the proxy is recorded automatically.
# 1. Start in recording mode pointing to the real API
make wiremock-record PROXY_TARGET=https://api.example.com
# 2. Make requests normally
curl http://localhost:8081/api/users
curl http://localhost:8081/api/products/42
curl -X POST http://localhost:8081/api/orders -d '{"item":"abc"}'
# 3. Stop the container
make down
# 4. Done! Mocks saved in mocks/mappings/
make list-mappingsStart/stop recording on demand without restarting the container.
# 1. Start WireMock normally
make wiremock
# 2. In another terminal, start recording
./scripts/record.sh start https://api.example.com
# 3. Make your calls
curl http://localhost:8081/api/users
curl http://localhost:8081/api/config
# 4. Stop recording (mocks are persisted)
./scripts/record.sh stop
# 5. Check recorded mocks
make list-mappingsCaptures the current state of all responses without continuous recording.
./scripts/record.sh snapshotUse the dashboard UI to manage recordings visually:
- Open
http://localhost:5173(dev) orhttp://localhost:9090(production) - Navigate to a project β Recording
- Enter the proxy target URL and click Start Recording
- Make requests against
localhost:8081 - Click Stop or Snapshot to persist mocks
graph TD
A["1 - Start recording"] --> B["2 - Make requests<br/>against real API"]
B --> C["3 - Stop recording"]
C --> D["4 - Mocks saved<br/>in mappings/"]
D --> E{"Edit mocks?"}
E -->|"Yes"| F["5a - Edit via Dashboard"]
E -->|"Yes"| F2["5b - Edit JSON manually"]
E -->|"No"| G["6 - Use offline"]
F --> G
F2 --> G
G --> H{"Which engine?"}
H -->|"WireMock"| I["make wiremock"]
H -->|"Mockoon"| J["make mockoon"]
I --> K["Mocks served<br/>on localhost:8081"]
J --> K
style A fill:#e76f51,color:#fff,stroke:#f4a261
style B fill:#e9c46a,color:#1a1a2e,stroke:#f4a261
style C fill:#2a9d8f,color:#fff,stroke:#264653
style D fill:#264653,color:#e6e6e6,stroke:#2a9d8f
style F fill:#6366f1,color:#fff,stroke:#4f46e5
style F2 fill:#457b9d,color:#fff,stroke:#1d3557
style G fill:#6c757d,color:#fff,stroke:#495057
style I fill:#2d6a4f,color:#fff,stroke:#40916c
style J fill:#e76f51,color:#fff,stroke:#f4a261
style K fill:#1a1a2e,color:#e6e6e6,stroke:#16213e
Mockoon can work in hybrid proxy mode: routes with a defined mock return the mock, routes without one are forwarded to the real API.
graph LR
App["App / Browser"] --> MK["Mockoon<br/>localhost:8081"]
MK -->|"Route with mock"| Mock["Mock<br/>Response"]
MK -->|"Route without mock"| API["Real API<br/>(proxy)"]
API --> MK
style App fill:#264653,color:#e6e6e6,stroke:#2a9d8f
style MK fill:#e76f51,color:#fff,stroke:#f4a261
style Mock fill:#2d6a4f,color:#fff,stroke:#40916c
style API fill:#457b9d,color:#fff,stroke:#1d3557
make mockoon-proxy PROXY_TARGET=https://api.example.com{
"request": {
"method": "GET",
"url": "/api/health"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": "{\"status\": \"ok\"}"
}
}Saved at
mocks/mappings/api_health_get.json
{
"request": {
"method": "GET",
"url": "/api/users"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"bodyFileName": "users.json"
}
}Mapping at
mocks/mappings/api_users_get.jsonBody atmocks/__files/users.json
graph LR
WM["WireMock<br/>mappings/*.json<br/>+ __files/*"] -->|"converter.js<br/>to-mockoon"| MK["Mockoon<br/>.mockoon-env.json"]
MK -->|"converter.js<br/>to-wiremock"| WM
style WM fill:#2d6a4f,color:#fff,stroke:#40916c
style MK fill:#e76f51,color:#fff,stroke:#f4a261
# WireMock β Mockoon
make convert-to-mockoon
# Mockoon β WireMock
make convert-to-wiremockConversion to Mockoon format happens automatically when the Mockoon engine starts. You only need to run it manually if you want to inspect or edit the generated file.
| Command | Engine | Description |
|---|---|---|
make wiremock |
WireMock | Serve existing mocks |
make mockoon |
Mockoon | Serve existing mocks (auto-converts) |
| Command | Description |
|---|---|
make wiremock-record PROXY_TARGET=<url> |
Start WireMock recording all proxied requests |
./scripts/record.sh start <url> |
Start recording via Admin API |
./scripts/record.sh stop |
Stop recording and persist mocks |
./scripts/record.sh snapshot |
Point-in-time capture of current state |
./scripts/record.sh status |
Check if recording is active |
| Command | Description |
|---|---|
make mockoon-proxy PROXY_TARGET=<url> |
Mockoon hybrid: mock + proxy |
| Command | Description |
|---|---|
make convert-to-mockoon |
Generate .mockoon-env.json from mappings |
make convert-to-wiremock |
Generate mappings from .mockoon-env.json |
| Command | Description |
|---|---|
make build |
Build Docker image |
make down |
Stop all containers |
make list-mappings |
List mocks and body files |
make clean |
Remove containers and generated files |
make clean-mocks |
Remove all mocks (careful!) |
make help |
List all available commands |
| Variable | Default | Description |
|---|---|---|
MOCK_PORT |
8081 |
Port on host and inside container |
PROXY_TARGET |
β | Real API URL for proxy/recording |
MOCK_ENGINE |
wiremock |
Engine: wiremock or mockoon |
RECORD_MODE |
false |
Enable automatic recording (WireMock) |
CONTROL_PORT |
9090 |
Control panel API port |
CORS_ORIGIN |
* |
Allowed CORS origins (comma-separated) |
All variables can be set in
.env(auto-loaded) or passed inline:MOCK_PORT=9090 make wiremock
graph TD
DC["docker-compose.yml"] --> P1["wiremock"]
DC --> P2["wiremock-record"]
DC --> P3["mockoon"]
DC --> P4["mockoon-proxy"]
P1 --> S1["Serve mocks offline"]
P2 --> S2["Proxy + record mocks"]
P3 --> S3["Serve mocks offline"]
P4 --> S4["Mock + hybrid proxy"]
style DC fill:#1a1a2e,color:#e6e6e6,stroke:#16213e
style P1 fill:#2d6a4f,color:#fff,stroke:#40916c
style P2 fill:#e76f51,color:#fff,stroke:#f4a261
style P3 fill:#2d6a4f,color:#fff,stroke:#40916c
style P4 fill:#e76f51,color:#fff,stroke:#f4a261
style S1 fill:#264653,color:#e6e6e6,stroke:#2a9d8f
style S2 fill:#264653,color:#e6e6e6,stroke:#2a9d8f
style S3 fill:#264653,color:#e6e6e6,stroke:#2a9d8f
style S4 fill:#264653,color:#e6e6e6,stroke:#2a9d8f
# Direct usage (without Makefile)
docker compose --profile wiremock up
docker compose --profile mockoon up
PROXY_TARGET=https://api.example.com docker compose --profile wiremock-record up
PROXY_TARGET=https://api.example.com docker compose --profile mockoon-proxy upI need to work without internet but my app depends on 3 external APIs.
# 1. With internet, record mocks for each API
make wiremock-record PROXY_TARGET=https://api-users.example.com
# use your app... then stop
make down
# 2. Repeat for other APIs or use the Recording page in the dashboard
# 3. Without internet, serve the mocks
make wiremockI need stable mocks in my CI pipeline.
# Record once locally, commit the mocks
make wiremock-record PROXY_TARGET=https://staging.api.com
make down
git add mocks/ && git commit -m "add API mocks"
# In CI
docker compose --profile wiremock up -d
npm test
docker compose --profile wiremock downThe team decided to migrate from WireMock to Mockoon (or vice-versa).
# Same mocks, different engine
make wiremock # before
make mockoon # after β zero changes to mocks| Guide | Description |
|---|---|
| Recording with PokΓ©API + Postman | Full walkthrough: record PokΓ©API mocks, serve offline, and use via Postman Collection |
MIT β see LICENSE for details.
Stubrix β made with β by Marcelo DavanΓ§o
