How to Generate Branded SVG QR Codes for Wi-Fi, vCard & WhatsApp in Node.js (in
Stop wrestling with canvas dependencies and broken Wi-Fi/vCard QR strings. Learn how to generate custom-styled SVG/PNG QR codes with center badges in Node.js.
Every developer eventually gets asked to add QR code generation to a product—whether it is for restaurant Wi-Fi onboarding, digital business cards (vCard), event tickets, crypto checkouts, or WhatsApp click-to-chat links.
Usually, two headaches appear immediately in production:
- Heavy native dependencies: Many QR styling libraries rely on
node-canvasor headless browsers (Puppeteer/Playwright) to draw custom colors or center badges, inflating Docker images by hundreds of megabytes and slowing down serverless cold starts. - Brittle payload formatting: A single unescaped semicolon in a
WIFI:string, a missing newline in aBEGIN:VCARDpayload, or setting Error Correction too low (Linstead ofH) when placing a badge in the center renders the QR code completely unscannable on iOS and Android cameras.
In this tutorial, we will look at how to generate custom-branded SVG and PNG QR codes with center badges and smart payload templates in under 5 milliseconds in Node.js.
Why Standard QR Strings Break on Mobile Scanners
When you generate a QR code for anything beyond a plain URL, mobile OS cameras expect strict RFC-compliant schemas:
- Wi-Fi Auto-Join: Requires
WIFI:T:<encryption>;S:<escaped_ssid>;P:<escaped_password>;H:<hidden>;;where characters like;,:, and\must be escaped. - vCard 3.0 Contacts: Requires strict
BEGIN:VCARD\nVERSION:3.0\nN:LastName;FirstName;;;\nFN:...headers. - Center Badges & Error Correction: If you overlay a badge or text in the middle of a QR matrix without promoting the Reed-Solomon Error Correction Level to
H(30% recovery), you destroy the data modules in the center and break the scan.
Generating Styled QR Codes with QRForge API
To handle all payload formatting, vector badge injection, and automatic Level-H error recovery in memory without touching node-canvas, we can use QRForge API (also open-source on GitHub).
1. Node.js Implementation (generate-qr.js)
Using native fetch in Node.js 18+:
const RAPIDAPI_KEY = process.env.RAPIDAPI_KEY || "YOUR_RAPIDAPI_KEY"; const QRFORGE_HOST = "qrforge-smart-qr-code-and-custom-branding-generator.p.rapidapi.com"; async function createSmartQR(type, data, options = {}) { const response = await fetch(`https://${QRFORGE_HOST}/v1/generate`, { method: "POST", headers: { "Content-Type": "application/json", "X-RapidAPI-Key": RAPIDAPI_KEY, "X-RapidAPI-Host": QRFORGE_HOST }, body: JSON.stringify({ type, data, options }) }); if (!response.ok) { throw new Error(`QRForge error: ${response.status}`); } return response.json(); } async function runDemo() { // Example 1: Branded Wi-Fi QR Code with Center "WIFI" Badge const wifiQR = await createSmartQR( "wifi", { ssid: "StartupHub_5G", password: "supersecret!2026", encryption: "WPA" }, { format: "svg", width: 500, darkColor: "#0F172A", lightColor: "#FFFFFF", centerBadgeText: "WIFI" } ); console.log(`Generated in ${wifiQR.meta.execution_time_ms} ms`); console.log(`Auto-Upgraded Error Level: ${wifiQR.data.errorCorrectionLevel}`); console.log(`Formatted Payload: ${wifiQR.data.payloadString}`); // Example 2: vCard 3.0 Digital Business Card const vcardQR = await createSmartQR( "vcard", { firstName: "Arturo", lastName: "Systems", phone: "+14155552671", email: "dev@example.com", org: "Cloud Microservices", title: "Senior Backend Engineer", url: "[https://github.com/artuturoh](https://github.com/artuturoh)" }, { format: "svg", darkColor: "#1E3A8A", centerBadgeText: "SCAN" } ); console.log(`vCard Data URI ready for <img> tag:`, vcardQR.data.dataUri.slice(0, 60) + "..."); } runDemo(); 2. What the JSON Response Looks Like
{ "success": true, "data": { "type": "wifi", "payloadString": "WIFI:T:WPA;S:StartupHub_5G;P:supersecret!2026;H:false;;", "format": "svg", "mimeType": "image/svg+xml", "width": 500, "margin": 2, "errorCorrectionLevel": "H", "colors": { "dark": "#0F172A", "light": "#FFFFFF" }, "hasCenterBadge": true, "svg": "<svg xmlns=\"[http://www.w3.org/2000/svg](http://www.w3.org/2000/svg)\" viewBox=\"0 0 41 41\" ...>...</svg>", "dataUri": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAw..." }, "meta": { "execution_time_ms": 1.76, "timestamp": "2026-11-08T19:45:00.000Z" } } Notice two things:
- Even though we did not manually specify
errorCorrectionLevel: "H", the engine automatically promoted the matrix toHbecausecenterBadgeText: "WIFI"was included. - You receive both the raw
<svg>markup (ideal for inline HTML rendering or PDF generation) and a ready-to-usedataUrithat drops straight into an<img src="..." />tag.
Batch Generating Up to 25 QR Codes in Parallel
If you are generating PDF event tickets, inventory labels, or restaurant table tents, calling an API 25 times sequentially adds unnecessary network overhead. You can use the POST /v1/batch endpoint to generate up to 25 QR codes in parallel in a single call:
const batchResponse = await fetch(`https://${QRFORGE_HOST}/v1/batch`, { method: "POST", headers: { "Content-Type": "application/json", "X-RapidAPI-Key": RAPIDAPI_KEY, "X-RapidAPI-Host": QRFORGE_HOST }, body: JSON.stringify({ items: [ { id: "table-1", type: "url", data: { url: "[https://menu.example.com/table/1](https://menu.example.com/table/1)" }, options: { centerBadgeText: "T1", darkColor: "#0F172A" } }, { id: "support-wa", type: "whatsapp", data: { phone: "+14155552671", message: "Hi! I need help at Table 1" }, options: { centerBadgeText: "CHAT", darkColor: "#16A34A" } } ] }) }); Try the Live Interactive Playground or View the Source
- Live Interactive Generator Studio: https://qrforge-api-production-2a50.up.railway.app
- RapidAPI Hub (Free Tier Available): QRForge API on RapidAPI
- GitHub Repository: https://github.com/artuturoh/qrforge-api
How are you handling QR generation and printable SVG assets in your Node.js apps? Let me know in the comments!