Dev.to AI 🤖 Ai 👁 0 📖 3 min read

Prefer fixture JSON over “sample data” comments when prompting UI agents

“Use some sample data” in a prompt is an invitation to invent. The agent fabricates a user shape that almost matches production, hard-codes three pretty rows, and skips the nullables your API actually returns. Reviewers

“Use some sample data” in a prompt is an invitation to invent. The agent fabricates a user shape that almost matches production, hard-codes three pretty rows, and skips the nullables your API actually returns. Reviewers only notice when the real payload hits the page.

I’ve stopped describing sample data in prose. I point the agent at a fixture JSON file (or paste a trimmed fixture) and require the UI to consume that shape.

Why comments lose to fixtures

Prose samples drift:

  • Field names get camelCased “for React” while the API is snake_case
  • Optional fields disappear because the happy path didn’t need them
  • Dates become "yesterday" strings instead of ISO timestamps
  • Empty arrays and nulls never appear, so empty states stay theoretical

A fixture checked into src/fixtures/ or testdata/ is greppable, reviewable, and reusable in Storybook / Playwright. A comment in the prompt is gone by tomorrow.

What a good fixture looks like

Keep it boring and honest:

{
  "invoices": [
    {
      "id": "inv_1001",
      "number": "2026-1001",
      "status": "open",
      "customerName": "Northwind Labs",
      "totalCents": 129900,
      "currency": "USD",
      "dueOn": "2026-11-30",
      "poNumber": null
    },
    {
      "id": "inv_1002",
      "number": "2026-1002",
      "status": "past_due",
      "customerName": "A very long customer name that should truncate in the table cell without wrapping the row awkwardly",
      "totalCents": 0,
      "currency": "USD",
      "dueOn": "2026-10-01",
      "poNumber": "PO-7781"
    }
  ],
  "pagination": { "page": 1, "pageSize": 25, "total": 2 }
}

Include at least one awkward row (long name, null, zero). That’s the point — not a marketing screenshot dataset.

Add siblings when the UI has branches:

  • invoices.empty.json → "invoices": []
  • invoices.error.json → shape your error boundary expects
  • invoices.forbidden.json → if the UI branches on 403

Prompt shape

Build the InvoiceTable UI against the fixture at
`src/fixtures/invoices.list.json`.

Constraints:
- Import / parse that file (or a Storybook loader that reads it) — do not invent a parallel mock object in the component file
- Prop types / Zod schema must accept every field in the fixture, including nulls
- Add stories: Default (list fixture), Empty (`invoices.empty.json`), LongName (already in list fixture)
- If the fixture is missing a field you need, stop and propose a fixture update — do not silently invent fields in JSX
- No “sample data” comments as a substitute for the file

The “propose a fixture update” line keeps the contract in the data layer, where it belongs.

Wire fixtures where agents already look

  • Storybook — args loaded from JSON, or a fetch to static fixtures in public/fixtures
  • MSW / Playwright — same JSON for network stubs so E2E and stories don’t diverge
  • Unit tests — import the fixture instead of inline objects

One source. Multiple consumers. The agent is less tempted to freestyle a fourth shape.

Validate the fixture once

If the repo already has Zod / JSON Schema / OpenAPI types for the endpoint, run the fixture through that parser in a one-line test:

import { invoiceListSchema } from '../api/invoiceList.schema';
import fixture from '../fixtures/invoices.list.json';

test('list fixture matches wire schema', () => {
  expect(() => invoiceListSchema.parse(fixture)).not.toThrow();
});

That catches the silent drift where someone “simplifies” the JSON for Storybook and breaks production parsing later. Agents should extend the fixture + schema together — never only the pretty mock.

Reject / send back

Reject

  • Inline const sampleUsers = […] that doesn’t match the fixture path you named
  • Happy-path-only mocks with no empty / null variants
  • Renaming API fields in the UI layer “for clarity” without a mapper
  • Prompt replies that say “using sample data” with no file path

Accept

  • UI wired to a real fixture path
  • Stories / tests that reference the same JSON
  • A small fixture PR when the contract truly needs a new field
  • Explicit mappers when the view model differs from the wire format

Tiny habit

Before the next UI generation prompt, drop a fixture JSON in the repo (or paste a trimmed one) and ban “sample data” wording. If the agent invents fields, don’t fix them in the component first — fix or extend the fixture, then regenerate against it. Concrete beats descriptive when the payload is the product.

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.