A multi-project tool for generating and seeding mock data into Webiny CMS instances. Manages project connections (encrypted), syncs models/groups/tenants from live Webiny, generates realistic fake data respecting CMS field validation, and sends entries via GraphQL. Includes a CLI, REST API, and web UI.
yarn installyarn cli initThis generates a .env file with a random encryption key and default port config:
ENCRYPTION_KEY=<64-char hex>
API_PORT=4000
UI_PORT=4001
Option A: Via CLI
yarn cli add-projectPrompts for project name, Webiny API URL, API token, tenant, and version.
Option B: Via seed file (recommended for teams)
Create .projects.json in the project root:
[
{
"name": "My Webiny Project",
"apiUrl": "https://your-api.webiny.com",
"apiToken": "your-api-token",
"tenant": "root",
"webinyVersion": "6.0.0"
}
]Projects are upserted by name on every server start. The API token is encrypted before storage. See .projects.json.example for the format.
Important:
.projects.jsoncontains real API tokens — it is gitignored. Never commit it. Only.projects.json.examplewith placeholder values is tracked.
yarn devThis starts both the API server (port 4000) and the UI (port 4001) with hot reload.
Open http://localhost:4001 in your browser.
If not already seeded via .projects.json, add a project:
- Click Add Project on the project list page
- Enter project name, Webiny API URL, API token, tenant, and version
Before seeding or importing, the project needs tenants and models pulled from Webiny:
- Open the project
- Go to Pull Tenants — click Pull Tenants to discover tenants from the Webiny instance
- For each tenant other than the default one, set its API token in the Tenants tab (Edit token). The environment's API token is the main key and only works for the default (root) tenant.
- Go to Pull Models — click Pull Models to pull CMS model definitions and groups for every tenant that has a key. Models are stored per tenant.
These must be done in order — tenants first, then tokens, then models. After pulling, the tenants and models tabs show what was discovered.
Option A: Seed new mock data
- Go to Seed Data
- Select a target tenant
- Set entries per model and revisions (e.g.
1or1-5for a random range) - Select which models to seed (grouped by content model group)
- Optionally override entries/revisions per model
- Choose a publish strategy (none, all, random %, first revision, last revision)
- Optionally enable unpublish cycles (simulates real content lifecycle)
- Click Seed Data — a confirmation dialog shows all settings and lets you adjust batch size (concurrent mutations)
- Confirm to start the job
Option B: Import existing entries from Webiny
- Go to Import to pull existing entries from the Webiny instance into the local audit log
- Imported entries become available as refs for future seed runs
All operations run as background jobs with real-time progress via WebSocket. Check the Jobs tab for status, logs, and to cancel running jobs.
- Dependency ordering: models with ref fields are seeded after the models they reference — e.g.
productCategoryseeds beforeproduct - Available refs: all previously seeded and imported entries are available for ref fields, so you can seed categories in one run and products in another
- Batch size: controls how many GraphQL mutations run concurrently (1–50). Higher = faster but more load on Webiny
- Fail fast: if a mutation fails for a model, seeding stops for that model and moves to the next
- Rate limiting: automatic retry on HTTP 429 with exponential backoff (up to 3 retries)
| Command | Description |
|---|---|
yarn cli init |
Generate .env with encryption key + port config |
yarn cli add-project |
Add a Webiny project interactively |
yarn cli list-projects |
Show all configured projects |
yarn cli remove-project |
Select + confirm + remove a project |
yarn cli pull-models |
Pull models/groups from a Webiny project |
yarn cli seed |
Generate + send mock entries (select project → tenants → models → amounts) |
yarn cli rotate-key |
Rotate the API token encryption key |
yarn cli upload-files |
Upload files to a Webiny project's file manager |
CLI (src/cli/) → shared services (src/shared/node/)
API (src/api/) → shared services
UI (src/ui/) → API via HTTP + WebSocket
- Shared layer (
src/shared/node/): SQLite persistence, GraphQL client, generators, job execution - API layer (
src/api/): Fastify REST + WebSocket server - UI layer (
src/ui/): React + Mantine + MobX - DI:
@webiny/dicontainer with abstractions/implementations pattern
All long-running operations (seed, sync, import, cleanup) run as background jobs:
- API route enqueues a job → returns 202 with job ID
- JobWorker polls every 3s, picks up pending jobs, runs executor
- Progress + logs pushed to UI via WebSocket in real-time
- UI shows toast notification on completion/failure
- Affected data auto-refreshes in the UI
Job types: seed, pull-tenants, pull-models, cleanup, import.
Every seeded entry is logged with:
- Request: full GraphQL mutation, variables, URL (auth token redacted)
- Response: complete raw HTTP response from Webiny
- Error: error message if the mutation failed
Click any entry in the Audit Log tab to see the full request/response detail.
| Script | Command | Purpose |
|---|---|---|
yarn dev |
concurrently |
API + UI together |
yarn cli |
tsx src/cli/entry.ts |
CLI tool |
yarn api:dev |
tsx --watch src/api/entry.ts |
API server only |
yarn ui:dev |
vite dev |
UI dev server only |
yarn typecheck |
tsc --noEmit |
Type checking |
yarn test |
vitest run |
Run tests |
yarn test:watch |
vitest |
Watch mode |
yarn lint |
oxlint |
Lint check |
yarn format:check |
oxfmt --check |
Format check |
yarn db:generate |
drizzle-kit generate |
Generate DB migration |
Before every commit: yarn lint && yarn format:check && yarn typecheck && yarn test
| Variable | Required | Default | Purpose |
|---|---|---|---|
ENCRYPTION_KEY |
Yes | — | 64-char hex for AES-256-GCM token encryption |
API_PORT |
No | 4000 | Fastify server port |
UI_PORT |
No | 4001 | Vite dev server port |
DB_PATH |
No | .webiny/data-mock.db |
SQLite database path |
All runtime data is stored in .webiny/ (gitignored):
.webiny/
├── data-mock.db # SQLite database
├── cache/ # File cache
└── logs/ # Log files
.projects.json is read on every server start. Projects are matched by name — existing projects are updated, new ones are inserted. This is the recommended way to share project connections across a team (each developer creates their own .projects.json from the example).
cp .projects.json.example .projects.json
# Edit .projects.json with your real values