Skip to Content
DevelopmentMock Backend

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 via JSON_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-password via json-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.cjs

How it boots

The flow when you run npm run json-server:

  1. node json-server/json-db.cjs runs first. It merges the JSON fixtures under data/api/ and writes the result to data/db.json.
  2. nodemon json-server/server.cjs starts the Express server on JSON_SERVER_PORT (default 7000).
  3. server.cjs wires:
    • json-server.create() as the Express app.
    • json-server.router('data/db.json') for default REST behavior.
    • json-server-auth for /login, /register, /send-password, and bearer-token enforcement on rule-restricted routes.
    • The custom endpoints from endpoints/index.cjs for non-trivial routes.
  4. 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-data

merge-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:

FileRoutes
assessments.cjsAssessment filtering, sort, aggregations
assessments-meta.cjsThe /assessments/meta enum endpoint (statuses, priorities)
bulk.cjsBulk delete / update across resources
countries.cjs/countries with localized names via i18n-iso-countries
customers.cjsCustomer-specific filters, logs
dashboard.cjsThe aggregated dashboard endpoint
middlewares.cjsShared request middlewares
recipients.cjsRecipient lookups for evidence requests
segments.cjsSegment 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 20260318

Modify 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:

  1. Create json-server/endpoints/<name>.cjs exporting (server, db) => { ... }.
  2. Register it in json-server/endpoints/index.cjs.
  3. 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:

  1. Stand up the real endpoints for one resource.
  2. Update its API slice’s getBaseQuery(path, 'SYSTEM_API').
  3. Verify against staging.
  4. 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:

  1. Stop json-server.
  2. Edit the relevant file(s) under json-server/data/api/.
  3. 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 targetAPI selector on getBaseQuery instead.
  • Skipping endpoint extraction. If a route’s logic is more than ~30 lines, give it its own file under endpoints/.

Next steps

  • API LayergetBaseQuery and the two-target switch
  • EnvironmentJSON_SERVER_PORT, VITE_APP_MOCKUP_API_URL
  • Installation — first-run setup including seed users
Last updated on