All work
chrome extension · tool

Color Palette Detector — Chrome Extension

A Manifest V3 Chrome extension that extracts, analyzes, and exports color palettes from any image or live website — 100% client-side, no backend, no telemetry. Median-cut quantization in a Web Worker, WCAG contrast checks, harmony generators, and exports to CSS, Adobe ASE, Markdown and HTML.

role
Solo — design to build
team
Solo (1)
timeline
2026 → built, pending Web Store listing
domain
Developer tool / Browser extension

Overview

Color Palette Detector is a Manifest V3 Chrome extension that extracts, analyzes, and exports color palettes from any image or any website you're viewing. It runs entirely in the browser — no backend, no accounts, no telemetry — and presents itself as a dark-mode-first side panel that re-tints its own accent to the palette you just pulled.

I built it as a self-contained product and a showcase piece: a real MV3 extension with the four execution contexts wired together properly, hand-rolled color math, and a test suite (unit + end-to-end) rather than a toy.

The problem

Designers and front-end engineers constantly need to answer "what colors is this?" — from a reference image, a competitor's site, or their own running app — and then get those colors out in a usable format. Most tools either only accept an uploaded image, require a paid account, or phone home with what you feed them.

I wanted one tool that could read colors from a live page (including colors set by JavaScript at runtime, which a static CSS scan misses), quantify the dominant palette honestly, check contrast against WCAG, and export to the formats people actually paste into code and design tools — all without a single network request that isn't the user's own action.

Constraints

Architecture

An MV3 extension runs code in isolated contexts. This one uses four, each with a single job — the side panel orchestrates, the worker does the pixel math, the service worker handles privileged fetches, and the scanner is injected only on demand.

┌─────────────────┐     message      ┌────────────────────┐
│  Content script │◄────────────────►│   Service worker    │
│  (DOM scanner)  │   on-demand only │  (bg · image fetch) │
└─────────────────┘                  └─────────┬──────────┘
     injected via                              │ message
  executeScript({func})                        │
                                     ┌──────────▼──────────┐
                                     │     Side panel       │
                                     │   React + Zustand    │
                                     │        spawns        │
                                     │   ┌──────────────┐   │
                                     │   │  Web worker  │   │
                                     │   │ median-cut,  │   │
                                     │   │OffscreenCanvas│  │
                                     │   └──────────────┘   │
                                     └─────────────────────┘

upload / drag-drop → ArrayBuffer ─────────────► worker → palette
image URL → SW fetch → ArrayBuffer (base64 hop) ► worker → palette
scan page → executeScript → ScanRaw → normalize (culori) → roles

Every color is normalized to one Color type (hex / rgb / hsl / cmyk) at the point of entry, so the UI never juggles raw color strings.

Key decisions & trade-offs

Status & what's next

The extension is built and working — load the dist/ folder unpacked in Chrome and the full flow runs: upload or scan → dominant colors (with 60-30-10 coverage) → harmony generators → WCAG contrast badges → export to JPEG, CSS variables, Adobe .ase, Markdown, and a self-contained HTML report. It's covered by a Vitest unit suite over the color logic and scanner plus a Playwright end-to-end test that drives the real built extension.

It is not yet on the Chrome Web Store — publishing requires a paid developer account, which I haven't set up yet. Before listing, the one change I'd make is migrating <all_urls> (a dev-mode convenience for the on-demand fetch/scanner) to optional_host_permissions requested per-action, so the store listing asks for the narrowest possible permissions.

The full source is public on GitHub: github.com/frankydinh/color-palette-detector — clone it, run npm install && npm run build, and load dist/ unpacked.

Free and open source while the Web Store listing is pending.

Chrome ExtensionManifest V3ReactTypeScriptWeb WorkerViteZustand