Point it at a photo and get a named color palette as ready-to-use CSS custom properties. Unsplash search, file upload, voice input, HEX/RGB/HSL output, and shareable URLs. No account, no server, no install.
Every designer has opened a reference photo just to use the eyedropper. You sample five colors,
manually convert them to hex, name them something like --accent-1, and repeat.
Twenty minutes later you have a palette that's still not consistent with what the image actually
communicates.
Visual Chromatics does the pixel clustering for you via ColorThief, names the results in
human-readable terms,
and writes the :root {} block immediately. The output isn't just color values. It's
already CSS:
/* Extracted from a coastal landscape */
:root {
--primary: #2d5a7b; /* Deep Ocean */
--secondary: #8fb4c8; /* Sky Haze */
--accent: #d4a853; /* Sunlit Sand */
--color-4: #f2efe6; /* Sea Foam */
--color-5: #1a3a50; /* Midnight Tide */
}
Pick the workflow that fits. All three end up at the same extraction step.
Unsplash Search
Type a keyword like "autumn forest" or tap a suggestion chip. A random matching photo loads instantly. Refresh pulls a new result for the same query without clearing your extracted palette.
File Upload
Drag in any local image or browse for it. The file is read via the Browser File API and never leaves the device. No upload, no server round-trip.
Voice Search
Tap the microphone and say a concept. Annyang captures the phrase via the Web Speech API and passes it to Unsplash. Works in Chrome and Edge; degrades gracefully elsewhere.
Colors are clustered from actual pixel data, not averaged. The result reflects the palette that visually defines the image, not a muddy blend of everything in it. Choose to extract 5, 7, or 9 colors.
The code block updates live as you switch formats. Copy the full CSS block
in the format your codebase expects.
/* RGB */
--primary: rgb(194, 169, 134);
/* HEX */
--primary: #c2a986;
/* HSL */
--primary: hsl(33, 29%, 64%);
Lock the current palette before refreshing the image. Useful for testing how the same set of colors reads across different photos. Export as PNG for design handoff.
CSS block to clipboard
Share Palette encodes the full state into a URL hash. Anyone opening the link sees the same
image and palette instantly, no account needed. The last 10 palettes persist in
localStorage for quick recall.
localStorage
A single Vue component tree with no router and no state management library. All state lives in
ImageSearch.vue, broken across four focused composables so each concern stays testable
in isolation.
| Composable | Responsibility |
|---|---|
useColorConversion |
Pure functions: RGB to HEX, HEX to RGB, RGB to HSL, and approximate color naming via HSL range matching. |
usePaletteHistory |
Reads and writes the 10-item palette archive to localStorage. |
useNotification |
Manages the transient toast notification shown after copy and export actions. |
useVoiceSearch |
Wraps Annyang lifecycle (start, stop, cleanup) and surfaces a reactive
listening state.
|
| Layer | Technology | Notes |
|---|---|---|
| Framework | Vue 3 (Composition API, <script setup>) |
No router, no Vuex/Pinia |
| Build tool | Vite | Hot reload in dev, optimized bundle in prod |
| Styling | Tailwind CSS v3 | |
| Color extraction | ColorThief | Median cut clustering on raw pixel data |
| Image source | Unsplash API | Key injected at build time via Vite env var, never committed |
| HTTP client | Axios | |
| Voice | Annyang (Web Speech API wrapper) | Chrome/Edge only; feature-detected before use |
| PWA | vite-plugin-pwa | Service worker + manifest for offline use |
No data is collected or transmitted to any first-party server.
Uploaded Images
Files are read locally via the Browser File API. The pixel data never leaves the device. No upload, no CDN, no logging.
API Key Handling
The Unsplash API key is injected at build time via a Vite environment variable. It is never stored in the repository and never visible in the built output.
Palette History
The 10-item archive is stored in your own localStorage.
It stays on your device and is never read by the app server because there is no app server.
Voice Input
Voice recognition uses the browser's native Web Speech API. Audio is processed by the browser, not by any server this app controls.
Upload a screenshot, a mood board image, or a product photo. In moments you have a
named palette and a CSS block ready to paste.