Mock Backend
Coreola ships a json-server mock backend so the frontend can run end-to-end without any real server. It is not a deployable backend — it exists to enable demos, local development, and frontend work that needs to land before backend work.
- Source:
json-server/ - Libraries:
json-server,json-server-auth,@faker-js/faker,nodemon,dotenv - Runs on:
http://localhost:7000(configurable viaJSON_SERVER_PORT) - Started with:
npm run json-server
What it does
In dev mode, every RTK Query slice pointing at MOCKUP_API talks to this server. It provides:
- Standard REST CRUD on
/users,/customers,/assessments,/roles,/abilities,/features,/notifications,/recipients,/segments,/meta, and so on. - bcrypt-authenticated
/login,/register,/send-passwordviajson-server-auth. - Custom endpoints (search, dashboard aggregation, avatar upload, bulk operations) handled by Express middleware in
json-server/endpoints/. - Seeded data generated by Faker for realistic listings.
Folder layout
json-server/
├─ server.cjs # Express + json-server entry point
├─ json-db.cjs # Merges fixtures + Faker seeds → data/db.json
├─ faker.cjs # Faker locale + seed configuration
├─ data/
│ ├─ db.json # The runtime database (gitignored, regenerated)
│ ├─ api/ # Fixture files merged into db.json
│ └─ ...
├─ endpoints/
│ ├─ index.cjs # Registers all custom endpoints
│ ├─ assessments.cjs
│ ├─ assessments-meta.cjs
│ ├─ bulk.cjs
│ ├─ countries.cjs
│ ├─ customers.cjs
│ ├─ dashboard.cjs
│ ├─ middlewares.cjs
│ ├─ recipients.cjs
│ ├─ segments.cjs
│ └─ uploadAvatar.cjs
└─ generators/
├─ assessments.cjs
├─ assessment-activity.cjs
├─ assessment-findings.cjs
├─ customers.cjs
├─ customers-logs.cjs
├─ evidence-requests.cjs
├─ meta.cjs
├─ recipients.cjs
└─ shared.cjsHow it boots
The flow when you run npm run json-server:
node json-server/json-db.cjsruns first. It merges the JSON fixtures underdata/api/and writes the result todata/db.json.nodemon json-server/server.cjsstarts the Express server onJSON_SERVER_PORT(default7000).server.cjswires:json-server.create()as the Express app.json-server.router('data/db.json')for default REST behavior.json-server-authfor/login,/register,/send-password, and bearer-token enforcement on rule-restricted routes.- The custom endpoints from
endpoints/index.cjsfor non-trivial routes.
- The server logs every route it knows about, then waits for requests.
Hot reload
nodemon watches json-server/server.cjs (and anything it requires). Saving a change to an endpoint restarts the server. The DB file is not regenerated on reload — only on the initial npm run json-server invocation.
To regenerate the DB while keeping the server running, use:
npm run merge-datamerge-data reruns json-db.cjs under nodemon and regenerates db.json from json-server/data/api/. If you edit fixtures directly, running node json-server/json-db.cjs once is enough.
Authentication
json-server-auth adds bearer-token authentication on top of json-server. The auth.rewriter block in server.cjs declares per-resource permission rules:
users: 660,
notifications: 660,
assessments: 660,
// ...The three-digit codes encode read/write rules — see the json-server-auth docs for the full semantics. In the seeded config, most resources are 660 (auth required for both reads and writes), which is what Coreola assumes.
The seeded admin user lives in json-server/data/api/users.json with a bcrypt-hashed password. See Installation for the sign-in caveat.
Custom endpoints
endpoints/index.cjs registers each custom endpoint module. They handle requests that go beyond plain CRUD:
| File | Routes |
|---|---|
assessments.cjs | Assessment filtering, sort, aggregations |
assessments-meta.cjs | The /assessments/meta enum endpoint (statuses, priorities) |
bulk.cjs | Bulk delete / update across resources |
countries.cjs | /countries with localized names via i18n-iso-countries |
customers.cjs | Customer-specific filters, logs |
dashboard.cjs | The aggregated dashboard endpoint |
middlewares.cjs | Shared request middlewares |
recipients.cjs | Recipient lookups for evidence requests |
segments.cjs | Segment CRUD with embedded customers |
uploadAvatar.cjs | /upload-avatar (base64 → file path) |
Each module is plain Express — (req, res, next) => { ... } handlers attached to server.use(...) or server.get(...) / server.post(...).
Order matters
server.cjs registers middlewares before the json-server router. Custom endpoints intercept the request first; anything they do not handle falls through to json-server’s automatic CRUD.
The body parser is applied before custom endpoints so they can read req.body directly.
Generators
generators/*.cjs produce realistic seed data. They consume Faker (configured in faker.cjs for locales en, uk) and emit arrays of objects with stable ids, sensible names, and inter-referenced ids (e.g., a finding references a real assessment id).
Generators are invoked explicitly through node json-server/faker.cjs:
node json-server/faker.cjs
node json-server/faker.cjs customers 200
node json-server/faker.cjs recipients 50
node json-server/faker.cjs assessments 120 20260318Modify a generator to change the shape of seeded data — useful for demos that need specific data shapes (“show 50 assessments, half in needs_review”). After generating fixtures, run npm run json-server or npm run merge-data to rebuild db.json.
When to extend it
Default CRUD is enough for most resources. Reach for a custom endpoint when:
- You need filtering or aggregation that json-server’s query operators cannot do.
- You need authorization logic beyond the simple permission codes.
- You are simulating an API the real backend will eventually expose, and the real version has business logic you want to mock.
The recipe:
- Create
json-server/endpoints/<name>.cjsexporting(server, db) => { ... }. - Register it in
json-server/endpoints/index.cjs. - Restart with
npm run json-server(nodemon will pick up subsequent edits).
When to drop it
In production, you do not run json-server. The Coreola frontend keeps pointing at MOCKUP_API for any slice that has not been migrated to the real backend — that variable can stay empty in production.
A pragmatic migration:
- Stand up the real endpoints for one resource.
- Update its API slice’s
getBaseQuery(path, 'SYSTEM_API'). - Verify against staging.
- Repeat for the next resource.
The mock backend supports the transition, not a final state. Once every slice talks to SYSTEM_API, you can stop running json-server entirely and delete the folder (though most teams keep it around for local dev).
Resetting state
The mock DB resets every time you run npm run json-server because json-db.cjs regenerates it from fixtures and Faker. To preserve a specific state across restarts:
- Stop json-server.
- Edit the relevant file(s) under
json-server/data/api/. - Restart.
For a one-off snapshot, copy data/db.json somewhere safe before restarting.
Anti-patterns
- Treating json-server as a production backend. It is not authenticated for real-world use, has no concurrency control, and stores everything in a single JSON file.
- Adding business logic to generators. Generators produce seed data; logic belongs in custom endpoints.
- Hand-editing
db.json. It is regenerated. Edits will be lost. - Pointing some endpoints at the real backend by hardcoding URLs. Use the
targetAPIselector ongetBaseQueryinstead. - Skipping endpoint extraction. If a route’s logic is more than ~30 lines, give it its own file under
endpoints/.
Next steps
- API Layer —
getBaseQueryand the two-target switch - Environment —
JSON_SERVER_PORT,VITE_APP_MOCKUP_API_URL - Installation — first-run setup including seed users