How to generate realistic json mock data for ui prototyping
- Step 1List the fields your component renders — Map them onto the fixed shape: a user card uses
name,email,status,score,address.city; a table row uses most fields. The generator always emits the full record; you bind or rename the fields you need. - Step 2Pick a count that fills the viewport — Use 8–12 for a card grid, 20–50 for a list, 100+ for a paginated table (Pro for over 500). Enough records to require scrolling is what reveals real layout behavior.
- Step 3Set a seed and keep it for the prototype — A fixed seed (default
42) makes the prototype's content reproducible, so design review screenshots match across machines. Use different seeds for different screens so they do not look cloned. - Step 4Generate and copy — Click Generate Mock Data and Copy the array. Output is pretty-printed JSON, ready to paste into a sandbox data file or a Figma data plugin.
- Step 5Load into your prototyping tool — In CodeSandbox/StackBlitz, paste as
const data = [ ... ]. In Figma, feed the JSON to a data-populating plugin so each component instance gets a different record. In Framer, bind the array to a list component's data source. - Step 6Force the layout extremes by hand — The generator gives believable middle-of-the-road data. For the genuinely hard cases — a 60-character name, a
scoreof 100, an empty array — override those fields or pass them manually so the review covers the breaking points.
Generated field → UI element and what it stresses
How the fixed fields exercise a layout. There is no per-field range control — values come from fixed pools.
| Field | UI element | Layout stress it reveals |
|---|---|---|
name | Title / primary text | Wrapping and truncation across varied lengths |
email | Secondary text | Long strings pushing layout width |
status | Badge / chip | Four values → all chip colors and widths |
score | Rating / metric / bar | 0–100 with a decimal — number formatting and bar fill |
address.city | Subtitle / location | Short vs long city names |
createdAt | Date line | Date formatting across 2020–2024 |
active | Toggle / dimmed state | Mixed true/false enables/dims rows |
Value ranges (fixed — not adjustable in the tool)
These pools are baked in. To prototype a different distribution, edit the output after generating or override fields in the prototype.
| Field | Range / pool | If you need something else |
|---|---|---|
age | Integer 18–77 | Override in the prototype for under-18 / senior cases |
score | 0–100, one decimal | Rescale after generation if your metric differs (e.g. price) |
status | active / inactive / pending / suspended | Rename values with a find-replace step if your states differ |
name | 10 first × 10 last (100 combos) | Replace specific names for length edge cases |
createdAt | 2020–2024, day 01–28 | Override for future or recent dates |
| no price field | — | Repurpose score or add a field after generating |
Cookbook
Recipes for loading the deterministic dataset into prototyping environments and forcing the hard layout cases.
CodeSandbox list prototype from a seeded array
ExamplePaste the generated array directly as the prototype's data. The seed keeps it identical across reloads and across reviewers.
// Generated: count 30, seed 42
const data = [
{ id: 1, name: 'Grace Davis', status: 'pending', score: 25, address: { city: 'North Haverbrook' } },
{ id: 2, name: 'Frank Wilson', status: 'suspended', score: 6.2, address: { city: 'Springfield' } },
// ...28 more, all deterministic
];
export default function App() {
return <UserList items={data} />;
}Figma data plugin populating component instances
ExampleGenerate enough records to fill the frame, then let a data-populating plugin bind one record per instance so every card shows distinct content.
Step 1 — generate count 12, seed 42 here; Copy the array.
Step 2 — in Figma, open a Data Populator-style plugin, paste the JSON.
Step 3 — bind layers: title→name, subtitle→email, badge→status.
Each card instance gets a different record from the array.
Result: a 12-card grid with varied real-feeling content for review.Force the long-name overflow case
ExampleThe generator's names are short-to-medium. To prove the title cell handles overflow, override one record's name with a long string.
import data from './data.json'; // count 20, seed 42
const withOverflow = data.map((r, i) =>
i === 0 ? { ...r, name: 'Anastasia Konstantinopolitanopoulos-Wright' } : r
);
// Render withOverflow to confirm the title truncates or wraps gracefully.Repurpose score as a price for an e-commerce grid
ExampleThere is no price field and no price-range control. Map the existing 0–100 score onto a price after generating, scaling as needed.
import data from './data.json'; // count 24, seed 42
const products = data.map(r => ({
id: r.id,
title: r.name, // reuse as product name
price: Math.round(r.score * 50) / 1, // 0–100 → $0–$5000-ish
inStock: r.active
}));
// Now you have a varied price spread for grid-alignment testing.Empty state authored manually
ExampleThe generator's minimum is 1 record, so it cannot produce an empty list. Pass an empty array yourself to prototype the empty state.
// Populated state: generated array.
// Empty state — author by hand:
const data = [];
// <UserList items={data} /> → renders the empty-state UIErrors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
You wanted a price-range or category picker
Not configurableThere is no per-field range control and no category preset. Values come from fixed pools (score 0–100, age 18–77, four status values, no price field). Generate the base data and remap or rescale fields in the prototype — e.g. derive a price from score.
You expected the tool to match your component schema
Not supportedThe generator emits the fixed person shape and ignores any schema. Map its fields onto your component, or rename/trim with json-key-renamer and json-key-filter to reach your component's data shape.
All names are short, so overflow never triggered
Force it manuallyGenerated names come from a small pool and are short-to-medium length, so the natural data may never overflow a title cell. Override one record's name with a deliberately long string to prove the overflow handling.
No avatar or image in the records
Not generatedThe record has no image field. For avatars in a prototype, derive a placeholder URL from name or id (DiceBear, picsum) after pasting, or bind an image layer to a static asset in Figma.
Need an empty-state screen
Author manuallyThe generator's minimum count is 1; it cannot emit []. Pass an empty array yourself for the empty-state prototype. Use the generator for the populated states.
Cards all look identical in a small grid
Increase countWith only a few records you may not see status or score variety. Generate 8+ records so status cycles all four values and scores spread across the range, which is what makes the grid look real in review.
Regenerating changed the whole prototype's content
By designA different seed produces different (still deterministic) data. Keep one seed per screen and commit the JSON so review screenshots stay consistent. Change the seed only when you intend to refresh the content.
Free plan blocked a 1,000-row table prototype
Plan limitFree caps at 500 records. A table prototype usually needs only enough rows to show scrolling and a couple of pages; for genuinely large datasets, Pro raises the cap to 10,000.
Repeated names across a large grid
ExpectedNames come from a 100-combination pool, so large grids repeat names. For a prototype this is usually fine; if a screenshot needs all-unique names, keep the count under ~100 or swap specific names by hand.
Frequently asked questions
Can I set a price range or pick value distributions?
No. There is no per-field range control. Values come from fixed pools — score is 0–100, age is 18–77, status cycles four values, and there is no price field at all. Generate the base data and remap or rescale fields in your prototype (for example, derive a price from score).
Does the tool generate data matching my component's schema?
No. It emits a fixed person-record shape and ignores any schema. Map its fields onto your component, or reshape with json-key-renamer and json-key-filter to reach the exact shape your component expects.
How many records should I generate for a prototype?
Enough to fill a realistic viewport and require scrolling: 8–12 for a card grid, 20–50 for a list, 100+ for a paginated table. The generator clamps to 500 on free and 10,000 on Pro, far more than most prototypes need.
How do I test how the layout handles a very long name?
Override one record's name with a long string after generating. The generator's names are short-to-medium, so natural data rarely overflows; forcing the extreme is the reliable way to prove your title cell truncates or wraps correctly.
Can I generate avatar images?
No — the record has no image field. Derive a placeholder avatar from name or id (e.g. DiceBear or picsum) in the prototype, or bind an image layer to a static asset in Figma. The generator covers text data, not media.
Will the prototype render the same content every time?
Yes, as long as the seed and count stay the same. The output is deterministic, so a committed dataset renders identically on every load and machine — which keeps design-review screenshots and recordings consistent across the team.
How do I prototype an empty state?
Pass an empty array yourself — the generator's minimum is 1 record, so it cannot emit []. Use the generator for the populated states and author the empty array for the empty-state screen.
How do I load the data into Figma?
Generate enough records to fill the frame, copy the array, and paste it into a data-populating plugin (Data Populator-style). Bind layers to fields (title to name, badge to status) so each component instance gets a different record from the array.
Why does flipping Sequential IDs change the names too?
The id mode shifts the internal random stream, so non-id fields change at the same seed. Decide the id style first, then lock the seed so the prototype's content is stable.
Is the output ready to paste into CodeSandbox or Framer?
Yes. It is valid, pretty-printed JSON — paste it as a const data = [ ... ] in a sandbox, or bind it to a list component's data source in Framer. For a compact inline form, run it through json-minifier first.
Can I convert the data for a different prototype need?
Yes — convert to CSV for spreadsheet-driven mockups with json-to-csv, generate types with json-to-typescript, or validate hand-edited data with json-validator.
Does my design or prototype data get uploaded?
No. Generation runs entirely in your browser. The tool ignores input and the generated data never reaches JAD Apps servers. Only an anonymous usage counter is recorded for signed-in dashboard stats.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.