npm install qrpeach
The published package carries the browser build, versioned metadata, and CDN entry points so you can install the package or reuse the same files from npm-backed CDNs.
qrpeach.js is a standalone browser QR library that creates QR codes and helps you understand them. It returns the full encoding path — payload bytes, bitstream values, ECC blocks, zigzag placement, and the final symbol — so you can inspect, debug, or teach every step. Drop it into any browser page with no external dependencies.
The published package carries the browser build, versioned metadata, and CDN entry points so you can install the package or reuse the same files from npm-backed CDNs.
Version tables, alignment centers, remainder bits, Reed-Solomon block rows, mode bits, ECC format bits, and source metadata are embedded directly in qrpeach.js, so the same single-file browser build can be loaded from jsDelivr or UNPKG.
Each successful publish also uploads stable release assets so you can download qrpeach.js directly without going through a package manager or CDN cache.
These are the public services the published package is intended to live on.
npm install qrpeach https://www.npmjs.com/package/qrpeach https://cdn.jsdelivr.net/npm/qrpeach@latest/qrpeach.min.js https://unpkg.com/qrpeach@latest/qrpeach.min.js https://github.com/dahln/qrpeach/releases/latest/download/qrpeach.js
Load the published browser build from a package CDN. The library computes the final masked symbol itself.
<script src="https://cdn.jsdelivr.net/npm/qrpeach@latest/qrpeach.min.js"></script>
<script>
const model = QRPeach.Generate({
type: 'text',
inputs: { value: 'HELLO WORLD' },
version: 2,
ecc: 'M'
});
console.log(model.ok);
console.log(model.payloadText);
console.log(model.values);
console.log(model.finalQr);
</script>
The browser build exposes two public methods on window.QRPeach: one for generation and one for debugging.
window.QRPeach QRPeach.Generate(options, format?, renderOptions?) QRPeach.Debug(source, options?)
Generate returns a QR model or a render-ready SVG/PNG/JPG asset. Debug returns JSON-safe diagnostic data either from generation inputs/models or from an uploaded QR image.
Each entry below includes the exported name, what parameters it accepts, and what shape it returns.
Name
Description
Primary browser-global namespace. Loading the published browser build from npm, jsDelivr, UNPKG, or the GitHub release asset attaches the minimal public API here.
Parameters
None. Load the browser build, then read window.QRPeach.
Returns
{
Generate: Function,
Debug: Function
}
Code Snippet
<script src="https://unpkg.com/qrpeach@latest/qrpeach.min.js"></script> <script> const api = window.QRPeach; console.log(Object.keys(api)); </script>
Name
Description
Generates a QR model from a payload type, typed inputs, version, and ECC level. When you also pass an output format, it returns a render-ready SVG, PNG, or JPG asset and can optionally trigger a browser download.
Parameters
options: {
type?: 'text' | 'uri' | 'url' | 'email' | 'phone' | 'sms' | 'contact' | 'vcard' | 'event' | 'wifi' | 'geo';
inputs?:
| { value: string } // uri or url
| { address: string, subject?: string, body?: string }
| { number: string }
| { number: string, message?: string }
| { name?: string, org?: string, phone?: string, email?: string, url?: string, note?: string }
| { title?: string, start?: string, end?: string, location?: string, description?: string, allDay?: boolean, timezone?: string }
| { ssid: string, encryption?: 'WPA' | 'WEP' | 'nopass', password?: string, hidden?: boolean }
| { lat: string, lng: string, query?: string };
version?: number; // 1 through 40, default 2
ecc?: 'L' | 'M' | 'Q' | 'H';
enableMask?: boolean; // default true
}
format?: 'svg' | 'png' | 'jpg' | 'jpeg'
renderOptions?: {
filename?: string,
download?: boolean, // default false when format is provided
cellSize?: number,
marginModules?: number, // default 4
foreground?: string, // CSS color, default #000000
background?: string, // CSS color, default #ffffff
quality?: number // JPG only, default 0.92
}
Returns
Without format:
{
ok: boolean,
type: string,
inputs:
| { value: string } // uri or url
| { address: string, subject?: string, body?: string }
| { number: string }
| { number: string, message?: string }
| { name?: string, org?: string, phone?: string, email?: string, url?: string, note?: string }
| { title?: string, start?: string, end?: string, location?: string, description?: string, allDay?: boolean, timezone?: string }
| { ssid: string, encryption?: 'WPA' | 'WEP' | 'nopass', password?: string, hidden?: boolean }
| { lat: string, lng: string, query?: string },
version: number,
ecc: 'L' | 'M' | 'Q' | 'H',
totalBytes: number,
dataBytes: number,
eccBytes: number,
countBits: number,
capacityBits: number,
payloadInfo: {
type: string,
typeLabel: string,
envelope: string,
description: string,
scannerRule: string,
inputs:
| { value: string } // uri or url
| { address: string, subject?: string, body?: string }
| { number: string }
| { number: string, message?: string }
| { name?: string, org?: string, phone?: string, email?: string, url?: string, note?: string }
| { title?: string, start?: string, end?: string, location?: string, description?: string, allDay?: boolean, timezone?: string }
| { ssid: string, encryption?: 'WPA' | 'WEP' | 'nopass', password?: string, hidden?: boolean }
| { lat: string, lng: string, query?: string },
payload: string
},
payloadText: string,
payloadBytes: Array<{ value: number, char: string, charLabel: string, charIndex: number, byteOffset: number, byteCount: number }>,
chars: Array<{ char: string, charLabel: string, bytes: number[], byteStart: number, byteEnd: number }>,
bits: Array<{
bit: '0' | '1',
kind: 'mode' | 'count' | 'payload' | 'terminator' | 'padbits' | 'padcw',
summary: string,
detail: string,
bitNumber: number | null,
charIndex?: number,
charLabel?: string,
byteIndex?: number,
byteValue?: number,
padValue?: number
}>,
values: Array<{
index: number,
key: string,
kind: string,
label: string,
bitStart: number,
bitEnd: number,
bitLength: number,
bits: string,
summary: string,
detail: string,
charIndex: number | null,
charLabel: string,
byteValues: number[],
moduleStartIndex: number,
moduleEndIndex: number
}>,
charMap: Array<{ index: number, char: string, charLabel: string, bytes: number[], bitStart: number, bitEnd: number, moduleStartIndex: number, moduleEndIndex: number }>,
dataByteValues: number[],
terminatorBits: number,
alignBits: number,
padByteStart: number,
padByteCount: number,
payloadBitLength: number,
remainder: number,
versionInfo: {
version: number,
size: number,
totalModules: number,
alignmentPatternCount: number,
hasVersionInfo: boolean,
totalCodewords: number,
dataCodewords: number,
eccCodewords: number,
remainderBits: number,
capacities: {
numeric: number,
alphanumeric: number,
binary: number,
kanji: number
},
eccProfile: {
L: number,
M: number,
Q: number,
H: number
},
rsBlocks: {
dataCodewords: number,
ecCodewordsPerBlock: number,
groups: Array<{ blocks: number, dataCodewords: number }>
}
},
moduleGrid: { size: number, aligns: number[][], grid: number[][] },
zigzagPath: Array<{ index: number, r: number, c: number }>,
finalQr?: {
matrix: boolean[][],
moduleCount: number,
cellSize: number,
maskPattern: number,
maskPenalty: number,
maskEnabled: boolean,
formatInfo: { value: number, bits: string, eccBits: string, maskBits: string, bchBits: string },
rsBlocks: Array<{ group: number, index: number, data: number[], ecc: number[] }>,
interleavedCodewords: Array<{ index: number, kind: 'data' | 'ecc', block: number, indexInBlock: number, value: number, hex: string }>,
placedBits: Array<{ index: number, row: number, col: number, kind: 'data' | 'ecc' | 'remainder', codewordIndex: number | null, block: number | null, indexInBlock: number, bitIndex: number, value: number, byteValue: number, maskedValue: number }>
},
error?: string,
requiredBits?: number,
suggestion?: number | null
}
With format:
Promise<{
format: 'svg' | 'png' | 'jpg',
filename: string,
mimeType: string,
blob: Blob,
size: number,
svg: string
}>
Code Snippet
const model = QRPeach.Generate({
type: 'text',
inputs: { value: 'HELLO WORLD' },
version: 2,
ecc: 'M'
});
console.log(model.ok);
console.log(model.finalQr.matrix);
const asset = await QRPeach.Generate({
type: 'url',
inputs: { value: 'https://example.com' },
version: 3,
ecc: 'M'
}, 'svg', { download: false });
console.log(asset.svg);
Name
Description
Returns well-formed JSON debug data. Pass generation options or a generated model to inspect QR construction data, or pass PNG, JPEG, or SVG bytes to run the internal virtual scan used by the encoder debugger.
Parameters
source:
| Generate options object
| Generate model object
| Uint8Array
| ArrayBuffer
| TypedArray
| number[]
options?: {
mimeType?: 'image/png' | 'image/jpeg' | 'image/svg+xml',
type?: 'image/png' | 'image/jpeg' | 'image/svg+xml',
sourceLabel?: string
}
Returns
When source is Generate options or a Generate model:
{
ok: boolean,
type: string,
inputs:
| { value: string }
| { address: string, subject?: string, body?: string }
| { number: string }
| { number: string, message?: string }
| { name?: string, org?: string, phone?: string, email?: string, url?: string, note?: string }
| { ssid: string, encryption?: 'WPA' | 'WEP' | 'nopass', password?: string, hidden?: boolean }
| { lat: string, lng: string, query?: string },
version: number,
ecc: 'L' | 'M' | 'Q' | 'H',
payloadInfo: {
type: string,
typeLabel: string,
envelope: string,
description: string,
scannerRule: string,
inputs:
| { value: string }
| { address: string, subject?: string, body?: string }
| { number: string }
| { number: string, message?: string }
| { name?: string, org?: string, phone?: string, email?: string, url?: string, note?: string }
| { ssid: string, encryption?: 'WPA' | 'WEP' | 'nopass', password?: string, hidden?: boolean }
| { lat: string, lng: string, query?: string },
payload: string
},
payloadText: string,
payloadBytes: Array<{ value: number, char: string, charLabel: string, charIndex: number, byteOffset: number, byteCount: number }>,
values: Array<{ index: number, key: string, kind: string, label: string, bitStart: number, bitEnd: number, bitLength: number, bits: string, summary: string, detail: string, charIndex: number | null, charLabel: string, byteValues: number[], moduleStartIndex: number, moduleEndIndex: number }>,
charMap: Array<{ index: number, char: string, charLabel: string, bytes: number[], bitStart: number, bitEnd: number, moduleStartIndex: number, moduleEndIndex: number }>,
versionInfo: {
version: number,
size: number,
totalModules: number,
alignmentPatternCount: number,
hasVersionInfo: boolean,
totalCodewords: number,
dataCodewords: number,
eccCodewords: number,
remainderBits: number,
capacities: { numeric: number, alphanumeric: number, binary: number, kanji: number },
eccProfile: { L: number, M: number, Q: number, H: number },
rsBlocks: { dataCodewords: number, ecCodewordsPerBlock: number, groups: Array<{ blocks: number, dataCodewords: number }> }
},
moduleGrid: { size: number, aligns: number[][], grid: number[][] },
zigzagPath: Array<{ index: number, r: number, c: number }>,
finalQr: {
matrix: boolean[][],
moduleCount: number,
cellSize: number,
maskPattern: number,
maskPenalty: number,
maskEnabled: boolean,
formatInfo: { value: number, bits: string, eccBits: string, maskBits: string, bchBits: string },
rsBlocks: Array<{ group: number, index: number, data: number[], ecc: number[] }>,
interleavedCodewords: Array<{ index: number, kind: 'data' | 'ecc', block: number, indexInBlock: number, value: number, hex: string }>,
placedBits: Array<{ index: number, row: number, col: number, kind: 'data' | 'ecc' | 'remainder', codewordIndex: number | null, block: number | null, indexInBlock: number, bitIndex: number, value: number, byteValue: number, maskedValue: number }>
},
error?: string
}
When source is PNG, JPEG, or SVG bytes:
{
ok: boolean,
mimeType: string,
byteLength: number,
sourceLabel: string,
image: {
width: number,
height: number,
isSquare: boolean,
threshold: number,
darkPixelRatio: number,
contrast: number,
bounds: { left: number, top: number, right: number, bottom: number, width: number, height: number } | null,
quietZone: { left: number, top: number, right: number, bottom: number } | null,
modulePitch?: { x: number, y: number },
quietZoneModules?: { left: number, top: number, right: number, bottom: number },
moduleCount?: number
} | null,
engine: {
name: string,
externalDependencies: boolean
},
decodedText: string,
symbol: {
version: number,
moduleCount: number,
eccLevel: 'L' | 'M' | 'Q' | 'H',
maskPattern: number,
formatInfo: {
level: 'L' | 'M' | 'Q' | 'H',
maskPattern: number,
value: number,
bits: string,
copyA: { value: number, bits: string, errorBits: number },
copyB: { value: number, bits: string, errorBits: number }
},
versionInfo: {
version: number,
value: number,
bits: string,
copyA: { value: number, bits: string, errorBits: number },
copyB: { value: number, bits: string, errorBits: number }
} | null,
bitCounts: {
data: number,
ecc: number,
remainder: number
},
bitstreams: {
metadata: string,
format: string,
version: string,
data: string,
ecc: string,
remainder: string
},
codewords: {
data: Array<{ index: number, bits: string, value: number, hex: string }>,
ecc: Array<{ index: number, bits: string, value: number, hex: string }>
},
byteMode: {
modeBits: string,
countBits: string,
byteCount: number,
payloadBits: string,
payloadBytes: number[],
terminatorBits: string,
alignBits: string,
padCodewords: Array<{ index: number, bits: string, value: number, hex: string }>
}
} | null,
issues: Array<{ severity: 'warning' | 'error', code: string, message: string, detail: string }>
}
Code Snippet
const model = QRPeach.Generate({
type: 'wifi',
inputs: {
ssid: 'Cafe WiFi',
encryption: 'WPA',
password: 'secret123',
hidden: false
},
version: 4,
ecc: 'M'
});
const generationDebug = await QRPeach.Debug(model);
console.log(generationDebug.values.length);
const bytes = new TextEncoder().encode((await QRPeach.Generate({
type: 'text',
inputs: { value: 'HELLO WORLD' },
version: 2,
ecc: 'M'
}, 'svg')).svg);
const scanDebug = await QRPeach.Debug(bytes, {
mimeType: 'image/svg+xml',
sourceLabel: 'Generated SVG'
});
console.log(scanDebug.ok, scanDebug.symbol && scanDebug.symbol.version);