npm versionlicenseCI status

@ttsalpha/qrcode

Lightweight, fully customizable React QR code library.
Pure SVG · Zero dependencies · Built from scratch.

pnpm add @ttsalpha/qrcode
QR code: @ttsalpha/qrcodesquare
QR code: https://github.com/ttsalpha/qrcoderounded
QR code: @ttsalpha/qrcodecircle

Try it live

Adjust every prop and see the result instantly.

What's included

Pure SVG
No canvas, no raster. Scales perfectly at any resolution — print or screen.
Zero dependencies
QR encoding built from scratch per ISO/IEC 18004. React is the only peer dep.
3 dot styles
Square, circle, and snake-connected rounded — mix freely with corner styles.
Customizable corners
Independent style and color for each finder pattern part (dot and square ring).
Logo support
Embed any image URL or React node in the center. Size auto-clamped per ECL to stay scannable.
Fully typed
Strict TypeScript throughout. Full IntelliSense on every prop.
Tree-shakeable
Named exports, ESM + CJS output. Minimal bundle impact.
Export helpers
toSVGString() generates SVG server-side without DOM. toDataURL() renders PNG/JPEG via Canvas.

Get started

Install

bash
pnpm add @ttsalpha/qrcode
# npm install @ttsalpha/qrcode
# yarn add @ttsalpha/qrcode

Quick start

tsx
import { QRCode } from '@ttsalpha/qrcode';

export default function App() {
  return <QRCode value="https://example.com" />;
}

React 18+ is required as a peer dependency.

Props

QRCodeProps
PropTypeDefaultDescription
valuestringData to encode (required)
sizenumber256Width and height of the SVG in pixels
marginnumber4Quiet zone in modules
dotStyleDotStyle'square'Style of data modules
dotColorstring'#000000'Color of data modules
backgroundColorstring'#ffffff'Background — 'transparent' accepted
cornerCornerOptionsFinder pattern corner styles
logoLogoOptionsLogo in center
qrQROptionsQR encoding options
classNamestringCSS class on <svg>
styleCSSPropertiesInline style on <svg>
ariaLabelstringAccessible label for the SVG; defaults to 'QR code: {value}'
DotStyle
ValueDescription
'square'Full square (default)
'circle'Full circle
'rounded'Rounded; adjacent modules connect smoothly (fluid/snake effect)
CornerOptions
ts
interface CornerOptions {
  dot?: {
    style?: 'square' | 'rounded' | 'circle'; // inner 3×3 block
    color?: string;
  };
  square?: {
    style?: 'square' | 'rounded' | 'extra-rounded' | 'circle'; // outer 7×7 ring
    color?: string;
  };
}

When corner.square.style is 'extra-rounded' and corner.dot.style is unset, the dot defaults to 'rounded'. When corner.square.style is 'circle', the dot defaults to 'circle'.

LogoOptions
ts
interface LogoOptions {
  src?: string;        // https, relative path, blob:, or data:image/… URI
  element?: ReactNode; // takes priority over src when both provided
  size?: number;       // 0–1 relative to max safe area; ECL auto-picked; default 0.4
  margin?: number;     // space between logo and edge of cleared area; default 0
  hideDots?: boolean;  // clear dots behind logo area; default true
}

ECL is auto-picked based on size: ≤ 0.25 → L (≤ 15% width), ≤ 0.44 → M (≤ 20%), ≤ 0.69 → Q (≤ 25%), ≤ 1.0 → H (≤ 30%). If errorCorrectionLevel is set explicitly, the size is clamped to that ECL's safe limit. Aspect ratio is auto-detected — landscape logos get a proportionally reduced height so they never overflow the QR.
hideDots uses an SVG mask, so transparent backgrounds are fully supported.

Security: javascript: and non-image data: URIs in src are silently rejected. Never pass unsanitised user input as element — it renders verbatim inside <foreignObject>.

QROptions
ts
interface QROptions {
  errorCorrectionLevel?: 'L' | 'M' | 'Q' | 'H'; // default: 'M'
  version?: number; // 1–40, auto by default
}
LevelRecoveryUse when
L~7%Clean environments, minimal data
M~15%General purpose (default)
Q~25%Industrial / harsh conditions
H~30%QR codes with a center logo
Export Helpers
ts
import { toSVGString, toDataURL } from '@ttsalpha/qrcode';

// Server-side SVG string — no DOM needed
const svg = toSVGString({ value: 'https://example.com', size: 512 });

// PNG data URL via Canvas (browser-only)
const png = await toDataURL({ value: 'https://example.com', size: 512 });

// JPEG with quality
const jpg = await toDataURL(
  { value: 'https://example.com', size: 512 },
  { format: 'jpeg', quality: 0.9 },
);

// Download link
const link = document.createElement('a');
link.href = await toDataURL({ value: 'https://example.com' });
link.download = 'qrcode.png';
link.click();

toSVGString accepts the same props as <QRCode> and returns a static SVG markup string — useful for SSR, saving to a database, or copying to clipboard.
toDataURL is browser-only (requires the Canvas API). JPEG automatically fills a white background when backgroundColor is 'transparent'.

OptionTypeDefaultDescription
format'png' | 'jpeg''png'Output image format
qualitynumber (0–1)browser defaultJPEG quality. Ignored for PNG

Frequently asked questions

How is this different from other QR code libraries?

Most libs handle either SSR or styling — not both. qrcode.react is SSR-safe but has no styling API. qr-code-styling covers custom dots, colors, and logos but relies on Canvas and breaks server-side. This lib covers all of it: custom dot shapes, per-corner colors, logo support, pure SVG, SSR-safe. 2× faster cold start than qrcode.react, 20× faster styled renders than qr-code-styling. See the benchmark →

Does it work with Next.js and server-side rendering?

Yes. The library is pure SVG — no DOM, no Canvas. The QRCode component renders server-side in Next.js App Router and works on Edge runtimes. For SSR without React, use toSVGString().

Can I generate QR codes without React (Node.js, CLI, email templates)?

Yes. toSVGString() produces a static SVG string — no DOM or React required. toDataURL() is browser-only as it requires the Canvas API.

How do I add a logo to the center of a QR code?

Use the logo prop with src for an image URL, or element for any React node. Error correction level is auto-picked based on logo size to keep the code scannable.

How do I export a QR code as PNG or JPEG?

Call toDataURL() in the browser — it returns a data URL you can attach to a download link. Use the format option for JPEG.

Does it support custom colors and dark mode?

Yes. Use dotColor for data modules, backgroundColor (accepts "transparent"), and the corner prop to color finder patterns independently. Pair with your own dark-mode logic to switch colors at runtime.