html-chameleon · v1 · design.html phase 0

Chameleon

Themable HTML, without the boilerplate. Write semantic classes once — the browser, the user, or a Chrome extension can repaint everything.

A spec-as-playground. Try the Light / Dark / Sunset / Forest / Midnight / Ocean / Rose / Slate / Lavender / Mint / Claude / Graphite / Nocturne buttons in the top-right — every section below re-themes live, including this page itself.

00 — WHY

Markdown got me reading. HTML keeps me in the loop.

Once Claude artifacts moved from a 30-line markdown file to a 200-line HTML one, two things happened. The output got dramatically richer — diagrams, tables, embedded interactions. But every artifact also started baking its own colors, its own dark-mode toggle, its own copy of "what looks good".

Chameleon is the smallest amount of structure that lets one Skill stop reinventing the palette, one Chrome extension override every artifact's theme without touching the file, and a future you read your own HTMLs in your own colors — three months later, on a different laptop, in a different mood.

The Why isn't "dark mode is nice". It's that the artifact and the viewer are different people now — the model writes the structure, you bring the taste.


01 — OVERVIEW

Three components, one contract

Chameleon is the agreement between a CSS file, a Skill, and a Chrome extension. Each is independently useful, but together they let any HTML behave like a Tailwind-themed site without ever importing Tailwind.

your.html themable artifact class="bg-primary text-on-primary" theme.css + theme.js 23 CSS variables · utility classes /v1/theme.css (GitHub Pages) <link rel="stylesheet"> Claude Skill generates / converts /chameleon writes Chrome extension live theme override localStorage + content.js repaints

How the three pieces split responsibility

