A mock buys your frontend three weeks it would otherwise spend waiting
The pattern repeats on most teams. The API contract is agreed in a meeting, the backend starts on the hard parts, and the frontend sits with a design that has nowhere to pull data from. Hardcoding an array inside the component feels quick, then someone ships it, and six months later a fixture nobody remembers is still shadowing a real endpoint.
A mock spec keeps the fake data outside your source tree. You describe the shape once, feed it to a mock server or your test suite, and delete one file when the real service arrives. Your components never learn that the data was invented.
From this page to a running server
Nothing on this page serves traffic. It writes the description, and a separate tool serves it. Three routes work with the file the Download button gives you.
- Prism
Install
@stoplight/prism-cli, then runprism mock openapi.json. You get a local server on port 4010 that answers every path in the file with an example matching the declared status code. - json-server
Take the generated record array instead of the spec, save it as
db.json, and runjson-server db.json. You lose the path definitions, you gain working POST and PATCH against an in-memory store. - MSW
Paste the record array into a Mock Service Worker handler. The interception happens inside the browser, which keeps the mock working in your test runner and in the dev server without a second process to start.
What the four steps actually control
| Step | Where it lands in the export | What it changes downstream |
|---|---|---|
| Name, version, description | info | Header text in Swagger UI. Version strings also drive client generator package names. |
| Base URL | servers[0].url | The host your generated client calls. Wrong value here means a mock that works and a build that does not. |
| Path and method | paths | Adding the same path twice with different verbs merges them under one path object, which is correct OpenAPI. |
| Status code | responses | Each endpoint carries exactly one code. Add the same path and verb again to describe a second outcome. |
| Response format | content media type | Switches between application/json, application/xml and application/text across every operation at once. |
| Authentication | components.securitySchemes | Defines the scheme. It does not apply it, so operations stay open until you attach a security block. |
Placeholders the record generator understands
The schema box takes flat JSON. Any string value holding a recognised token is replaced per record. Anything else is copied through as a literal, which is how you pin a field to a fixed value.
| Token | What each record gets | Good fit for |
|---|---|---|
{{faker.datatype.number}} | Integer between 1 and 1000, redrawn per record | ids, counts, quantities |
{{faker.name.fullName}} | One of five names, cycled in order | display names in a list view |
{{faker.internet.email}} | user0@gmail.com upward, domain rotates through four | account rows, login tables |
{{faker.image.avatar}} | A pravatar.cc URL, image 1 to 50 | real images in a card grid |
{{faker.date.recent}} | ISO 8601 timestamp inside the last 30 days | created_at, last_seen, sort keys |
{{random.number(1, 1000)}} | Integer between 1 and 1000. The arguments are decorative | scores, view counts |
{{random.words(2)}} | The string Item followed by the row index | titles you plan to overwrite |
{{random.email}} | user0@test.com upward | throwaway addresses |
{{random.float(0, 100)}} | Two decimal places, delivered as a string | prices and ratings, once you parse it |
{{random.boolean}} | true or false, near even split | flags, toggles, filter tests |
Matching is by substring, so a value like "Order {{faker.datatype.number}}" returns the bare number, not the sentence. Put the token on its own and build the label in your component.
Four ways mock data lies to you
Every mock is an opinion about the real service. These are the four disagreements that reach production most often.
- Everything is the happy path
- Ten tidy records, every field populated, no timeouts. Add a second entry for the same path with a 500 status and point your client at it for an afternoon. Empty states and error states are where mocked frontends fall over first.
- Strings that are always short
- Generated names run to a dozen characters. Real users have hyphenated surnames, no surname, and emoji in the display field. Paste one 200 character string into the record set on purpose and see what your layout does.
- Types that drift
- The float placeholder returns
"42.19"with quotes around it. If the real API sends a number, your client works against the mock and breaks against the service. Check every numeric field for quotes before you build arithmetic on it. - Ten rows instead of ten thousand
- Pagination bugs hide behind a single page of results. Set the record count to 500 and confirm the list virtualises, the meta block adds up, and the page-two request goes out.
Where this page stops
Worth knowing before you plan a workflow around it.
- No live endpoint. The output is a description. Serving it takes Prism, json-server, MSW or WireMock.
- Response schemas stay generic. Every operation declares
type: objectwith no properties, so Swagger UI lists your routes without field-level detail. Client generators produce loosely typed models from it. - Path parameters are not declared. A route such as
/users/{id}exports without a matchingparametersentry, which strict validators flag as an error. Add them by hand if the file has to pass linting. - No request bodies. POST and PUT operations carry responses only, so a generated client will not know what to send.
- One response template for the whole spec. Different shapes per endpoint means editing the exported file or running the generator once per resource.
- XML and plain text set the media type only. The body template box still expects JSON, and the preview panel parses JSON.
For a spec you intend to publish rather than mock against, start from the OpenAPI Swagger generator, which carries schema definitions and request bodies.
Nothing you type leaves the tab
Generation happens in JavaScript on your machine. Internal hostnames, unreleased route names and client identifiers stay in the browser, and no request carries them anywhere. Values persist until you reload the page, so refresh before handing the screen to someone else.
