Version v3.0.0 Size 5.9 KB gzip Dependencies Zero dependencies
Why Sigil?
QR workflows usually pull in a general-purpose barcode library that renders to canvas and guesses at colors, or a from-scratch decoder you do not need. Sigil is a pure, zero-dependency encoder (numeric, alphanumeric, and byte modes; versions 1–40; all four error-correction levels; automatic mask selection) with renderers that stay out of the way — an SVG string that themes with CSS, and a canvas painter for print/bitmap flows. Scanning is a thin lifecycle wrapper over the platform's native BarcodeDetector, so there is no decoder weight and no polyfill to ship.
// Before — a QR library per concern, canvas-only output, hardcoded colors
import QRCode from 'qrcode';
const dataUrl = await QRCode.toDataURL(text, { width: 256, color: { dark: '#000' } });
img.src = dataUrl; // raster, fixed colors, no theme support
// After — encode once, render anywhere
import { encodeQr, toSvg } from '@vielzeug/sigil';
const matrix = encodeQr(text); // smallest version that fits, auto mask
element.innerHTML = toSvg(matrix); // currentColor modules — themes with CSS| Feature | Sigil | qrcode (node-style) | jsqr |
|---|---|---|---|
| Bundle size | 5.9 KB | ~100 kB+ | decoder only |
| Runtime dependencies | |||
| Output | Matrix, SVG string, canvas | Canvas/DataURL/UTF-8 | — |
| Themeable output | currentColor by default | Hardcoded color strings | — |
| Scanning | Native BarcodeDetector wrapper | Pure-JS decoder | |
| SSR-safe import |
Use Sigil when you need QR output that themes with your UI (SVG/currentColor), a minimal encoder with no runtime dependencies, or a scanner that uses the platform decoder instead of shipping one.
Consider jsqr-style decoding when you must scan in browsers without BarcodeDetector — sigil reports SigilUnsupportedError rather than bundling a fallback decoder.
Installation
pnpm add @vielzeug/sigilnpm install @vielzeug/sigilyarn add @vielzeug/sigilQuick Start
Encode to an SVG string — works in Node and the browser:
import { encodeQr, qrCapacity, toSvg } from '@vielzeug/sigil';
const payload = 'https://vielzeug.dev';
const matrix = encodeQr(payload, { errorCorrection: 'M' });
document.querySelector('#qr').innerHTML = toSvg(matrix, { label: 'Vielzeug link' });Scan with the camera (browser only — see support notes in the usage guide):
import { createQrScanner } from '@vielzeug/sigil';
const video = document.querySelector('video');
const scanner = createQrScanner({ video });
scanner.onResult((result) => {
console.log('scanned:', result.value); // once: true stops after first decode
});
await scanner.start(); // throws SigilUnsupportedError / SigilPermissionErrorFeatures
encodeQr— pure matrix encoder: numeric/alphanumeric/byte modes, versions 1–40, EC levels L/M/Q/H, automatic or forced maskqrCapacity— byte capacity per version/mode/level, for pre-flight validationtoSvg— compact path-merged SVG string;currentColormodules,<title>+role="img"built indrawToCanvas— bitmap rendering with DPR-aware scaling for print and download flowsdetectQr— one-shot detection on anyImageBitmapSourcecreateQrScanner— camera scan loop withoncemode, status events,tap()observability, and strict disposalisQrScanSupported/qrScanSupport— sync and async feature detection that never assumes
Documentation
- Usage Guide — encoding modes, capacity, rendering, scanning, and testing
- API Reference — every export, option, type, and error
- Examples — copy-paste recipes, including pairing two devices with
meshQrCodec