← Back to home

Style Extractor

A Website's Design System From One Link

Role: Engineering + DesignStack: Next.js, FastAPI, ClaudeWebsite: style-extractor-chi.vercel.app ↗

Overview

You land on a site and love how it looks: the colors, the type, the whole feel. Finding out what they actually used means opening devtools, digging through stylesheets and copying hex codes one at a time.

Even then you get a pile of values with names like --color-bg-panel or --ds-gray-1000, and no idea which one is the background, which one is the text, and which one is the brand color.

I wanted to paste a link and get the design system back, already sorted and ready to use.

That idea became Style Extractor.

What It Is

Style Extractor pulls out a website's design system from a single URL, ready to explore and export into your next project.

Paste a link and it reads the site's styles, names every color by the job it does (background, surface, text, primary and so on), lays out the fonts and type scale, and gives you the whole thing as code.

The page itself takes on the site you extracted, so you see the palette working together before you copy any of it.

Features

Palette By Role

Every color gets a role, a name and the variable it came from. Hover a card and it reveals the name, the hex value and how often the site uses it, so you can tell a core color from a one-off.

Fonts

The heading, body and mono fonts are shown in their own typeface, with the full alphabet and numbers, so you can judge them as type instead of as names.

Type Scale

The font sizes the site leans on, with their weight, line height and letter spacing, each written out in that size. The biggest sizes always make the list, so the headings show even on sites where small body text is used far more often.

Export

One click copies the system as CSS variables, a Tailwind v4 theme, shadcn tokens, Figma design tokens or JSON, so it drops straight into a new project.

How It Works

The backend reads the same files a browser downloads, works out what the values mean, and streams each step to the frontend as it happens.

Fetch
Downloads the page and every stylesheet it loads, including imported ones and inline styles.
Read
Pulls out every color and CSS variable, resolves variables that point to other variables, and splits light values from dark ones.
Count
Counts how often each color, font and size is used, so the result reflects what the site actually leans on.
Name
Claude gives each color a role and a name, choosing only from colors found in the CSS.
Export
The named palette, fonts and type scale are turned into CSS, Tailwind, shadcn, Figma tokens or JSON.

Architecture

Most of the work is plain parsing. The model only does the one part that needs judgment: naming.

Python + FastAPI: Fetches the site and parses its CSS. Results stream to the frontend as newline-delimited JSON events, and those events drive the status you see while it works.
Claude API:Names the palette through a forced tool call, so the answer always comes back in the same shape. Any color the model returns that isn't in the site's CSS is thrown away. Gemini is kept as a fallback if Claude fails.
Next.js + Framer Motion: The frontend runs the thinking orb, the theme change, the swatch reveals and the layered Export and Type Scale cards.
Vercel: The frontend and the Python backend deploy together as one project on one domain.

Trade-offs

  • Reading CSS, Not Rendering The Page. Fetching stylesheets directly is fast and cheap, with no headless browser to run. The cost is that sites which build their styles in JavaScript at runtime return almost nothing. When that happens the app says so instead of guessing.
  • Counting Instead Of Seeing.How often a value appears in the CSS is a good guide to what matters, but it isn't the same as how much of the screen it covers. A color used in one big hero can count for less than a border used everywhere.
  • A Model For Names Only. Letting the model pick roles makes the palette readable, but models can make things up. Limiting it to colors that exist in the CSS keeps every value real, even when a role is a judgment call.

Design Decisions

The output is someone else's design, so the interface stays quiet and lets their colors and type do the talking.

  • One Input, Bottom Of The Screen.The input sits where it sits in chat apps from the first frame, and stays docked there once results load, so there's nothing to find.
  • Show The Work. While it runs, the thinking orb shows each step: fetching the site, reading its stylesheets, naming its colors. The wait feels like progress instead of a spinner.
  • The Page Becomes The Site. When results land, the background, text and borders change to the extracted palette, so you see it in use rather than as a list of swatches.
  • Flat Cards. No drop shadows. Cards get a thin hairline and a small lit corner in their own color, so nothing competes with the palette being shown.
  • Layered Export.Export sits in front of the type scale and overlaps it, so the code and the type you're copying stay side by side.