spritore turns SVG icons into the PNG sprite sheet and JSON index used by
MapLibre GL styles. It can also rasterize a single SVG
into RGBA pixels for map.addImage previews.
Use spritore from a command line, a Rust application, a browser, or Node. It is well suited to style build pipelines, CI asset generation, map editors with live icon previews, and applications that let users export sprite assets.
| Interface | Good for | Start with |
|---|---|---|
| npm CLI | JavaScript projects and CI jobs | npx @kartore/spritore build ... |
| Cargo CLI | Rust-oriented build environments | cargo install spritore |
| Browser API | Map editors, previews, and in-browser exports | @kartore/spritore |
| Node API | Build scripts and server-side asset generation | @kartore/spritore/node |
| Rust API | Applications that process SVG and sprite data in memory | spritore or spritore-core |
For browser, Node, or npm CLI use:
pnpm add @kartore/spritoreOr with npm:
npm install @kartore/spritoreFor the Rust API:
cargo add spritore --no-default-featuresUse spritore-core directly when your integration only needs the in-memory
rendering and sprite-building types:
cargo add spritore-coreInstall the command-line interface with Cargo:
cargo install spritoreBuild standard- and high-density sprite assets from the lowercase .svg files
in a directory:
npx @kartore/spritore build ./icons -o ./public/spritesThe default output is:
public/sprites/
├── sprite.png
├── sprite.json
├── sprite@2x.png
└── sprite@2x.json
The complete command is:
spritore build <svg-dir> -o <out-dir> [--name sprite] [--ratio 1,2] [--fast] [--skip-invalid]
--name <name>changes the output basename.--ratio <ratios>accepts comma-separated integers from 1 to 255.--fastprioritizes generation speed over PNG file size.--skip-invalidreports SVG parse errors and continues with valid icons.
Without --skip-invalid, an invalid SVG stops the command before output files
are written. Icon IDs come from filename stems; characters outside
a-zA-Z0-9_- become -, and collisions after conversion are errors.
The Cargo-installed command uses the same syntax:
spritore build ./icons -o ./public/spritesThe rendering functions initialize the bundled WebAssembly module on their
first call. renderIcon returns the dimensions and straight-alpha RGBA data
expected by MapLibre's map.addImage API.
import {
buildSpriteSheet,
renderIcon,
} from "@kartore/spritore";
const markerSvg = `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
<circle cx="8" cy="8" r="6" fill="#4264fb" />
</svg>
`;
const marker = await renderIcon("marker", markerSvg, 2);
map.addImage("marker", {
width: marker.width,
height: marker.height,
data: marker.pixels,
});
const sprite = await buildSpriteSheet(
[{ id: "marker", svg: markerSvg }],
2,
);sprite.png is a Uint8Array, sprite.index is the parsed MapLibre index,
and sprite.indexJson is a ready-to-write JSON string.
Import the /node entry point when working outside a browser:
import { readFile, writeFile } from "node:fs/promises";
import { buildSpriteSheet } from "@kartore/spritore/node";
const markerSvg = await readFile("marker.svg", "utf8");
const sprite = await buildSpriteSheet(
[{ id: "marker", svg: markerSvg }],
1,
{ fast: true },
);
await writeFile("sprite.png", sprite.png);
await writeFile("sprite.json", sprite.indexJson);See the npm package README for advanced WebAssembly input options and the complete TypeScript API. Result objects and sprite index entries are frozen plain objects; returned byte arrays are caller-owned and need no cleanup.
The Rust API accepts SVG strings and returns the PNG bytes and MapLibre index:
use spritore::{BuildOptions, build_sprite_sheet, index_to_json, render_icon};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let svg = r##"<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
<circle cx="8" cy="8" r="6" fill="#4264fb" />
</svg>"##;
let icons = [render_icon("marker", svg, 1)?];
let sheet = build_sprite_sheet(&icons, 1, BuildOptions::default())?;
std::fs::write("sprite.png", sheet.png)?;
std::fs::write("sprite.json", index_to_json(&sheet.index))?;
Ok(())
}See the spritore crate README for Cargo
features and the spritore-core README for
the lower-level API.
The default mode prioritizes smaller PNG files and is intended for final
assets. Set fast: true in the JavaScript or Rust API, or pass --fast to the
CLI, when quicker preview generation matters more than file size.
- External resources such as linked images and web fonts are not loaded.
- SVG
<text>is not supported in this release because fonts are not bundled. Text elements may parse successfully but are not rendered.
The repository uses its pinned Rust toolchain plus Node and pnpm.
cargo fmt --check
cargo clippy --workspace -- -D warnings
cargo test --workspace
pnpm install
pnpm build
pnpm typecheck
pnpm test
pnpm benchBuilding the JavaScript package also requires the exact wasm-bindgen-cli
version declared in crates/spritore-wasm/Cargo.toml and Binaryen's
wasm-opt. See js/README.md for setup details.
Licensed under either of Apache License, Version 2.0 or the MIT License, at your option.