ProductIntegrationsPricingFAQFeedbackX
All posts

Enforce Your DESIGN.md in React Native and Expo With Live Style Inspection

Ike Studios LLC

A DESIGN.md file holds your design system in a form your AI coding agent can read: the colors, type scale, spacing, and corner radii your app is supposed to use, plus the rules for using them. The agent reads it before it builds a screen. Reading the rules doesn't mean the screen follows them, though. Your agent can only enforce your design system if it can check what the running app actually rendered.

Ceraph lets it do that check. Ceraph is an MCP server that lets your AI coding agent drive and test a React Native or Expo app on iOS devices and simulators, plus Android devices and emulators. One option on its snapshot tool returns render-time styles from the running app. Your agent gets the render-time color, font, spacing, and radius values each matched element received, and can check them against your DESIGN.md before it calls the work done.

What DESIGN.md is

DESIGN.md is an open format from Google Labs for describing a visual identity to coding agents. It's Apache-2.0 licensed and currently marked alpha, and its specification is also documented on Stitch. A file has two parts:

  • YAML front matter with the tokens. These are the normative values, grouped as colors, typography, spacing, rounded, and components. Tokens can point at each other with references such as {colors.primary}.
  • A Markdown body with the rationale. Sections such as Overview, Colors, Typography, Layout, Shapes, Components, and Do's and Don'ts explain how to apply the tokens.

The format ships with a linter (npx @google/design.md lint DESIGN.md) that checks the file itself, for problems like broken token references, orphaned tokens, and contrast ratios. That covers the spec. Whether your app follows the spec is a separate question, and you can only answer it by looking at the app.

Why design token drift hides from a code review

Reading the code isn't enough to enforce a design system in React Native, because the value that reaches the screen is often decided outside the line you're reviewing:

  • Hardcoded values. A #FF5722 typed into one StyleSheet looks like a brand color but isn't the token.
  • Wrong variant. A shared Button renders its secondary radius because the screen passed the wrong prop.
  • Theme resolution. A themed value resolves through hooks and context, so the source shows a lookup, not a color.
  • Overrides. A style prop spread late in the array quietly beats the token the component meant to use.

Each of these looks plausible in a diff, and each is obvious in the rendered output. That's where Ceraph lets your agent check.

Live style inspection with includeStyles

ceraph_snapshot is the agent's structured view of the current screen: each element's role, label, on-screen bounds, and a stable ref to act on. When you pass includeStyles: true, the snapshot also carries bounded render-time styles for the visible elements it can uniquely match, covering:

  • Color: text color, background color, border colors
  • Typography: font family, size, weight, style, line height, letter spacing
  • Spacing: margin, padding, and gap
  • Shape: border widths and corner radii
  • Layout and size: flex settings, alignment, width, and height

The snapshot also reports style-coverage metadata: how many elements were eligible, how many came back styled, how many were ambiguous, and the overall ratio. The agent can see what it didn't inspect, so a partial snapshot doesn't pass as a full audit. Nested Text reports the typography and color it inherits from its parent Text, marked as inherited, so a body style set once on a paragraph is checked on every span inside it. Platform defaults aren't style props, which is why the coverage numbers and the screenshot matter. Ceraph's guidance tells the agent to pair the styled snapshot with a screen_screenshot. The numbers show what rendered, and the screenshot shows how it looks.

Ceraph doesn't parse your DESIGN.md. Your agent reads the spec and Ceraph supplies the evidence. Your design system stays in your repo and in your words. Google's format, a hand-written token table, or a Figma export all work, because the comparison happens in the agent that already reads your project.

Walkthrough: catching drift on a paywall screen

Say your DESIGN.md includes:

---
name: Acme
colors:
  primary: "#1A1A2E"
  accent: "#FF6B35"
typography:
  body:
    fontFamily: Inter
    fontSize: 16px
    lineHeight: 24px
rounded:
  md: 12px
components:
  button-primary:
    backgroundColor: "{colors.accent}"
    rounded: "{rounded.md}"
---

You ask your agent to build a paywall screen with an Upgrade button.

  1. Build and bring up. The agent writes the screen, calls ceraph_start to get the app running, and opens the paywall with screen_open_url.
  2. Snapshot with styles. It calls ceraph_snapshot({ includeStyles: true }). The Upgrade button reports a background of #FF5722 and a border radius of 8. The body text, which sets its typography directly, reports Inter at 16 with a line height of 24, which matches.
  3. Compare against the spec. The agent checks the button against button-primary: the background should resolve to {colors.accent} (#FF6B35) and the radius to {rounded.md} (12). Both drifted. A hex value copied from an old mock and a radius left over from a default.
  4. Fix at the source. It swaps both values for your theme's tokens. It doesn't patch in new literals.
  5. Confirm on the running app. A fresh ceraph_snapshot({ includeStyles: true }) shows #FF6B35 and 12. A screen_screenshot confirms the button looks right, and the coverage metadata shows the elements it checked.

Steps 2 through 5 run inside the same conversation, so the drift is fixed before the screen reaches review.

A prompt you can paste

Put this in your agent's project instructions, or add it to any UI request:

Before finishing any UI change, open the affected screen with Ceraph, call ceraph_snapshot with includeStyles: true, and check every styled element against DESIGN.md: colors, typography, spacing, and radii. Fix mismatches at the token source, re-snapshot to confirm, attach a screenshot, and report the style coverage.

Run on every visual change, this makes your design system something the agent verifies on the running app before it finishes. Your coding agent already reads DESIGN.md, and Ceraph shows it the styles the running app rendered with.

Ready to try it on your own app? Get started here.