Recolour, vectorise, and theme any SVG to a brand palette with a zero-dependency studio that emits a copy-paste CSS filter. Triggers on: recolour svg, brand tint an svg, duotone svg, recolour a diagram, cloudcraft/draw.io/figma svg to brand, svg css filter, png to svg, vectorise a logo, image trace.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add 0xDarkMatter/claude-mods --skill svg-brand-tint-ops --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Svg Brand Tint Ops?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/0xdarkmatter-svg-brand-tint-ops)More formats (shields.io, HTML) on the badges page.
---
name: svg-brand-tint-ops
description: "Recolour, vectorise, and theme any SVG to a brand palette with a zero-dependency studio that emits a copy-paste CSS filter. Triggers on: recolour svg, brand tint an svg, duotone svg, recolour a diagram, cloudcraft/draw.io/figma svg to brand, svg css filter, png to svg, vectorise a logo, image trace."
license: MIT
metadata:
author: claude-mods
related-skills: "color-ops, genart-ops, mapbox-ops"
---
# SVG Brand-Tint Studio
Recolour **any** SVG to a brand palette — theme-aware — and get a copy-paste CSS
filter you can bake into an app. Also **vectorises rasters** (PNG/JPG → SVG) so a
flat-image logo or a screenshot becomes an editable, recolourable SVG. One
zero-dependency HTML file served by a ~90-line Node server. Nothing uploads —
pixels are read in a local `<canvas>`.
Extracted from a real job: taming a CloudCraft AWS-diagram export into a house
brand for an app's hosting page. It generalises to any third-party SVG export
(draw.io, Figma, Mermaid, Excalidraw, icon sets) and any raster you need as
vector.
## When to reach for it
- A **diagram/icon/logo export** is the wrong colours and has hundreds of inline
`fill`/`stroke` values you don't want to hand-edit.
- You want a **duotone / tri-tone** brand treatment and a light + dark variant
from one palette swap.
- You have a **PNG/JPG** and need clean **vector paths** (threshold, posterised,
or colour-quantised — an in-browser Image-Trace).
- You need the **exact CSS `filter:` line** (and a React snippet) to bake a
theme-aware tint into a real page.
This is a **skill, not a rule**: it carries the operational knowledge (the
colour math, the trace pipeline, the bake pattern) plus the working tool. For
one-line "always do X" guidance there's no rule here — the value is the studio +
the reference.
## Run the studio
```bash
node skills/svg-brand-tint-ops/scripts/server.mjs # → http://localhost:4322
# PORT=8080 node …/server.mjs choose a port
# node …/server.mjs --root ./icons serve your own folder of SVGs/PNGs
# node …/server.mjs --help usage + exit codes
```
It serves the sibling `assets/` (the studio + a generic `sample.svg`). Open the
URL, then **drop an SVG or PNG** on the canvas (or use the Source panel's sample
buttons). The left rail is accordion sections; the right is a scalable,
pan/zoom viewport with a live readout of the exact `filter:` line and ramp hex.
**What the panels do** — *Source* (load SVG/PNG/JPG, drop, paste, samples) ·
*Image Trace* (raster → vector: B&W / Steps / Color, detail, smoothing,
despeckle) · *Tone Map* (the N-stop brand ramp + presets + "palette from image")
· *Photographic* (saturate/contrast/brightness/hue/sepia/blur/drop-shadow) ·
*Strokes & Fills* (outline-only, fill-only, stroke width/colour) · *Typography*
(curated Google Fonts on the SVG's `<text>`, weight, size scale, tracking) ·
*Geometry* (rotate/flip/scale, strip fixed size) · *Canvas* (checker/solid/
light/dark, padding, grid) · *Inspect* (hover to highlight any element with its
tag/id/class/colours) · *Export* (copy CSS / baked SVG / tokens / React snippet;
download SVG or PNG @1–4×). `Split` (top bar) is a before/after divider.
## How the recolour works (tri-tone)
Three stacked stages — the first two are one SVG `<filter>`, the third is CSS:
1. `feColorMatrix type="saturate" values="0"` → collapse the source to a grey ramp.
2. `feComponentTransfer` → remap that ramp per channel to the brand stops via
`tableValues` (`lines → ink`, `mid → accent`, `faces → canvas`).
3. `filter: url(#tonemap) saturate(1.55) …` → CSS tune on top.
**Two stops = duotone (often washed); a third accent midstop = tri-tone that
reads as designed.** Custom stop positions are handled by resampling the ramp to
a fixed table. Full derivation, N-stop math, and the `sRGB` vs `linearRGB` note:
[references/tri-tone-and-trace.md](references/tri-tone-and-trace.md).
## How the vectoriser works (PNG → SVG)
A from-scratch, accuracy-tuned engine ([assets/trace-core.mjs](assets/trace-core.mjs),
shared by the tool and the headless CLI): **2× supersample** → alpha-aware
segment into layers (threshold / posterise / **median-cut → k-means-refined →
merged** colour) → **interpolated sub-pixel iso-contours** (`fill-rule="evenodd"`
cuts holes) → closed-ring **Douglas–Peucker** → **corner-split + Schneider
least-squares Bézier fit** (fairs out staircase noise into clean curves; straight
runs and letter corners stay razor-sharp) → despeckle. Benchmarked on 24 real
logos (RMSE ≈27→11.5, edge-F1 0.66→0.86) it reproduces bold/geometric/coloured
marks near-perfectly (thin small text stays readable). It's one
continuous move: **PNG → trace → SVG → brand-tint**. Algorithm + tuning knobs:
[references/tri-tone-and-trace.md](references/tri-tone-and-trace.md) §2.
Trace from the command line (needs `sharp` to decode; the browser tool needs
nothing):
```bash
node skills/svg-brand-tint-ops/scripts/trace.mjs logo.png logo.svg --colors 6
node skills/svg-brand-tint-ops/scripts/trace.mjs --help # flags + exit codes
```
## Baking the result into an app
Render the SVG **inline** (an `<img>` sandboxes fonts + `var()` tokens + document
filters). Because filter primitives can't read CSS variables, read your theme
tokens with `getComputedStyle(el).getPropertyValue('--ink')` and write the
`feFunc*` `tableValues` in JS — rebuild on theme change so light/dark re-tints
for free. Strip the root `width/height` (keep `viewBox`) so it scales. Apply
`filter: url(#id) saturate(…)`. The studio's **Export → React snippet** emits
this pre-filled; the full pattern + gotchas ledger is in
[references/tri-tone-and-trace.md](references/tri-tone-and-trace.md) §3–4.
## Resources
| Path | What |
|---|---|
| [scripts/server.mjs](scripts/server.mjs) | Zero-dep Node static server. `node scripts/server.mjs --help` for flags (`--root`, `--port`, exit codes). Serves `assets/`. |
| [scripts/trace.mjs](scripts/trace.mjs) | Headless PNG/JPG → SVG tracer over the shared engine. `--help` for options + exit codes. Needs `sharp` to decode (browser tool doesn't). |
| [assets/trace-core.mjs](assets/trace-core.mjs) | The canonical, dependency-free trace engine (`traceImage`). Same code the tool runs inline; imported by the CLI. `DEFAULTS` at the top are the tuning knobs. |
| [assets/index.html](assets/index.html) | The studio — the whole tool in one self-contained file (kept classic-script so the `file://` preview works). Editable `PRESETS` and `FONTS` maps near the top of the `<script>`; brand palettes are examples only. |
| [assets/sample.svg](assets/sample.svg) | Generic (brand-agnostic) diagram that auto-loads for a first-run demo. |
| [references/tri-tone-and-trace.md](references/tri-tone-and-trace.md) | The colour math, the trace algorithm, the theme-aware bake pattern, and a gotchas ledger. |
**Tenant-agnostic:** every shipped palette (petrol, mono, blueprint, …) is an
example. Swap the `PRESETS` map for your own tokens — nothing here is bound to a
brand.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!