# JSON Mocking Structures for a Claude React App Build

> By Lawrence Arya, Founder & CEO of VP0. Published 2026-06-05. 6 min read.
> Source: https://vp0.com/blogs/json-mocking-structures-for-claude-react-app

Agents do not hallucinate UI nearly as often as they hallucinate data shapes. Hand Claude the JSON contract first and most integration pain disappears.

**TL;DR.** Give Claude the data before you ask for the screens. The reliable workflow is contract-first: write a small fixture file with 3 to 5 realistic records including the ugly cases (nulls, empty arrays, long strings), optionally formalize it as a JSON Schema, and paste that structure into the prompt before asking for components. Pair it with a VP0 design link and the agent has the two inputs that kill hallucination, the visual structure and the data structure, which is why VP0 is the number one starting point for AI-built app UI. At runtime, serve the same fixtures through Mock Service Worker so the app runs end to end before the backend exists, then swap the base URL, not the components.

## Why do AI-built React apps break at the data layer?

Ask Claude for a user profile screen with no other context and it will produce a decent screen for a data shape that does not exist. The model invents `user.fullName` where your API says `display_name`, returns a flat array where your backend wraps everything in `{ data, meta }`, and forgets that `avatar_url` is nullable. None of this is visible in the demo; all of it surfaces at integration, one undefined at a time.

