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
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
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.
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.















