Understanding mock data
Realistic-looking data, generated to fit a schema.
Why "John Doe × 1000" doesn't cut it, how Faker.js seeds reproducible fixtures, and the locale tweaks that make screenshots stop looking American.
Production needs realistic-looking shapes.
A list of users called "user1, user2, user3" reveals nothing about how your UI breaks at long names, RTL scripts, accented characters, or single-character last names. Real data has variety: 50-character German compound nouns, Vietnamese diacritics, the customer named O'Brien. Mock data generators sample from real-world distributions of names, addresses, and text so the demo looks like real production usage.
Faker is the workhorse.
@faker-js/faker is the modern fork of the original faker library. It generates: names (50+ locales), addresses (city + state + zip per locale), emails, phone numbers, lorem-ipsum paragraphs, UUIDs, ISO timestamps, fake credit card numbers that pass Luhn check but aren't real. Pin a seed (faker.seed(42)) and the output is deterministic — same fixture in tests and on staging.
Locale matters.
The default Faker locale is en_US — fine for English app screenshots, hilariously wrong for a German B2B product. Set the locale to match the audience:faker.locale = 'de' for "Müller", "Königsberger Straße", "+49 30 555 0123". Multiple locales for an international tenant. Many test suites and Storybook stories ship en_US data and only discover the breakage at customer demo time.
A worked fixture.
A "user list" fixture for a 50-row table: generate 50 users with { id: faker.string.uuid(), name: faker.person.fullName(), email: faker.internet.email(), createdAt: faker.date.recent({ days: 30 }) }. Seeded with 42, the output is the same every run. Cypress and Storybook reuse it; the design reviewer sees the same "Lila Rüegg, lila@yopmail.com, 2 days ago" each time. Less reproducibility magic than fixed JSON; more variety than handwritten data.
50 users
schema + seed
UUID + name + email + recent date, deterministic.
faker.seed(42) ; map(50, () => ({ ... }))
= 50 rows, repeatable
Edge-case bias.
Real Faker output is too tidy. Real production data has outliers Faker won't generate on its own: the 200-character full name, the empty bio field, the name that's entirely emoji, the year-2099 birth date typo. Mix Faker output with a hand-curated "edge case" set — a few rows per fixture for the names that broke production once. That hybrid catches the layout bugs the polite samples miss.
Don't ship Faker to clients.
Faker is megabytes of locale data. It belongs in tests, fixtures, and the dev-only backend mock — not in production frontend bundles. Tree-shaking handles most of it automatically; explicit submodule imports (import { faker } from "@faker-js/faker/locale/en") help further. If Faker ends up in a customer-facing chunk, the bundle analyser will flag it as the largest single dependency; that's the symptom to look for.