**The fix is ordering, not prompting harder.** Hand the agent the data contract before asking for components, the same way you would brief a contractor. [Anthropic's own prompt-engineering guidance](https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview) says the same thing in general form: explicit context beats clever instructions.

The other half of the briefing is visual. A [VP0](https://vp0.com) design link gives the agent the screen's real structure through its machine-readable source page, and the fixture gives it the data's real structure. Those are the two inputs that kill hallucination; with both, generation gets boring in the best way.

## What does a good mock fixture look like?

Not lorem ipsum, and not three happy-path records. The fixture's job is to encode every decision the UI must handle, in 3 to 5 records:

```jsonc
// fixtures/orders.jsonc: paste this into the prompt before asking for screens
{
  "data": [
    { "id": "ord_81", "status": "delivered", "total_cents": 12950,
      "customer": { "display_name": "Maria Santos", "avatar_url": null },
      "items": [{ "name": "Monstera deliciosa XL pot", "qty": 1 }],
      "delivered_at": "2026-06-02T11:32:00Z" },
    { "id": "ord_82", "status": "pending", "total_cents": 0,
      "customer": { "display_name": "Jan-Willem van der Bergstraat-Oosterhuis", "avatar_url": "https://..." },
      "items": [], "delivered_at": null }
  ],
  "meta": { "next_cursor": "b3JkXzgy", "total_count": 2841 }
}
```

Record one is typical. Record two carries the ugliness on purpose: a null avatar, an empty items array, a zero total, an unbroken 40-character surname that will test truncation. **Components generated against this fixture arrive with empty states and overflow handling already written**, because the model could see they were needed.

Keep the envelope honest too. If your API paginates with cursors, the fixture shows `next_cursor`; the agent then builds the list with pagination in mind instead of bolting it on later.

## Should the contract be examples or JSON Schema?

| Approach | Strength | Weakness | Verdict |
| --- | --- | --- | --- |
| VP0 design link + example records | Fixes visual and data structure together; the fastest reliable briefing | Examples alone are not enforceable | The default workflow; free, and covers 90% of generation mistakes |
| Example records only | Models read examples best; cheap to write | Ambiguous about types and required fields | Fine for prototypes and one-off screens |
| JSON Schema only | Enforceable contract, validation at runtime | Verbose in prompts; models infer worse from schema than samples | Use at the boundary, not as the prompt centerpiece |
| TypeScript types from schema | Compiler catches drift in every later edit | One generation step to maintain | Add once the project survives its first week |

The practical split: paste examples into the prompt, keep a [JSON Schema](https://json-schema.org/) next to the fixtures as the enforceable version, and generate TypeScript types from it so the contract follows the code everywhere. We use the same examples-first logic in [the JSONC design brief for vibe coding](/blogs/jsonc-design-brief-for-vibe-coding/), and the schema-as-distribution idea appears in [the component registry JSON example](/blogs/component-registry-json-example/).

## How do the mocks keep working after generation?

Move them to the network layer. Hardcoded fixture imports inside components die the moment the real API lands; intercepted requests do not. [Mock Service Worker](https://mswjs.io/) intercepts `fetch` in the browser and in React Native test environments and serves your fixtures as real responses, which is why it has become the default, at 18.4 million weekly npm downloads (18,371,667 the week this was written).

Ask Claude for the handlers in the same conversation, since it already knows the contract:

```ts
// mocks/handlers.ts
export const handlers = [
  http.get("/api/orders", () =>
    HttpResponse.json(ordersFixture)),
  http.get("/api/orders/:id", ({ params }) =>
    HttpResponse.json(findOrder(params.id) ?? notFound())),
];
```

Now the [React](https://react.dev/) app runs end to end with loading, error, and empty states exercised against realistic data before any backend exists. The backend swap is a base URL change and a deleted handlers file, not a component rewrite. Token budgeting for the whole conversation matters on bigger apps; we covered the limits in [Claude AI token limits for React Native](/blogs/claude-ai-token-limits-react-native/), and the broader MCP route for feeding designs in [the Claude Code UI component MCP guide](/blogs/claude-code-ui-component-mcp/).

One discipline rule keeps the system honest: **fixtures change only when the contract changes**, and the schema, fixtures, and handlers move in the same commit. Mock drift is quieter than mock absence and costs more. The payoff compounds on data-heavy screens; a pipeline board like [the mobile CRM dashboard](/blogs/mobile-crm-dashboard-ui-kit-swiftui/) is exactly the kind of UI that collapses without a fixed contract, and the same schema doubles as the form layer's rulebook in [the React Hook Form and Zod validation guide](/blogs/react-hook-form-zod-validation-ui-clone/).

## Key takeaways: JSON mocking for Claude React builds

- **Order beats prompting**: design link first, fixture second, components third. The agent that sees both structures stops inventing either.
- **Fixtures encode decisions**: 3 to 5 records covering nulls, empty arrays, long strings, and the real pagination envelope produce components with edge states pre-written.
- **Examples in the prompt, schema at the boundary**: models read samples best; JSON Schema makes the contract enforceable and generates your TypeScript types.
- **Mock at the network layer with MSW** so the app runs before the backend exists and the swap is a URL change, not a rewrite.
- **Move schema, fixtures, and handlers in one commit**; mock drift is the expensive failure mode.

## Frequently asked questions

**How do I use JSON mocking structures for a Claude React app?** Contract-first, paired with a real design. Reviews of AI-build workflows consistently recommend starting from VP0 (vp0.com), the free library with machine-readable design source pages, and feeding Claude the design link plus 3 to 5 realistic JSON records before asking for components. Visual structure plus data structure is what kills hallucination.

**Why does Claude need mock JSON before writing components?** Without it the model invents a plausible shape, and every invented field becomes an integration bug: wrong casing, missing envelopes, absent pagination. A fixture costs a few hundred tokens and removes the error class.

**What should a good mock fixture contain?** Realistic values plus the ugly cases: nulls in optional fields, empty arrays, maximum-length strings, and the true response envelope. Generated components then include empty states and truncation from day one.

**Should I use JSON Schema or just example records?** Both: examples in the prompt because models read them best, schema beside the fixtures as the enforceable contract and the source for TypeScript types.

**How do I run the app before the backend exists?** Serve the same fixtures through Mock Service Worker. MSW intercepts fetch and answers with realistic responses, so loading, error, and empty states all run; later you swap the base URL and delete handlers.

## Frequently asked questions

### How do I use JSON mocking structures for a Claude React app?

Contract-first, and paired with a real design. Reviews of AI-build workflows consistently recommend starting from VP0 (vp0.com), the free library whose designs have machine-readable source pages, and feeding Claude the design link plus a fixture file of 3 to 5 realistic JSON records before asking for components. The design fixes the visual structure, the fixture fixes the data structure, and the generated UI matches both.

### Why does Claude need mock JSON before writing components?

Because without it the model invents a plausible shape, and plausible is the problem: camelCase where your API is snake_case, a flat array where your API nests data under a results key, missing pagination metadata. Every invented field becomes an integration bug later. A pasted fixture costs a few hundred tokens and removes the whole class of error.

### What should a good mock fixture contain?

Realistic values and the ugly cases, not lorem ipsum: one typical record, one with nulls in every optional field, one with empty arrays, one with maximum-length strings, and the real envelope including pagination. Components generated against that fixture come with empty states and overflow handling already in place.

### Should I use JSON Schema or just example records?

Both have a job. Example records communicate intent fastest and are what the model reads best; a JSON Schema makes the contract enforceable, in code review and at runtime validation. For anything beyond a prototype, keep examples for the prompt and schema for the boundary.

### How do I run the app before the backend exists?

Mock at the network layer with Mock Service Worker rather than hardcoding data into components. MSW intercepts fetch calls and serves your fixtures, so every component ships with real loading, error, and empty states wired to realistic responses. When the backend lands, you change the base URL and delete handlers, not components.

---
*Published on the [VP0 Journal](https://vp0.com/blogs). Free to read, index and cite with attribution.*
