npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gent8/brandkit

v0.3.1

Published

One SVG → 14 ship-ready brand assets (favicon, og-image, PWA icons, Chrome Web Store) — all palette-locked to brand.json. CLI + MCP server with a CI gate that exits 1 on any off-palette color.

Readme

One source SVG → every asset you need to ship a brand. brandkit is a CLI + MCP server that turns a single SVG into 14 standard files — favicon, apple-touch-icon, maskable PWA icon, og-image, Chrome Web Store assets — all palette-locked to your brand.json. The verify command is a CI gate: it exits 1 on any off-palette color, so a drift can't sneak into the bundle the same way ESLint catches a typo.

$ brandkit export dist/logo.svg --brand brand.json --out ./assets
✓ wrote 14 files to ./assets (icon-16.png … cws-marquee-920x680.png)
✓ all colors in palette (5)

$ brandkit verify ./assets/og-image.png  # works on any output
✓ all colors in palette

Use export to ship the bundle. Use verify as a CI gate. Use recolor as a pure SVG-in/SVG-out transform. Use gen for the full prompt → palette-locked SVG pipeline. Every tool is also exposed over MCP, so any Claude / Anthropic-SDK / MCP-compatible agent can call them inline.

What's actually different

1. One command, every surface. Other dev tools cover one slice (pwa-asset-generator does favicons, RealFaviconGenerator does favicons, AI logo SaaS gives you a brand kit but no CI hook). Nothing else gives you the full bundle from one SVG, palette-locked, scriptable:

| Tool | Steps to ship-ready palette-locked SVG + asset bundle | Steps | |---|---|---| | DALL-E 3 / Nano Banana 2 / Midjourney v7 | gen raster · vectorize · recolor · verify · render every asset size | 5 | | Recraft v3 (vector) | gen vector (off-palette) · recolor · verify · render every asset size | 4 | | Raw Ideogram v3 | gen raster · vectorize · recolor · verify · render every asset size | 5 | | RealFaviconGenerator / pwa-asset-generator | favicons only · no og-image · no palette enforcement · still need verify | 3+ | | Looka / Brandmark / LogoAI | rich brand kit but SaaS-locked · no CLI · no verify | n/a | | brandkit | brandkit gen then brandkit export (or one MCP call for the gen part) | 1–2 |

brandkit export writes 14 files from one source SVG: icons (16/32/48/128), favicon (svg + multi-res ico), apple-touch-icon, android-chrome (192/512), maskable-512, og-image (1200×630), and the three Chrome Web Store assets. All palette-locked, no manual rasterization step.

2. The bundle is verified, not just generated. Same source raster, fed through "vectorize only" vs "vectorize + recolor + verify":

| Pipeline | verify exit | Off-palette colors | |---|---|---| | Vectorize-only (Recraft on the raster) | 1 | 48 | | brandkit (vectorize + recolor + verify) | 0 | 0 ✓ |

The drift is 3–15 RGB points per color — invisible to the eye, but accumulates across favicon, og-image, print, merch, and breaks brand QA downstream. verify catches it at build time. Numbers from brandkit verify against the checked-in fixtures. See src/palette.js.

How the pipeline works

  1. Generate — provider call with palette as a strong hint (Ideogram v3 via fal.ai by default).
  2. Vectorize — raster → SVG (Recraft API by default).
  3. Recolor — every #hex and rgb() in the SVG snapped to the nearest palette member.
  4. Verify — drop any candidate that still has off-palette colors. Exit 1 on drift.
  5. Trim — vectorizers pad the mark inside a much larger square; trim rewrites the root viewBox to the rendered geometry bbox so favicons, og-images, and print all fill their canvas.

Install

CLI (npm)

npm install -g @gent8/brandkit
brandkit --help

Or run from source:

git clone https://github.com/gent8/brandkit
cd brandkit
npm install
npm link
brandkit --help

MCP server (Claude Code, Claude Desktop, etc.)

The MCP server lives in mcp/. Build the Docker image and add it to your MCP client config:

docker build -t brandkit-mcp:latest -f mcp/Dockerfile .

Claude Code config:

{
  "mcpServers": {
    "brandkit": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "FAL_KEY",
        "-e", "RECRAFT_API_KEY",
        "brandkit-mcp:latest"
      ]
    }
  }
}

brand.json

{
  "name": "Acme Co",
  "palette": ["#FAFAF9", "#5B21B6", "#10B981", "#F43F5E", "#1C1917"],
  "paletteTokens": {
    "bg": "#FAFAF9",
    "primary": "#5B21B6",
    "accent": "#10B981",
    "warn": "#F43F5E",
    "ink": "#1C1917"
  },
  "negativePrompt": ["leaves", "plants", "sparkles"]
}

The palette array is the law. Anything outside it gets snapped to the nearest member.

CLI commands

| Command | What it does | Side effects | |---|---|---| | recolor | Snap every color in an SVG to the nearest palette member | SVG-in / SVG-out | | verify | Exit 1 on any off-palette color — use as CI gate | None (read-only) | | trim | Tighten root viewBox so the mark fills its canvas | SVG-in / SVG-out | | export | One SVG → 14 ship-ready assets (icons, favicons, og-image, CWS) | Writes files | | gen | Full pipeline: prompt → palette-locked SVG candidates | API calls + files |

