Building tools. Learning to build tools. Learning to build learning tools.
What Color Identity does, what you’ll learn, and how this tutorial is organized.
Color Identity is a VS Code extension that automatically gives each workspace a unique, harmonious color identity. Open three projects side by side and you can tell them apart at a glance — the title bar, activity bar, and status bar each carry a tint derived from the workspace’s folder name.
Unlike extensions that let you pick arbitrary colors, Color Identity derives its palette from two inputs: a deterministic hash of your folder name (so the same project always gets the same hue) and your active color theme (so dark themes get dark tints, light themes get light tints, and the colors never clash with the rest of your editor).
The extension is small — six TypeScript files, around 690 lines of code total, with zero runtime dependencies. But it covers a surprising range of topics: VS Code extension APIs, HSL color theory, deterministic hashing, PNG file encoding from scratch, event-driven reactivity, and workspace settings management. That’s what this tutorial is about.
This tutorial teaches three subjects in parallel:
| Extension VS Code API | Color Color Science | Arch Architecture |
|---|---|---|
| package.json manifest — Declaring commands, configuration, and activation events. | HSL color space — Why hue/saturation/lightness is the right model for theme-aware color generation. | Shared types — Defining interfaces that keep six files in sync without circular dependencies. |
| QuickPick API — Building a picker with icons, separators, and custom input flow. | djb2 hashing — A classic string hash that maps workspace names to hues deterministically. | Settings merging — Writing to workspace config without clobbering other extensions. |
| Event listeners — Reacting to theme changes and configuration changes. | HSL-to-hex conversion — The math that turns color theory into #rrggbb strings. |
PNG encoding — Building a valid PNG from raw pixels using only Node’s zlib. |
| Status bar items — Adding interactive indicators to the VS Code chrome. | Theme profiles — Deriving saturation and lightness ranges from the active theme kind. | CRC-32 checksums — The integrity mechanism every PNG chunk requires. |
You need:
If you’ve never written a VS Code extension before, this tutorial starts from scratch and explains every API as it appears. You don’t need to run through Microsoft’s “Your First Extension” guide first, though it won’t hurt.
Sections are tagged with one of three labels:
Like the other tutorials on this site, this one explains an existing project rather than having you type code line by line. Every section walks through real code from the Color Identity source, explains each decision, and highlights the tradeoffs. You’re encouraged to have the source open in VS Code alongside these pages.
The entire extension lives in six TypeScript files. Here’s the map:
| File | Lines | Role |
|---|---|---|
extension.ts |
172 | Entry point. Registers commands, creates the status bar, wires up event listeners, orchestrates color application. |
colorGenerator.ts |
137 | The color engine. Hashes workspace names to hues, defines theme profiles, converts HSL to hex, generates the full palette. |
colorApplier.ts |
86 | Settings integration. Reads and writes workbench.colorCustomizations without clobbering other extensions. |
colorPicker.ts |
109 | The color picker UI. A QuickPick with 14 named presets, live swatches, and custom hue input. |
swatchGenerator.ts |
129 | PNG encoder. Generates solid-color swatch images at runtime using raw PNG encoding — no image library. |
types.ts |
57 | Shared interfaces and the config reader. Defines the contracts that keep the other five files decoupled. |
Notice the zero-dependency design. The extension uses only Node.js built-ins (path,
fs, zlib) and the VS Code API. No color libraries, no image libraries,
no utility packages. Everything is implemented from first principles. This makes the extension
fast to activate, trivial to audit, and immune to supply-chain concerns. It also makes it a
much more interesting thing to study.