DEV Community

Cover image for Fully vector QR codes with an SVG logo in React (download as scalable SVG)
Rafael Franco
Rafael Franco

Posted on

Fully vector QR codes with an SVG logo in React (download as scalable SVG)

I needed a QR code with a logo in the middle that I could put on a printed poster — which meant it had to stay sharp at any size. That ruled out almost every option I tried:

  • Canvas-based QR libraries hand you a raster image. Scale it up for print and it blurs.
  • The ones that do output SVG usually treat the logo as a separate raster <img> pasted on top — so even if the code is vector, the logo isn't.

What I actually wanted was one SVG where both the QR modules and the logo are vector paths — so I can drop it in a poster, a PDF, or a print job and it's crisp at any resolution.

That's what react-quick-response does. It renders the QR code as SVG (the encoding is handled by Project Nayuki's well-known QR Code generator library, bundled in — no extra runtime dependency), and it lets you pass an SVG logo as a child that stays vector too.

Fun fact, and the reason for the package name: QR actually stands for "Quick Response." It was invented in 1994 by Denso Wave to track car parts faster than a regular barcode could be scanned — most people never realize the "QR" is a real abbreviation.

Full disclosure: I'm the author. Here's the part I care about most — keeping everything vector.

Install

npm install react-quick-response
Enter fullscreen mode Exit fullscreen mode

An SVG logo that stays an SVG

Pass any SVG element as a child. It isn't rasterized or pasted on as an image — it's inlined into the same <svg> as the QR modules. The component scales it to the largest size that's still scannable for your error-correction level, centers it, and knocks out the modules behind it automatically:

import { ReactQR } from "react-quick-response";
import Logo from "./logo.svg?react"; // an inline SVG component

<ReactQR value="https://react.dev" errorCorrectionLevel="H">
  <Logo />
</ReactQR>;
Enter fullscreen mode Exit fullscreen mode

Because the logo lives in the SVG tree as real paths, there's no resolution to "max out" — it's resolution-independent, exactly like the code around it.

Download it as one scalable SVG

Here's the payoff. The whole thing — modules and logo — is a single <svg> node, so "exporting" is just serializing the DOM. No canvas, no rasterization, no quality loss:

import { useRef } from "react";
import { ReactQR } from "react-quick-response";
import Logo from "./logo.svg?react";

function DownloadableQR() {
  const ref = useRef<SVGSVGElement>(null);

  const downloadSvg = () => {
    if (!ref.current) return;
    // The serialized markup includes the QR paths AND the inlined logo —
    // all vectors, infinitely scalable.
    const data = new XMLSerializer().serializeToString(ref.current);
    const blob = new Blob([data], { type: "image/svg+xml;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "qr-code.svg";
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <>
      <ReactQR
        ref={ref}
        value="https://example.com"
        size={256}
        errorCorrectionLevel="H"
      >
        <Logo />
      </ReactQR>
      <button onClick={downloadSvg}>Download SVG</button>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Open that file in a browser or a vector editor (Figma, Illustrator, Inkscape) and zoom in forever — both the code and the logo are paths. Perfect for print, large-format, or anywhere you don't control the final size.

Need a PNG too? Draw the same SVG onto a <canvas> at whatever resolution you want and call toDataURL("image/png") — but for anything that gets scaled or printed, ship the SVG.

Why "keep it vector" matters

  • Print & large format — posters, stickers, packaging: a raster QR with a logo gets soft; a vector one doesn't.
  • One file, no compositing — the logo isn't a second asset you have to align and embed; it's already part of the SVG.
  • Tiny & editable — SVG paths are small and you can restyle colors in the file afterward.

A couple of extras

You also get module shapes (purely visual — same encoded data):

<ReactQR value="https://example.com" shape="dots" />
<ReactQR value="https://example.com" shape="rounded" />
Enter fullscreen mode Exit fullscreen mode

…plus the usual size, margin, foregroundColor, backgroundColor, and error-correction controls. It's TypeScript-typed and SSR-friendly (it's just SVG markup, so it works in Next.js / Remix server rendering).

Try it

A live playground to tweak size, colors, error correction, shape, and logo — then download the SVG:

If you put a vector QR + logo into a real print job with it, I'd love to see it. ⭐ and issues welcome.

Top comments (0)