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

@verevoir/qr

v2.1.0

Published

QR code encoding engine and SVG renderers — 10 visual styles, layered output, fabrication-ready, zero runtime dependencies. Ships a drop-in node-qrcode shim at ./qrcode.

Readme

@verevoir/qr

Text to QR code in TypeScript. Thirteen SVG styles — including two that sample a source image for photo and logo overlays — two corner treatments, PNG export. Zero dependencies.

npm install @verevoir/qr

Styles

Eight hundred words of spec is one picture:

| squares | dots | horizontal | diagonal | metro | | ---------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------ | -------------------------------------------------------------- | -------------------------------------------------------- | | | | | | |

Plus diamonds, vertical, network, circuit, and scribble. Same data, different visual treatment; any of them scans.

Two image-driven styles round it out:

  • photo — dot-density modulates from a source image. Dark regions get big dark dots, light regions get small ones; light modules in dark regions render as a dark ring with a small light centre so the decoder still sees them. The image emerges from the dot pattern itself — no background image needed in the output.
  • logo — sparse dots overlaid on a composited source image. Each module is rendered only where the image can't carry the contrast on its own, using the ISO/IEC 15415 reflectance bands as thresholds. You place the image in the DOM behind the SVG; the QR adds the minimum necessary ink on top.

Quick start

import { encode, toSvg } from '@verevoir/qr';

const results = encode('https://example.com');
const svg = toSvg(results[0], { style: 'dots', cornerStyle: 'rounded' });

// svg is a complete SVG string — set as innerHTML, write to disk,
// drop in a React component, whatever.

encode returns an array of mask candidates ranked by visual quality. Most libraries pick one for you; this one lets you pick — what looks best depends on the style you're rendering with.

Why it exists

  • Zero dependencies. GF(256) arithmetic, Reed-Solomon error correction, mask evaluation, SVG rendering — all self-contained TypeScript.
  • Thirteen built-in styles. Most libraries ship one (filled squares). Scanning-reliable variations — dots, diamonds, traced networks, bezier scribbles, plus two image-driven styles (photo, logo) — let you design instead of settle.
  • SVG out by default. QR codes are grids; vectors scale perfectly and work in any CAD / fabrication tool. PNG export is there when you need pixels.
  • Outline tracing. The square and grid-based styles trace connected regions as single paths rather than thousands of rectangles. Smaller files, cleaner output.
  • Layer separation. The dots renderer outputs dark and light modules as separate <g> groups — useful for multi-colour prints and laser cutting.

Picking a style

import { encode, toSvg } from '@verevoir/qr';
import type { SvgStyle } from '@verevoir/qr';

const qr = encode('https://verevoir.io')[0];

const styles: SvgStyle[] = [
  'square',
  'dots',
  'diamonds',
  'horizontal',
  'vertical',
  'diagonal',
  'network',
  'circuit',
  'metro',
  'scribble',
  // Image-driven — each requires a PhotoSampler:
  'photo',
  'logo',
  'color-logo',
];

for (const style of styles) {
  const svg = toSvg(qr, { style, cornerStyle: 'rounded' });
  // Distinct visual treatment of the same data
}

PNG (browser)

import { encode, toSvg, svgToPng, downloadPng } from '@verevoir/qr';

const svg = toSvg(encode('https://example.com')[0], { style: 'square' });

// As a blob
const blob = await svgToPng(svg, { size: 1024 });

// Or trigger a download
await downloadPng(svg, { size: 1024, filename: 'qr-code.png' });

Browser-only — uses the native canvas API, no canvas package required.

API

Encoding

| Export | Description | | ------------------------ | ---------------------------------------------------------------------------------------------------- | | encode(text, options?) | Encode text into QR matrix. Returns QrResult[] — multiple mask candidates sorted by penalty score. |

Rendering

| Export | Description | | ---------------------------- | ------------------------------------------------------- | | toSvg(qrResult, options?) | Render a QR result as an SVG string. | | svgToPng(svg, options?) | Convert SVG string to PNG blob (browser only). | | downloadPng(svg, options?) | Render to PNG and trigger file download (browser only). |

