wireframe-to-react
4-phase workflow to convert wireframe HTML into production React with visual parity gate and screenshot verification.
wireframe-to-react
Use this skill when converting an approved wireframe HTML file into a production React component for Floom.
The goal is fidelity first: extract the wireframe's visual contract, map it into the existing Floom app patterns, then verify with TypeScript and token audits before opening a PR.
Inputs
- Approved wireframe HTML path or URL.
- Target React route/component path.
- Any explicit Federico approval notes, especially for hero, headline, subcopy, or first-viewport visual changes.
Non-Negotiables
- Do not silently change locked hero content, hero visual, eyebrow, subcopy, or hero card.
- Use
var(--v0-*)design tokens only for colors, shadows, radii, fonts, and borders. - Do not use Tailwind classes.
- Use CSS modules, scoped CSS, or the existing local CSS pattern for the target area.
- Use
mascotDataUri()from@/lib/mascotfor avatars/mascots. Do not callcreateAvatar(...)directly. - Preserve Next.js SSR safety with an
isMountedguard when rendering client-only animation, browser-only measurement, randomization, or time-dependent UI. - Use
useReducedMotionfor motion-sensitive animation paths. - Keep web thin: React UI calls existing/public API routes and never reads local user disk paths.
- Keep copy non-technical and Floom v0 aligned: receiver path first, no terminal-forward hero, no "Claude" alone.
Phase 1: Extract Visual Contract From Wireframe HTML
Read the wireframe as a contract, not inspiration.
- First viewport composition and content order. - Exact text content, hierarchy, and emphasis. - Layout grid, spacing rhythm, alignment, max widths, and responsive breakpoints. - Card, panel, toolbar, modal, or repeated item structure. - Button/link labels, states, and destinations. - Image, mascot, icon, and illustration usage. - Motion timing, reveal order, hover states, and reduced-motion fallback. - Mobile behavior and any content that must remain visible above the fold.
- Backgrounds: --v0-cream, --v0-cream-2, --v0-cream-3. - Text: --v0-ink, --v0-ink-2, --v0-muted, --v0-muted-2. - Accent: --v0-emerald, --v0-emerald-2, --v0-emerald-3, --v0-emerald-soft, --v0-emerald-tint. - Lines: --v0-line, --v0-line-soft. - Terminal/code: --v0-term-, light cream terminal only. - Type: --v0-font-display, --v0-font-body, --v0-font-mono. - Radius/shadow: --v0-radius-, --v0-shadow-, --v0-glass-.
- Inspect the HTML structure and CSS.
- Extract the visual contract into notes:
- Identify Floom design token mappings from
/root/floom/DESIGN.md: - Mark any mismatch between wireframe and Floom source-of-truth docs as a product/design question before implementation.
Output from this phase: a concise contract summary that can be checked against the final screenshot.
Phase 2: Read Target Context
Before editing, inspect the target implementation and its callers.
- useReducedMotion - isMounted - mascotDataUri - framer-motion usage - CSS token usage - buttons, pills, glass cards, and responsive sections
- Read the existing route/page/component files.
- Trace imports, shared components, stylesheets, CSS modules, and tests.
- Check whether the target is a server component or client component.
- Find existing local patterns for:
- Confirm no web code imports from
cli/ormcp-sync/.
Output from this phase: the exact files to edit and the existing patterns being followed.
Phase 3: Generate React Component
Implement the wireframe as production React, scoped to the target area.
Component Rules
- Add
"use client"only when client behavior is required. - If client-only rendering is required, initialize:
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
setIsMounted(true);
}, []);
- Gate browser-only or time/random-dependent UI behind
isMounted. - Use
useReducedMotion()and provide a non-animated path. - Prefer existing Floom components and utilities over new abstractions.
- Keep props typed and narrow.
- Keep repeated data in typed arrays only when it simplifies rendering.
- Keep comments rare and only for non-obvious constraints.
Styling Rules
- backgrounds - text colors - borders - shadows - radii - fonts - terminal/code blocks
- Use
var(--v0-*)tokens only. Do not introduce raw hex, rgba, named colors, Tailwind utilities, or one-off palette values. - Use CSS variables from
DESIGN.mdfor: - Avoid dark terminal blocks. All terminal/code visuals use the light
--v0-term-*palette. - Preserve glass treatment using Floom's existing card classes or equivalent tokenized CSS.
- Use responsive constraints (
clamp,minmax,aspect-ratio,min-height,max-width) so content does not overlap or resize unexpectedly. - Do not use nested cards unless the target pattern already requires it.
Floom-Specific Patterns
- Mascots/avatars:
import { mascotDataUri } from "@/lib/mascot";
const mascotSrc = mascotDataUri({ size: 160 });
- Motion:
import { useReducedMotion } from "framer-motion";
const reduceMotion = useReducedMotion();
- Animation variants must respect
reduceMotion. - Hero, first-viewport, and conversion copy require exact approval alignment.
- Web-only save/add/share flows must have a no-CLI path.
Output from this phase: edited React and style files matching the extracted visual contract.
Phase 4: TypeScript Build Check And Token Audit
Verification is mandatory before reporting completion.
- TypeScript check. - Lint or build command used by the repo. - Targeted tests when available.
- Run the relevant checks from the Floom web package:
- Audit changed files for forbidden styling:
rg -n "#[0-9A-Fa-f]{3,8}|rgba\\(|rgb\\(|tailwind|className=.*(bg-|text-|grid-|flex-|rounded-|shadow-)" web/src
- Confirm every intentional color/font/radius/shadow maps to
var(--v0-*). - Confirm no direct
createAvatar(call was introduced. - Confirm
mascotDataUri(is used for mascots/avatars. - Confirm
useReducedMotionis present when animation is present. - Confirm
isMountedis present when browser-only, random, time-based, or hydration-sensitive UI is present. - Run a fresh browser screenshot for UI work and compare it to the phase 1 contract.
- If a screenshot only shows loading, skeletons, or a missing changed element, keep working.
Output from this phase: exact commands run, relevant output, and screenshot path when UI changed.
Phase 5: PR Creation
Open a PR only after local verification passes.
- Summary of the wireframe implemented. - Files changed. - Verification commands and outputs. - Screenshot path or URL for UI changes. - Any design/product defers. - Self-roast section.
- Review
git difffor scope, clarity, and unintended changes. - Confirm no
.env*, secrets, generated junk, or unrelated files changed. - Commit with a focused message.
- Push the branch.
- Create a PR with:
Self-Roast
Every final report and PR description includes a short "what's still not amazing" section with at least three concrete observations.
Use this format:
### What's still not amazing
- ...
- ...
- ...
These are not excuses. They are the remaining quality gaps visible after implementation and verification.
Done Criteria
- The React implementation matches the extracted wireframe contract.
- The implementation follows existing Floom code patterns.
- TypeScript/build checks pass.
- Token audit passes with no unapproved raw colors or Tailwind.
- Mascots use
mascotDataUri(). - Motion respects
useReducedMotion. - SSR-sensitive UI uses
isMounted. - Browser screenshot verifies the actual changed UI, not a loading state.
- PR exists with verification evidence and self-roast.
wireframe-to-react into Claude, Codex, Cursor, Kimi, and OpenCode.