Reverse-engineer any app or site UI into pixel-accurate responsive code.
Read the skill at https://ai-skills-vault.pages.dev/skills/clone-ui-from-screenshot.md and install it as a skill in your agent. Follow it exactly, including its checklists. Then ask me the questions it requires and do the work.
Given one or more screenshots of an app or website, produce working front-end code that matches it - layout, spacing, type, colour, states and responsive behaviour.
Ethics and law: clone for learning, for migrating your own product, or for internal reference. Do not ship a pixel-identical clone of another company's brand, logos or copyrighted illustrations, and do not use it to impersonate a service or phish users. Reproduce layout and interaction patterns; replace brand assets, copy and imagery with your own.
List what you actually have:
If the user gave only one screenshot, say plainly which states you are inventing.
Work at a fixed reference width: 390 CSS px for mobile, 1440 for desktop. Convert every measurement to that width.
Extract and write down:
Record all of it as CSS custom properties. This token block is the contract the rest of the build obeys.
:root {
--bg: #0B0B0F;
--surface: #15151C;
--surface-2: #1D1D26;
--text: #F5F5F7;
--text-muted: #9A9AA8;
--border: #26262F;
--primary: #5B5BF5;
--on-primary: #FFFFFF;
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 16px;
--space-1: 4px; --space-2: 8px; --space-3: 12px;
--space-4: 16px; --space-5: 24px; --space-6: 32px;
--font: -apple-system, "Segoe UI", Roboto, sans-serif;
--shadow-card: 0 1px 2px rgba(0,0,0,.06), 0 8px 24px rgba(0,0,0,.08);
}
Walk the screenshot top to bottom and name every element as a component with its variants:
AppHeader, SearchBar, CategoryChip (default/selected), ProductCard (default/sale/sold-out), TabBar (4 items), EmptyState, Skeleton.
For each: props (data in), states, and whether it is shared. Anything appearing twice becomes a component. Anything appearing once stays inline until it repeats.
Build the whole screen in grey boxes at correct sizes. Screenshot it next to the original at the same width. Fix layout and spacing while it is still grey - this is where 80% of "it looks off" actually lives.
Only after the grey skeleton matches: apply tokens, then type, then icons, then imagery.
Decide, do not guess:
clamp() for headings, minmax() for grids, aspect-ratio for media, gap in place of margins between siblings.Never fix a height on a text container. Never use a fixed px width on a card grid.
Do at least two loops. One loop always leaves 5-10 small errors that a user notices as "cheap".
For each interactive element: hover (web), focus-visible (always), active, disabled, loading. Focus rings are not optional - use outline: 2px solid var(--primary); outline-offset: 2px.
Add the states the screenshot did not show but the product needs: empty list, error banner, skeleton loading, long-text truncation, offline. Say explicitly which ones you added.
button for actions, a for navigation, nav/main/header landmarks.alt="" on decoration.prefers-reduced-motion for every transition.Deliver in this order:
tokens.css - the variable block.NOTES.md listing what was measured, what was invented, and what is still off by design.| Symptom | Cause | Fix |
|---|---|---|
| Everything looks 10% too big | Measured at 3x without dividing | Divide by DPR |
| Spacing feels tight/loose | Margins used instead of gap | Switch to gap and one spacing scale |
| Colours look muddy | Sampled a compressed JPEG | Sample flat areas, round to nearest 5% |
| Text wraps differently | Font substitution | Match the metric-compatible font or set letter-spacing |
| Looks flat | Missing subtle border/shadow layer | Add 1px border at 8% or a 2-layer shadow |
| Responsive breaks | Fixed widths | Fluid units and minmax grids |
Read the skill at the URL above and follow it exactly. I will attach screenshots. Stage 0: tell me what is missing (states, breakpoints, dark mode). Stage 1: output the measured token block. Then build the grey skeleton, then components, then the page. Do two pixel-diff verification loops and report every delta as a number before you call it done.