Options

| Type | Values | Default | | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | | SvgStyle | 'square' | 'dots' | 'diamonds' | 'horizontal' | 'vertical' | 'diagonal' | 'network' | 'circuit' | 'metro' | 'scribble' | 'photo' | 'logo' | 'color-logo' | 'square' | | CornerStyle | 'square' | 'rounded' | 'square' | | LineWidth | 'normal' | 'thin' | 'normal' | | ErrorLevel | 'L' | 'M' | 'Q' | 'H' | 'L' |

SVG styles

| Style | Description | | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | square | Filled squares per module (default) | | dots | Round dots — dark and light on the same layer | | diamonds | Diamond-shaped modules rotated 45° | | horizontal | Horizontal line segments | | vertical | Vertical line segments | | diagonal | Diagonal line segments | | network | Connected traced paths with diamond tips | | circuit | Connected traced paths with circular tips | | metro | Layered horizontal, vertical and diagonal lines | | scribble | Connected component walking with bezier-smoothed turns | | photo | Dot-density modulates from an image sampler. Dark-dot diameter tracks local darkness; light modules in dark regions render as a dark ring with a small light centre. Requires photo: { sample }. | | logo | Sparse dots overlaid on a composited source image. Two-threshold cull per ISO/IEC 15415 — lum < 0.4 / lum > 0.7 by default. Requires logo: { sample }. | | color-logo | As photo, but each dot uses the sampler's color. Size tracks prominence; a dark anchor is added when the emitted hue is too light to read as a dark module. Requires colorLogo: { sample }. |

Image-driven styles

photo, logo and color-logo take a curried PhotoSampler:

import { encode, toSvg } from '@verevoir/qr';
import { imageToSampler } from '@verevoir/qr/web';

const img = new Image();
img.src = '/portrait.jpg';
await img.decode();

const [qr] = encode('https://example.com', { boostErrorCorrection: true });
const svg = toSvg(qr, {
  style: 'photo',
  photo: { sample: imageToSampler(img) },
});

imageToSampler takes any CanvasImageSourceHTMLImageElement, HTMLCanvasElement, ImageBitmap, SVGImageElement, etc. — rasterises it at the QR's module resolution (aspect-preserving letterbox on white), and returns a sampler the renderer consumes. The core library stays DOM-free; Node consumers can write their own sampler around sharp, node-canvas, or any other source.

For logo, composite the source image behind the SVG yourself (DOM layering, or an <image> tag inside a wrapping SVG). The QR only emits the dots that are strictly needed; the underlying image carries the rest.

Neither style is surfaced through the @verevoir/qrcode shim — the node-qrcode API has no way to pass a sampler callback.

Reserving space for a logo

If you want to cover the centre of a QR with a logo image (any style, not just logo), pass logoArea to encode. The encoder forces H-level error correction and picks a version large enough that the covered area fits inside the recovery budget:

const [qr] = encode('https://example.com', { logoArea: 0.15 });
const svg = toSvg(qr, { style: 'square' });
// Composite a 15%-area logo over the centre of the rendered SVG.

Recommended range 0.050.25. Values above ~0.30 exceed H's practical recovery and will usually fail to scan. If the data is too large for any version at the requested ratio, encode throws "content is too large".

Coming from node-qrcode?

@verevoir/qrcode is an API-compatible wrapper. Same method names (toString, toFile, toBuffer, toCanvas, toDataURL), so existing call sites migrate without code rewrites — you just change the import. Use @verevoir/qr directly when you want the full control; use @verevoir/qrcode when you're swapping in behind existing code.

Part of Verevoir

@verevoir/qr is standalone — zero Verevoir dependencies, fine as a single-purpose library. It's also the QR engine behind Verevoir's hosted shortener/tracker and the Slinqi service. If you need link tracking or URL shortening alongside, @verevoir/link-tracking composes with this.

Acknowledgements

The encoding engine was built with the help of Massimo Artizzu's excellent "Let's Develop a QR Code Generator" series on Dev.to, which walks through the QR specification from first principles.

License

MIT