AI PROJECTS / Roadrunner HR CRM Dashboard

Design-to-code loop that holds.

Roadrunner CRM Solo Project
Closing the design-to-code loop end to end

A live, AI-assisted CRM designed and built solo, closing two problems at once: the design-to-code drift that breaks handoffs, and the dirty data inside every CRM.

AI Product Design

Design Systems

Front-End Development

Design-to-Code

CRM

Client / Self-initiated · built to sell on Etsy

Data + AI / 11 free public providers · free-tier AI · zero paid APIs

Role / Product design · front-end build · deploy

Timeline / 3 days Acme · 5 days Roadrunner v1 · 1 day polish

Scope / Working CRM · 8 modules · live

Stack / Figma MCP · Claude Code · Next.js 16 · TypeScript · Tailwind

$0

$0

11

11

8

8

5 DAYS

6 1

INFRA COST,

HOSTING & SSL

TEAMS

ALIGNED

PUBLIC PROVIDERS,

NO FAKES

MODULES LIVE,

ONE DOMAIN

EMPTY REPO

TO LIVE V1

THE CONSTRAINT

Two problems followed twelve years of CRM work. Design and code never matched: Figma handed off, engineering rebuilt it close enough, and the tokens drifted apart within a few sprints. Every CRM shipped carried the second problem too, dirty data, the duplicate records and stale contacts and sources nobody could trace.


Roadrunner was self-initiated, with no team, no client, and no users to interview. The build ran on free-tier AI and eleven public data providers, zero paid APIs, one designer across design system, front end, and deploy.


The bar was a live product, not a prototype. AI had to fire against real APIs, records had to save to a real backend, and any hiring manager had to be able to click through and try to break it.

WHAT I DID

The design-to-code loop closed by defining Acme tokens once. Figma variables and Tailwind custom properties referenced the same values, so Figma MCP and Claude Code generated against the source the design already used, with no translation step to drift. Claude handled the generation while the judgment seat stayed put, and every grid pattern traced to twelve years of watching HR and comp teams ask for saved views, column pinning, and density control that were not there. The AI suggestions wired to real public sources with per-field attribution, because an earlier pass that faked a duplicate detector against a hardcoded name pool was replicating the exact dirty-data problem the product existed to solve.

DELIVERABLE: Token Library

A running token library engineering installs.

Acme tokens are defined once. Figma variables and Tailwind CSS custom properties reference the same source, so engineering installs, imports, and ships with no translation step and no drift.

When a token changes in Figma, the CSS variable updates, and every component using it retints. The loop holds in both directions.

TOKEN FILE - GLOBAL.CSS

TOKEN FILE - GLOBAL.CSS

One query. Eleven sources. Live.
QUERY"Tom Coffee"ClearbitGitHubWikidataSECGLEIFORCIDGravatarOpenCorpCos.HouseSAMHunter
One query fans out to eleven free public sources in parallel. Each returns independently. Source attribution is captured per field.

THE GRID WORK

Twelve years of pattern literacy, shipped into one product.

The grids carry the patterns enterprise users keep asking for and rarely get. Each screen below shipped because twelve years inside HR and comp tools showed exactly where the default grid runs out.

Duplicate detection at intake. As a record is typed, public registers surface likely matches to merge before a duplicate is created.

Column and density controls. Show the fields that matter, fit more rows when the work needs it.

Help, tips, and guided tours live in one on-demand panel, not a one-time install a user clicks past.

A status and tag system, color-coded and legible across a dense grid.

Undo on every destructive action, confirmed by toast.

WHAT I DELIVER TO ENGINEERING

Because the loop closes, I hand engineering deliverables they can consume directly instead of specs to translate.

A senior designer who has closed the design-to-code loop doesn't move stories from "in design" to "in dev." They move them from "in design" to "merged," because the artifacts engineering receives are already the ones they would build. That is the difference between one sprint and three.

The loop that finally closed
FIGMAVariables · componentsvia Figma MCPACMETOKENSone sourceCODETailwind CSS varsvia Claude CodeREAD · WRITEREAD · WRITE
One token. Rendered in Figma. Rendered in code. The token moves between both surfaces in real time — no handoff, no drift, no translation.

WITHOUT THE LOOP

What engineering gets today on most projects

  • Figma file with redlines to measure

  • PNG exports of states

  • Hex codes copy-pasted into CSS

  • Slack threads clarifying what a component means

  • Design drift discovered three sprints later

  • QA tickets retrofitting accessibility

  • Coordination meetings to align tokens

WITH THE LOOP

What engineering gets from me

  • Running token library — install and import

  • Live React components next to Figma frames

  • Figma-to-code prop mapping, one page per component

  • Validation rules authored on the design side

  • Accessibility baked into the system

  • AI-generated first drafts with judgment applied

  • One master doc, not thirty Slack threads

OUTCOMES

A live working product, open for anyone to try.

The Loop Held

Figma tokens and Tailwind variables resolved to the same values. Zero handoff artifacts were written during the build.

Every AI claim is inspectable

Provider badges render next to every suggested field. Any claim can be traced to a real public source in one click.

Polish was disciplined

13 UX decisions shipped in one day. Average rationale: two sentences per decision. No feature creep.

Real AI, not a Figma prototype

The AI fires against real APIs. Custom subdomain, open-source repo. Anyone can click through and try to break it.

roadrunner-crm.paulwentzellux.com

What I'd do differently

Real providers belonged in from day one, since the fake-pool rebuild proved instructive but expensive. Validation should have shipped on every intake surface before the first AI feature, not after, and the Postgres backend should have landed with v1 rather than browser-local storage. The hardest lesson was state management: visual-only edits batch safely, but state-engine changes each need one isolated commit with a verified diff before push.

COPYRIGHT © 2026 | Paul Wentzell UX