uidna
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@uidnacapture the UI at example.com and rebuild it as a React project with a diff report"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
UI DNA is REA for user interfaces. REA's promise is "see a feature you like, understand how it works, down to the binary, show the evidence, build it." UI DNA's promise: see an interface you like, understand how it is structured, how it behaves and how to reproduce it, down to the token, the component and the state transition, then rebuild it as code you own, with proof.
agent asks about a target → UI DNA captures, crawls, measures, explores
→ returns a UI DNA document + evidence + unknowns
agent reconstructs, verifies, repairs, reportsContents
Related MCP server: art-director-mcp
Quick start
npm install -g @rohzzn/uidna
npx playwright install chromium
uidna setup # registers the MCP server in Claude Code, Codex and Cursor; asks first, backs up
uidna doctor # browser availability, CDP reachability, registration stateuidna setup prints the planned changes to ~/.claude.json, ~/.codex/config.toml and
~/.cursor/mcp.json, asks for confirmation and backs up every file it touches. Use
--scope project to write .mcp.json and .cursor/mcp.json in the current directory
instead, and --yes to skip the prompt. The registered command is
npx -y @rohzzn/uidna@latest serve (wrapped in cmd /c on Windows).
Manual MCP configuration, if you prefer:
{
"mcpServers": {
"uidna": { "type": "stdio", "command": "npx", "args": ["-y", "@rohzzn/uidna@latest", "serve"] }
}
}The shipped skill, skills/uidna/SKILL.md, teaches the agent the
loop. Copy it into your agent's skills directory (for Claude Code, ~/.claude/skills/uidna/).
To run the whole loop without an agent, on one page:
uidna reconstruct https://example.com ./example-clone --viewports 1280,768,390On a small site you own, following up to five same-origin pages, capturing JSON responses as data and exercising its forms with synthetic values:
uidna reconstruct http://localhost:3000 ./my-site --crawl '{"maxPages":5}' --capture-bodies json --policy formsHow it works
Step | What happens | Who decides |
Capture | Chromium loads each page at each viewport. UI DNA records the DOM, computed styles filtered to rendering properties, bounding boxes, the accessibility tree, form facts, fonts, assets, network metadata and one screenshot per state. It reads the page's stylesheet width conditions and resizes between the scanned widths to locate where the layout actually changes. With a crawl, same-origin links are followed breadth-first within a page budget; with body capture, JSON responses are stored as redacted data assets. | UI DNA |
Explore | Hover, focus, Escape, Tab, and clicks on non-submitting buttons, summaries, tabs and disclosure or menu triggers, on every page. Search boxes of tables and lists are tried with a query taken from their items, then one that matches nothing, then cleared. Links to another crawled page are followed once and recorded as navigation transitions. The | UI DNA |
Measure | Tokens come from clustering measured values, with sample counts. Component candidates come from structural fingerprints across pages, with instances, varying props, variants and a confidence derived from agreement. Header and footer shared by every page become a layout. Repeated items become collections, and each transition that narrowed or reordered them is classified as a search, filter, sort or reset with the field that explains it. | UI DNA |
Understand and annotate | The agent reads the document, names components and tokens, records what it infers and why, and authorizes assets the user owns. Agent readings are stored as | the agent |
Generate | A deterministic React + TypeScript + Tailwind + Vite project: one component per page behind react-router, semantic HTML, extracted components, tokens as CSS variables and a Tailwind theme with the located breakpoints, observed transitions as React state with the original ARIA attributes, collections rendered through search, filter and sort state, forms with the observed validation messages, typed mocks from captured data, and a Playwright suite that replays the recorded transitions. | UI DNA |
Verify | Pixel diff, SSIM, geometry, computed styles and element presence per page, state and viewport, plus the layout on both sides of every located breakpoint. Recorded transitions are replayed, including fills, blocked submits and navigations; after a search, filter or sort the generated items are compared with the original's by identity and order. The generated Playwright suite can run too. One finding per concrete difference, with the original and generated values. | UI DNA |
Repair and report | The agent edits the project against the DiffReport and re-verifies; regressions and resolved findings are tracked per attempt. A static HTML report shows the evidence. | the agent |
Every value in the document carries provenance: measured, observed, inferred (agent
only) or unknown with a reason. Nothing is rounded into a guess, and no result is a
single blended score.
What ships today
Phase 1, the single-page loop. From URL to verified React project, proven in CI with a real Chromium against Fixture A, a marketing page with a responsive navbar and hamburger menu, a hero, two call-to-action buttons, a three-card grid, an image, an FAQ accordion and a footer, at 1280, 768 and 390 pixels wide.
Two browser modes: Playwright-launched Chromium for public pages, and attach to your own Chrome over the DevTools Protocol for sessions you are authorized to analyze.
robots.txthonored, per-origin rate limits, Chromium sandbox requested (with an honest limitation when the host cannot provide one), secrets redacted before anything is stored.Twelve tools with one evidence envelope, identical over MCP and the CLI;
setupanddoctoron the CLI;--json, a config file and debug logging.A versioned, framework-neutral schema published separately as
@rohzzn/uidna-schema.The generated project builds; its build, the recorded transitions, and an injected CSS and behavior regression are each a CI test.
Phase 2, sites, forms, data, collections and breakpoints. Each capability below is a CI gate on its own fixture.
Multi-page crawl.
crawl: { maxPages, include, exclude }follows same-origin links breadth-first; cross-origin links are recorded and never followed. Pages carry their depth and the link that discovered them. Components are matched across pages, and the header and footer every page shares become one layout.Navigation transitions. A click on a link to another crawled page is recorded as a transition between the two pages. The generator wires it as a router link and the verifier replays it through the original link.
Forms. The
formspolicy fills controls with synthetic values (never real credentials; hidden and file inputs are never filled), submits the empty form to observe client-side validation and the filled form to observe the result. Validation states keeparia-invalid, the error message and the browser's validity. Every submission request is blocked, recorded as a side effect and never repeated.Data.
captureBodies: "json"stores JSON responses from fetch and XHR as redacted, size-capped data assets. The generator turns each one into a typed mock.Responsive rules. Breakpoints are located where the layout actually changes, not at the scanned widths: stylesheet thresholds are read and confirmed one pixel apart by resizing, and changes no stylesheet explains are found by bisection within a budget. Probing only resizes the page and blocks every non-GET request. The document lists each breakpoint with its bracket and condition and the layout values that change there; the generator declares those breakpoints and attributes each style change to the one that explains it; the verifier checks the generated layout on both sides of each.
Search, filter and sort. Tables, lists and card grids become collections with item identity, fields and value kinds. A search box is tried with a query taken from the items' own text; chips, tabs and column headers are clicked as usual. Each change is classified against the base items: a search with its match and fields, a filter with the field and value it keeps, a sort with its field, direction and comparator, a reset. The generated project renders the items through that state, and the verifier compares the generated items with the original's by identity and order.
Row actions. A control repeated in every item of a collection (an "Archive" button per row) is one action: once it causes a side effect, it is skipped in every other item.
Behavior tests. The generated project includes
tests/behavior.spec.ts: one Playwright test per implemented transition, asserting the observed delta. Transitions the generator did not reproduce, or that caused a side effect when observed, are skipped with the reason.verify_reconstructionruns the suite when asked.
Fixture B is an orders dashboard: a table loaded from a JSON endpoint with a search box, status chips and sortable columns, a row action that posts, and breakpoints at 600, 960 and 1100px, none of them a scanned width. Fixture C is a signup form with client-side validation, a POST endpoint and a JSON list. Fixture D is a three-page site with a shared header and footer, tabs, a pricing toggle and a cross-origin footer link.
Tools and commands
Command | Tool | Answers |
|
| What is on each page at each viewport, and where does the layout change? |
|
| What changes when I interact? |
|
| Summary, one facet, one path, or the whole document. |
|
| One node: box, style, tokens, a11y, form facts, ancestors, evidence. |
|
| Fingerprinted component candidates in stable order, matched across pages. |
|
| Token clusters with member values and sample counts. |
|
| Apply the agent's readings with |
|
| The React project, installed and built. |
|
| The DiffReport for this attempt, with regressions and resolved findings. |
|
| The static HTML report. |
|
| A portable evidence bundle with a manifest of digests. |
|
| The whole loop. |
Every tool returns the same envelope; add --json on the CLI to see it:
{
"result": {},
"evidence_id": "ev_3f9a1c7b2d4e",
"evidence": { "kind": "scan", "inputs": {}, "artifacts": [], "capturedAt": "2026-10-13T17:29:00.000Z" },
"limitations": [],
"unknowns": []
}The full catalog, generated from the contracts, is in docs/tools.md.
The UI DNA document
A UI DNA document describes an interface the way an engineer needs it described to rebuild it: pages and navigation, observed states and the transitions between them, component candidates with their instances, visual tokens with the measurements behind them, layout constraints per node, form facts and validation states, observed behavior, assets and data with origin and authorization, and what could not be observed.
{
"value": "248px",
"provenance": {
"kind": "measured",
"source": "computed-style",
"stateId": "st_01",
"viewport": { "width": 1280, "height": 800 },
"evidenceId": "ev_3f9a1c7b2d4e",
"capturedAt": "2026-10-13T17:29:00.000Z",
"confidence": 0.98
}
}Schema 0.2.0 adds pages with depth and discovery, form facts on nodes, fill and submit
actions, navigation transitions and data assets; every 0.1.0 document is still valid. The
reference is docs/ui-dna.md; a complete validated example from
Fixture A is in docs/examples/fixture-a.dna.json.
A measured run
Measured on Fixture A (http://127.0.0.1:51767/) by scan scan_20261014_13cdb7 with tool version 0.2.0:
Step | Result |
scan | 3 base states at 1280, 768, 390 px; 71 / 71 / 71 nodes; 1 asset; 113.7 s of browser time for scan and explore together |
explore (safe) | 36 interactive elements discovered, 88 interactions performed, 69 produced a new state, 44 skipped with a reason; 73 transitions, 69 derived states |
tokens | 10 colors, 17 typography styles, 11 font sizes, 12 spacing values, 4 radii, 1 shadow, 2 breakpoints |
breakpoints | located 768px (css, bracket 767–768), 1024px (css, bracket 768–1280); 2 stylesheet conditions read, 73 layout rules, 4 widths measured |
collections | 2 detected (grid of 3, grid of 3); rules: 0 search, 0 filter, 0 sort, 0 reset |
components | 7 candidates, 65 instances (largest: Component01 with 17) |
behavior | 73 observed rules; 0 limitations recorded |
verify attempt 1 | 21 findings (layout 9, typography 3, color 6, asset 3); pixel diff 1280px 0.66%, 768px 0.53%, 390px 0.80%; 73/73 replayed transitions matched; 1/1 breakpoints matched on both sides; 0 regressions, 0 resolved |
verify attempt 2 | 35 findings (layout 9, typography 3, color 20, asset 3); pixel diff 1280px 1.29%, 768px 1.61%, 390px 1.84%; 73/73 replayed transitions matched; 1/1 breakpoints matched on both sides; 14 regressions, 0 resolved |
verify attempt 3 | 21 findings (layout 9, typography 3, color 6, asset 3); pixel diff 1280px 0.66%, 768px 0.53%, 390px 0.80%; 73/73 replayed transitions matched; 1/1 breakpoints matched on both sides; 0 regressions, 14 resolved |
verify attempt 4 | 45 findings (layout 9, typography 3, color 6, asset 3, behavior 24); pixel diff 1280px 0.66%, 768px 0.53%, 390px 0.80%; 62/73 replayed transitions matched; 1/1 breakpoints matched on both sides; 24 regressions, 0 resolved |
verify attempt 5 | 21 findings (layout 9, typography 3, color 6, asset 3); pixel diff 1280px 0.66%, 768px 0.53%, 390px 0.80%; 73/73 replayed transitions matched; 1/1 breakpoints matched on both sides; 0 regressions, 24 resolved |
Pixel ratios depend on the fonts of the machine that rendered them; the counts do not.
Attempts 2 and 4 are the CI loop's injected regressions (a changed primary color, then a
script that swallows clicks); attempts 3 and 5 are the reverts. The 21 baseline findings
are all the unauthorized illustration rendered as a labeled placeholder, by design. The
table is written by scripts/readme-numbers.ts from the scan that produced it.
Authorized use
Scan interfaces you own or are allowed to analyze. UI DNA never bypasses authentication,
CAPTCHAs, anti-bot measures or access controls, never stores credentials, and never
redistributes third-party assets: unauthorized assets become labeled placeholders until
you mark them authorized with annotate_dna. See DISCLAIMER.md and
SECURITY.md.
Exploration blocks every non-GET request for the whole run, including beacons sent while
a page unloads: an action that tries to send one is recorded as a side effect and never
repeated, and the request never reaches its server. A page that loads its content with
POST requests shows its error state instead. The forms policy types synthetic values into
the page and runs its submit handlers; search boxes are typed into with text taken from the
page's own items. Use them only on interfaces you may test that way. A crawl stays on the seed's origin, honors robots.txt
and stops at its page budget.
To analyze an authenticated app, start your own Chrome with --remote-debugging-port=9222,
open the page, then uidna scan --cdp-endpoint http://localhost:9222. The session stays
yours; UI DNA reads the page and performs the same safe interactions.
Limitations
A crawl follows same-origin
<a href>links only, up to 50 pages. Navigations made by scripts are blocked and reported, not followed.Server responses to form submissions are never observed, because the requests are blocked. Success states that depend on the server are reproduced only as far as the page showed them without one, and the generated README says so.
<iframe>content and shadow DOM are not entered; they are reported as limitations.Inline
<svg>markup is not captured; such nodes become placeholders.Breakpoints are located from readable stylesheets and by resizing between the scanned widths. Cross-origin stylesheets, container queries and continuously varying values (
clamp(),vw) are not breakpoints; a threshold above the widest or below the narrowest scanned width is read from the stylesheet but not seen. When two located breakpoints fall between the same scanned widths, a property that changes twice there is generated at the later one.Collections are explored through search boxes outside forms, and through the chips, tabs and column headers the click round already clicks. Selects, checkboxes, combined filters, server-side search, pagination and load-more are not explored or reproduced; generated collections show the captured items, not the endpoint's data.
Spacing tokens are used values: a
margin: autoshows up as the pixel margin it produced.Hover and focus transitions are reproduced as CSS variants at every viewport. Click toggles are reproduced, sharing their state across section files when the changed nodes live elsewhere; component instances changed together with nodes outside them are rendered inline instead. Every behavior the generator could not implement is listed in the generated README and skipped in its Playwright suite.
The generator is a baseline, not a finished product: names are placeholders and the agent is expected to repair against the DiffReport.
Verification compares at the scanned viewports with system fonts; cross-machine pixel diffs reflect font rendering differences, which is why findings carry the measured values rather than a single score.
Development
packages/schema/ @rohzzn/uidna-schema: Zod schema, JSON Schema, types, changelog
src/domain/ fingerprints, clustering, colors, safe-action and forms policy, Result, budgets
src/contracts/ tool contracts and the canonical catalog (docs/tools.md is generated)
src/browser/ Playwright launch + CDP attach adapters, capture, robots, redaction, JSON bodies
src/analysis/ normalization, token clustering, components, layout, multi-page assembly
src/explore/ interaction rounds, navigation, form chains, state graph, revert
src/generate/ UI DNA document → React project, router, forms, mocks, Playwright tests
src/verify/ render, visual + behavioral compare, generated-test runs, DiffReport, HTML report
src/application/ workflows shared by the CLI and the MCP server, crawl, scan store
src/server/ MCP adapter
skills/uidna/ SKILL.md
fixtures/ A (marketing page), B (dashboard), C (signup form and data), D (three-page site)
tests/ end-to-end loops on Fixtures A, B, C and D, and the MCP server over stdionpm ci
npm run build
npm run test:unit # real Chromium against the fixtures and synthetic pages, no module mocks
npm run test:e2e # the Phase 1 and Phase 2 loops and the MCP server (about 35 minutes)
npm run docs:catalogConventional Commits, ESM TypeScript in strict mode, Zod at every boundary, tagged errors
with Result, no any, no non-null assertions, no floating promises. See
CONTRIBUTING.md.
License
MIT. See LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Captured web interfaces, screenshots, flows and structured evidence for AI coding agents.
See the rendered web: design tokens, fonts, animation timings, WebGL shaders and 3D from any URL.
Hosted browser for AI agents: screenshots, post-JS DOM, console, WCAG. No install, no API key.
Give agents eyes on any web page: structured context, and changes explained in plain language.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI coding agents to see and interact with real Chrome pages through structured DOM inspection, targeted screenshots, recordings, and human-in-the-loop approvals across major coding-agent hosts.MIT
- AlicenseNot gradedqualityBmaintenanceProvides coding agents with local tools to inspect project UI inventories, propose and compare visual direction boards, compile versioned design contracts and DTCG tokens, retrieve section-specific blueprints, and audit running interfaces with browser evidence including screenshots, accessibility findings, and overflow measurements.MIT
- AlicenseAqualityBmaintenanceEnables AI coding agents to see, measure, and verify web pages through a real Chrome browser, including screenshots, responsive layout and accessibility audits, pixel diffing against baselines, secure logins, and deployed-fix verification.271MIT
- AlicenseNot gradedqualityBmaintenanceEnables coding agents to run an evidence-backed visual QA loop for browser interfaces, including inspecting a running app, retrieving findings with screenshots, and rechecking only the captures affected by a fix.MIT