ComponentOwnsOutput
theme/v1/* The contract: CSS variables & utility class names Two static files served from GitHub Pages
/skill Claude-side authoring: emit / refactor HTML to use the contract Generated or converted .html files
/extension User-side viewing: settings UI & runtime override localStorage entry consumed by theme.js

02 — CONTRACT

23 CSS variables, semantic names

Themes never address pixels — only roles. --primary is "the color you click", not "blue". This is the entire contract a theme must implement; everything else is built from these.

Surface

--canvaspage background
--surfacecards, panels
--surface-2nested / elevated

Text

--textprimary body text
--text-mutedsecondary text
--text-subtlehints, placeholders

Brand

--primarymain CTA / brand
--on-primarytext on primary bg
--secondarysecondary brand
--on-secondarytext on secondary bg
--accentplayful accent
--on-accenttext on accent bg

Borders

--borderdefault border
--border-subtlesofter divider
--border-strongfocus / emphasis

Semantic states

--successpositive / OK
--warningcaution
--dangerdestructive / error

Why these and not more? Every variable a theme has to define is a tax on contributors. 21 covers 95% of artifacts. Anything else (chart palettes, syntax-highlight colors) goes in a v2 namespace and stays optional.


03 — CLASSES

Utility classes, Tailwind-shaped

The class names are intentionally close to Tailwind's mental model — but every value resolves to a CSS variable, not a hardcoded hue. Compose them just like you would in Tailwind.

ClassResolves toDemo
bg-canvas background: var(--canvas) Canvas
bg-surface background: var(--surface) Surface
bg-surface-2 background: var(--surface-2) Elevated
bg-primary bg + auto on-primary text Primary
bg-secondary bg + auto on-secondary text Secondary
bg-accent bg + auto on-accent text Accent
bg-success / warning / danger state bg + matching text OK ! ×
text-base / muted / subtle three text shades Aa Aa Aa
text-primary / secondary / accent brand-colored text Aa Aa Aa
border / border-subtle / border-strong three border weights · · ·
rounded / rounded-lg / rounded-full radius helpers

Layered with Tailwind?

Yes. Chameleon classes are intentionally narrow in scope (color & border only). Spacing, layout, typography sizes — keep using Tailwind, raw CSS, or whatever you prefer. Chameleon stays out of those decisions.


04 — PLAYGROUND

Pick a theme. Watch the page change.

The picker on the left writes inline CSS variables on :root — exactly what the Chrome extension will do. The preview, this page, and every Chameleon-themed artifact share the same variables.

Presets

Custom override

Onboarding email — March numbers

Last updated 2 hours ago · ▲ 12.4%

Welcome flow A/B test concluded. Variant B (with progress bar) outperformed control on day-3 retention. Recommend rolling out to 100% in the next release.

System status

All services nominal. Last incident 14 days ago.
Cache hit rate dropped to 87% (target: 95%).
Payment processor returned 5xx for 0.2% of requests in the last hour.

Code review snippet

// theme.js — load from localStorage, fall back to system pref
const stored = localStorage.getItem('chameleon-theme');
const theme  = stored ? JSON.parse(stored) : { mode: 'light' };
document.documentElement.dataset.theme = theme.mode;

05 — CONVERSION

Existing HTMLs, retroactively themable

Most of the value is in retrofit — the dozens of HTML artifacts you already have. The Skill scans inline styles, <style> blocks, and SVG fill attrs, proposes a role mapping, and shows a dry-run before touching anything.

Before — hardcoded
<div style="background:#1a1a2e;
            color:#e0e0e0;
            border:1px solid #16213e">
  <h2 style="color:#0f3460">Report</h2>
  <button style="background:#e94560;
                  color:white">
    Run
  </button>
</div>
After — themed
<div class="bg-surface text-base
            border rounded">
  <h2 class="text-primary">Report</h2>
  <button class="btn btn-primary">
    Run
  </button>
</div>

// + <link href="...theme.css">
// + <script src="...theme.js">

Proposed mapping (Skill output)

Original colorProposed roleConfidenceAction
#1a1a2e--surfacehigh · 92%auto
#e94560--primaryhigh · 88%auto
#0f3460--secondarymedium · 64%confirm
#16213e--bordermedium · 58%confirm
SVG fill (illustration)— preserve —opt-outskip

Anything below 70% confidence pauses for your sign-off. Illustration / brand-locked colors get an explicit opt-out marker so they survive future passes.


06 — REPO

What lives where

Everything ships from one repo. The contract files are versioned under /v1 so a breaking change becomes /v2 rather than a silent regression.

html-chameleon/
├── theme/
│   └── v1/
│       ├── theme.css          23 CSS variables + utility classes
│       └── theme.js           localStorage loader, system-pref fallback
├── skill/
│   ├── SKILL.md           Claude Code skill — generate / convert modes
│   └── prompts/
│       ├── generate.md
│       └── convert.md
├── extension/
│   ├── manifest.json      Chrome MV3
│   ├── popup.html         settings panel UI
│   ├── content.js         injects floating button + sets localStorage
│   └── background.js      cross-tab sync
├── examples/
│   ├── basic.html         "hello world" themed page
│   ├── dashboard.html     complex layout demo
│   └── conversion.html    before/after sample
├── docs/
│   └── design.html        ↩ this file
├── README.md
└── LICENSE               MIT

GitHub Pages serves /theme/v1/theme.css at a stable URL. Themed HTML files reference it with one <link> tag. The contract is small enough that anyone reading the README can author a new preset in 5 minutes.


07 — SKILL

The Claude-side authoring kit

A single Skill with two modes. It does not live in CLAUDE.md — it auto-triggers only when the request is HTML-related, keeping the regular agent context lean.

Modes

ModeTriggered byBehavior
generate "make an HTML…", "create an artifact…" Emit new HTML with the standard <link>/<script> bootstrap and Chameleon classes throughout.
convert "make this themable", "Chameleon-ify" Read existing HTML → propose color→role mapping → dry-run preview → write on approval.

Bootstrap snippet (always emitted in generate mode)

<link rel="stylesheet" href="https://churin1116.github.io/html-chameleon/theme/v1/theme.css">
<script src="https://churin1116.github.io/html-chameleon/theme/v1/theme.js"></script>
<html data-theme="light">  <!-- default; overridden by extension/localStorage -->

Convert mode contract


08 — EXTENSION

The viewer-side dial

The extension is purely additive: HTMLs work without it (they get the default theme baked into theme.css), they just don't get the live picker. This keeps shareability intact.

Mockup — popup panel

🦎 Chameleon v1.0
Theme
Custom colors
Apply to all sites
Sync via Chrome account

Behavior

  • Detects <link> referencing html-chameleon and shows the floating dial.
  • Writes localStorage['chameleon-theme']; theme.js already listens for changes.
  • Optionally syncs across devices via chrome.storage.sync.
  • Per-site override: hold Shift while choosing to apply only to current origin.

What it deliberately doesn't do

  • Inject styles into pages that don't reference Chameleon — that would be CSS surgery on random sites and is out of scope.
  • Edit the underlying HTML file. Theme override is runtime-only.

09 — OPEN

Decisions still outstanding

Before the v1 contract gets locked at /v1/theme.css, these are the calls worth making explicitly.

Naming

Class collisions with Tailwind

Should we prefix utilities (cm-bg-primary) for safety, or stay clean and document the collision risk?

Variables

Add elevation / shadow tokens?

Right now Chameleon owns color only. Shadows are surprisingly theme-dependent in dark mode. Worth 3 more vars?

Extension

Auto-inject for unthemed pages?

If a page doesn't reference Chameleon, should the extension offer to inject the theme.css link client-side as a "force theme" mode?

Skill

Convert as Bash script or pure prompt?

Pure-prompt convert is portable; a small script could parse stylesheets more reliably. Maybe both, with prompt as fallback.

Hosting

CDN cache vs. GitHub Pages?

GitHub Pages has no edge cache headers control. For a globally-loaded stylesheet, jsDelivr or a tiny Cloudflare worker may be worth it later.

Distribution

Publish as npm too?

For non-Claude users embedding theme.css in build pipelines, an html-chameleon npm package costs nothing extra and widens reach.