@trtmn/qrcody
v1.12.1
Published
Beautiful, customizable QR codes — SVG, PNG, and WebP output. The rendering engine behind https://qrcody.trtmn.io.
Readme
qrcody
Beautiful, customizable QR codes — the same rendering engine behind qrcody.trtmn.io, packaged for reuse outside the app. Full parity with the site: every pixel style, finder-eye/pupil style, corner style, gradient, frame, and logo-embedding option.
Outputs SVG, PNG, and WebP. A sibling Python port with the same
API surface lives at qrcody (PyPI) — the
npm package is scoped (@trtmn/qrcody) because npm's registry blocks the bare
qrcody name as too similar to the existing qrcode package; PyPI had no
such collision, so the two registries carry intentionally different names for
the same package.
Install
npm install @trtmn/qrcody
# For PNG/WebP rasterization in Node:
npm install @resvg/resvg-js sharp@resvg/resvg-js and sharp are optional peer dependencies — only needed if
you use the @trtmn/qrcody/node raster entry point. The default @trtmn/qrcody
entry point is pure JS (no native bindings) and works anywhere: browser, Node,
Cloudflare Workers, etc.
Usage
SVG (any runtime)
import { generateSVG } from '@trtmn/qrcody';
const { svg, w, h } = generateSVG('https://example.com', {
pixelsStyle: 'dots',
eyesStyle: 'circle',
fgColor: '#0b61cb',
frame: 'scan-me',
frameText: 'Scan me',
});Or drive the two lower-level primitives directly for more control:
import { buildSVG, buildFramedSVG, DEFAULT } from '@trtmn/qrcody';
const settings = { ...DEFAULT, text: 'https://example.com' };
const qrSVG = buildSVG(settings); // the QR body, viewBox 0 0 1000 1000
const { svg, w, h } = buildFramedSVG(qrSVG, settings); // wrapped in the chosen framePNG / WebP (Node only)
import { generatePNG, generateWebP } from '@trtmn/qrcody/node';
const png = await generatePNG('https://example.com', { pixelsStyle: 'squircle' }, { width: 1200 });
const webp = await generateWebP('https://example.com', { pixelsStyle: 'squircle' }, { width: 1200, quality: 90 });
await fs.writeFile('qr.png', png);
await fs.writeFile('qr.webp', webp);Or rasterize an SVG string you already built:
import { buildSVG, buildFramedSVG, DEFAULT } from '@trtmn/qrcody';
import { svgToPNG, svgToWebP } from '@trtmn/qrcody/node';
const settings = { ...DEFAULT, text: 'https://example.com' };
const { svg } = buildFramedSVG(buildSVG(settings), settings);
const png = svgToPNG(svg, { width: 1200 });
const webp = await svgToWebP(svg, { width: 1200 });CLI
npx @trtmn/qrcody "https://example.com" -o qr.svg
npx @trtmn/qrcody "https://example.com" --pixels dots --eyes circle -o qr.png
npx @trtmn/qrcody "https://example.com" --frame scan-me --frame-text "Scan me" -o qr.webpNote the @ — npx @trtmn/qrcody ... installs and runs the published npm
package. npx trtmn/qrcody ... (no @) means something different to npx:
that's GitHub-shorthand for installing from the trtmn/qrcody git repo, not
this package.
Output format is chosen by the -o/--output file extension (.svg,
.png, or .webp). PNG/WebP need @resvg/resvg-js and sharp available —
same optional peer deps as the @trtmn/qrcody/node entry point above. A bare
npx @trtmn/qrcody ... won't have them (npx doesn't install a package's
optional peer deps), so for PNG/WebP either install them alongside in a
real project (npm install @trtmn/qrcody @resvg/resvg-js sharp, then run via
an npm script or npx qrcody ... inside that project), or pull all three
into the same ephemeral npx environment:
npx -p @trtmn/qrcody -p @resvg/resvg-js -p sharp qrcody ... -o qr.png.
SVG output has no such requirement — npx @trtmn/qrcody ... -o qr.svg works
standalone. Run npx @trtmn/qrcody --help for the full flag list — it
mirrors the Python package's CLI (python/src/qrcody/cli.py) and the
/api/qr HTTP API's parameters.
Settings reference
DEFAULT (imported from @trtmn/qrcody) documents every recognized setting and its
default value — pass any subset as overrides. Style enums are exported as
PIXELS_STYLES, EYE_STYLES, PUPIL_STYLES, CORNERS_STYLES,
FRAME_STYLES, and CORRECTION_LEVELS.
| Setting | Type | Notes |
|---|---|---|
| text | string | The content to encode. |
| correctionLevel | L|M|Q|H | Error correction level. |
| color / fgColor | hex | Background / foreground. |
| transparent | boolean | Transparent background. |
| pixelsStyle | see PIXELS_STYLES | square|rounded|dots|blob|bars-h|bars-v|squircle |
| eyesStyle | see EYE_STYLES | square|rounded|circle|leaf|squircle |
| pupilsStyle | see PUPIL_STYLES | square|rounded|circle|squircle |
| cornersStyle | see CORNERS_STYLES | Card corner rounding. |
| *SquircleRadius | 0–100 | Superellipse exponent for pixels/eyes/pupils/corners when the style is squircle. |
| border | number | Quiet-zone size in SVG units (viewBox is always 1000×1000). |
| logo / logoScale | data URI / 0.10–0.35 | Center logo overlay. |
| fgGradient/bgGradient/frameGradient (+ *From/*To/*Angle) | | Independent per-element linear gradients. |
| frame | see FRAME_STYLES | none|perimeter|scan-me|scan |
| frameColor / frameText / frameTextSize / framePadding | | Frame styling. |
Why two export paths?
@trtmn/qrcody (default) is pure JS — safe for browsers and edge runtimes like
Cloudflare Workers, which can't load native Node addons. @trtmn/qrcody/node adds
PNG/WebP rasterization via @resvg/resvg-js (native binding) and sharp,
which only run in Node.