brandkit recolor <input.svg> [--brand brand.json] [-o out.svg]

Snap every hex in the SVG to the nearest palette color. 3-digit hex auto-expanded. Errors on hsl() or named colors with a list of offenders — convert those upstream first. Idempotent.

brandkit verify <input.svg> [--brand brand.json]

Exit 0 if every color is in the palette, 1 with a list of offenders otherwise. Use as a precommit / CI gate.

brandkit trim <input.svg> [-o out.svg] [--pad <pct>] [--strip-bg]

Tighten the root viewBox to the rendered geometry bbox so the mark fills its canvas at every output size. Rewrites preserveAspectRatio to xMidYMid meet and drops fixed width/height so consumers can size via container. Pure SVG-in / SVG-out, idempotent. --strip-bg also removes shapes that fill the entire viewBox (typically vectorizer-added background rects).

Why this exists: vectorizers (Recraft, vectorizer.ai) emit marks padded inside a much larger square — easily 40–60% empty. Run on a vectorize output before brandkit export and every favicon, og-image, and print render fills its canvas instead of inheriting the padding. Wired into brandkit gen automatically; standalone for SVGs that came from elsewhere.

brandkit export <input.svg> [--brand brand.json] [--out ./assets] [--bg <hex>]

From one source SVG, produces:

  • icon-{16,32,48,128}.png — Chrome extension
  • favicon.svg, favicon.ico (multi-res 16+32+48), apple-touch-icon.png (180×180)
  • android-chrome-{192,512}.png, maskable-512.png
  • og-image.png (1200×630, mark centered on palette[0] or --bg)
  • cws-icon-128.png, cws-tile-440x280.png, cws-marquee-920x680.png

Rasterization via @resvg/resvg-js. ICO via png-to-ico.

brandkit gen --prompt "..." [--brand brand.json] [--out ./assets] [--count 4] [--dry-run]

Full pipeline:

  1. Provider call (fal.ai Ideogram v3) with prompt + locked palette + negative-prompt list.
  2. Download N rasters → ./assets/_raw/.
  3. Vectorize each (Recraft) → ./assets/_svg/.
  4. Recolor each to snap to palette.
  5. Verify each; drop any that still fail.
  6. Write candidates.html gallery for human selection.
  7. After picking, run brandkit export <chosen.svg>.

--dry-run prints the requests it would make without sending them.

Providers

Wired:

| Var | Used by | |---|---| | FAL_KEY | gen --provider fal (default) | | RECRAFT_API_KEY | gen --vectorize recraft (default) |

Stubbed (throw new Error("not implemented")) — PRs welcome:

  • --provider replicate — needs REPLICATE_API_TOKEN
  • --vectorize vectorizer — needs VECTORIZER_AI_API_ID / VECTORIZER_AI_API_SECRET

If a key is missing for the chosen provider, brandkit exits 1 with a clear set $VAR message.

MCP tools

When run as an MCP server, three tools are exposed:

  • brandkit_gen(prompt, palette, count?, extraNegative?, dryRun?) — full pipeline in one call. Returns survivor SVGs inline as text. No filesystem handoff needed.
  • brandkit_recolor(svg, palette) — pure text-in/text-out. Snaps every hex AND rgb()/rgba() color to the nearest palette member.
  • brandkit_verify(svg, palette) — pure text-in/JSON-out gate; reports off-palette offenders with normalized hex + suggestion.
  • brandkit_trim(svg, padPct?, stripBackground?, keepDimensions?) — pure text-in/text-out. Rewrites the root viewBox to the rendered geometry bbox so the mark fills its canvas. Set stripBackground=true to drop vectorizer-added canvas-fill rects.

recolor/verify accept both #hex and rgb() color forms (Recraft's vectorize output uses rgb()). Named CSS colors and hsl() are still rejected.

export is intentionally CLI-only — it writes 14+ files to disk, which doesn't fit the MCP text-in/text-out model.

Example session

cp example/brand.json ./brand.json
$EDITOR brand.json   # set name + palette

brandkit gen --prompt "minimalist wordmark for a moving-storage app, geometric, clean" --count 6
open ./assets/candidates.html
# pick candidate-3.svg

brandkit export ./assets/_svg/candidate-3.svg --out ./assets/final
ls ./assets/final
# → icon-16.png ... cws-marquee-920x680.png

CI gate

brandkit verify dist/logo.svg --brand brand.json   # exit 1 on drift

Status

[!NOTE] Solo-maintained, best-effort. See STATUS.md. Issues may sit; PRs are read on a slow cadence.

Comparison

See brandkit.run for a side-by-side: same prompt, same palette, fed through Claude-direct SVG / raw Ideogram / brandkit. Spoiler: only the brandkit column passes verify.

License

Apache-2.0. Use it commercially, embed it, fork it — the only ask is that you keep the copyright notice and the license file.