Skip to main content
Design & UICoding

Screenshot To Code

Turns a screenshot, mockup, Figma export, or photo of a UI into working front-end code - React + Tailwind CSS v4 by default, or Next.js, Vue, or plain HTML/CSS - matching layout, spacing, colors, and typography, then renders the result and compares it against the image to close visual gaps. Use whenever the user shares an image of a website, app screen, dashboard, component, or wireframe and wants it built, cloned, recreated, or "made real", or says "code this up", "build this design", or "match this screenshot".

View source3 files · 11 KB

What it does

# Screenshot to Code

Recreate the UI in the image as clean, responsive, accessible code, then check the render against the image.

## Workflow

1. **Pick the target stack.** If the user is inside a project, match it: read `package.json` for React/Next/Vue and the Tailwind version, and reuse existing components, tokens, and icon libraries. Do not ask when the repo already answers it. With no project:
   - Single screen or quick prototype: one self-contained `index.html` (Tailwind via the browser build, see [references/stack-setup.md](references/stack-setup.md)).
   - App or multi-screen: React + TypeScript + Tailwind v4 on Vite.
   - User mentions Next.js, SSR, or routing: Next.js App Router.

2. **Write a short spec before coding.** Looking at the image, note:
   - Layout regions top to bottom (nav, hero, sidebar, grid, footer) and the grid or flex structure of each
   - Design tokens: 3-6 colors as hex, font family guess and the type scale, spacing rhythm (usually multiples of 4px), corner radius, shadow style
   - Repeated components (cards, list rows, buttons) that should be one component with props
   - What the image cannot show: hover and focus states, mobile layout, real data, content below the fold

   Estimate sizes from the image resolution. If the screenshot is 2x (a Retina capture 2880px wide is a 1440px layout), halve the pixel measurements.

3. **Build.** Use semantic elements (`header`, `nav`, `main`, `section`, `button`, `a`), extract repeated pieces into components, and put tokens in one place (Tailwind v4 `@theme` or CSS custom properties) rather than scattering hex codes. Use real text from the image, not lorem ipsum. For images and logos you cannot extract, use sized placeholders with descriptive `alt` text. Use an icon library the project already has (default: `lucide-react`), not hand-drawn SVGs or emoji.

4. **Make it responsive.** Build for the screenshot's viewport first, then define how it collapses: multi-column grids stack, navs become a menu button, and type scales down with `clamp()` or responsive utilities. If the screenshot is mobile, go the other direction.

5. **Render and compare.** If you can run a browser (Playwright, a headless browser, or a browser tool), screenshot the result at the source image's viewport width and compare side by side. See [references/visual-check.md](references/visual-check.md). Fix the largest differences first: layout and alignment, then spacing, then type size and weight, then color. Two or three passes is usually enough; stop when remaining differences are at the level of font rendering.

6. **Deliver.** Provide the files, how to run them, and a short list of assumptions (fonts guessed, states invented, content inferred). Name anything that needs real assets.

## Stack notes

- **React 19**: function components with TypeScript prop types. `propTypes` checks were removed from React 19; do not add them. `forwardRef` is not needed for passing `ref` to function components.
- **Tailwind CSS v4**: configuration lives in CSS. Use `@import "tailwindcss";` and `@theme { --color-brand: #...; }`, not a `tailwind.config.js` and not the v3 `@tailwind base/components/utilities` directives. Custom tokens become utilities automatically (`bg-brand`).
- **Next.js (App Router)**: pages in `app/`, components are Server Components by default. Add `"use client"` only to components that use state, effects, or event handlers.
- **Create React App** is deprecated. Use Vite for plain React.

Setup commands for each stack are in [references/stack-setup.md](references/stack-setup.md).

## Worked example

Input: a 1440px-wide screenshot of a pricing section - centered heading, three plan cards with the middle one highlighted, feature checklists, and a button per card.

Spec:
- Regions: heading block, then a 3-column card grid, max width about 1100px, 24px gap
- Tokens: background `#0B1220`, card `#111A2E`, accent `#3B82F6`, text `#E5E7EB`, muted `#94A3B8`; Inter-like sans; radius 12px
- Components: `PlanCard` with `name`, `price`, `features[]`, `highlighted`, `cta`
- Unknowns: hover states, monthly/annual toggle behavior, mobile layout

Build: `PricingSection.tsx` mapping a `plans` array into `PlanCard`; `highlighted` adds an accent border and a "Most popular" label; `grid-cols-1 md:grid-cols-3`. Check icons from `lucide-react`.

Compare: the first render has cards 40px too tall because of button padding, and the heading weight is 600 against a 700 in the image. Fix both, re-render, and deliver with an assumptions list: toggle not built, font assumed Inter.

## Failure modes

- **Guessing the stack** when the repo already defines it, or mixing Tailwind v3 config into a v4 project.
- **Absolute positioning to force a pixel match.** It breaks on the first resize. Use flex and grid, and accept small differences.
- **One giant component.** Anything that repeats three times is a component with props.
- **Invisible states.** Buttons and links need hover and `focus-visible` styles even though the screenshot cannot show them. Inputs need labels.
- **Color drift.** Sample colors from flat areas of the image, not anti-aliased edges or gradients, and check text contrast meets WCAG AA (4.5:1 for body text).
- **Claiming a match without looking.** If you could not render the result, say the comparison was not done.
Read the full SKILL.md on GitHub

More design & ui skills