qrcode.vue renders QR codes as canvas or SVG with no runtime dependencies
A Vue component to generate QRCode. QRCode vue supports both Vue 2 and Vue 3. It offers two QR code formats: canvas and svg. Customize QR code size, margins, error correction level, foreground and background colors, logo images, and gradient effects.
At a glance
- What is it?
- qrcode.vue is a Vue component for generating QR codes that ships as CommonJS, ESM and UMD builds, works in Vue 2 and Vue 3, and exposes props for error correction, margins, colors, gradients, logo images and rounded modules. The package has no runtime dependencies and the SVG render path is the one built for server side rendering.
- Who is it for?
- qrcode.vue fits a Vue 3 application that needs a QR code rendered from a live value, whether that is a URL, a wallet address or a serial number, and it is the right choice when you want to avoid a rendering dependency and keep the QR code styleable through the render-as prop.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Version routing is the first thing to get right
The README opens with two version notes that decide whether your project works at all.
If you are using Vue 3.x, upgrade qrcode.vue to 3.x. If you are using Vue 2.x, keep using version 1.x. Those are the two lines at the top of the file, and they matter because the current package declares its peer dependency as vue ^3.0.0.
"peerDependencies": {
"vue": "^3.0.0"
},
"dependencies": {},That peer range is the whole compatibility story. The 3.x line is built for Vue 3, and the 2.x support that the project description mentions is historical, carried by the older 1.x release that Vue 2 users are told to stay on.
The package itself declares no runtime dependencies at all. For a component that has to encode data into a QR symbol, that is a notable choice, and it is the one piece of hard evidence in the repository about how the encoding is done: there is no separate encoder library listed, so the encoding logic ships inside this package.
The releases are frequent and current. Version 3.9.1 shipped on 2026-05-12, 3.10.0 on 2026-06-13 and 3.11.0 on 2026-09-07, and the last push to the repository was on 2026-10-15, five days before the date of this writing.
The licence is MIT, the author is scope.wu, and the project homepage is qr-vue.tie.pub.
Three builds and how your bundler picks one
The install section documents the package manager step and then lists the distribution files.
npm install --save qrcode.vue # yarn add qrcode.vuedist/
|--- qrcode.vue.cjs.js // CommonJS
|--- qrcode.vue.esm.js // ES module
|--- qrcode.vue.browser.js // UMD for browser or require.js or CommonJS
|--- qrcode.vue.browser.min.js // UMD Minimum sizeThe package.json fields line up with that listing. main points at the CommonJS file, module at the ES module file, browser at the UMD build, and unpkg and jsdelivr both point at the minified UMD build for a direct script tag. The exports map repeats the same choices for modern resolvers, with types pointing at dist/index.d.ts.
So a Vite or webpack project will get the ESM build, a Node require will get the CommonJS one, and a plain HTML page with no bundler can load the UMD file from a CDN. That is a conventional layout and it means the component works in a legacy script-tag page as well as in a modern app, which is why the README still advertises Vue 2 support in the description even though the current release targets Vue 3.
There is one extra item in the files list that is unusual for a component library: /skills is published alongside /dist, README.md and llms.txt. The repository also carries a skills directory and an llms.txt file at the root, which suggests the project publishes an agent-facing description of itself alongside the library. The example directory has an i18n folder and a server.js, so the project also hosts a small demo site.
One component, three entry points, and a render-as prop
The usage section shows two ways in. The first is the plain createApp style, registering the component and passing a value.
import { createApp } from 'vue'
import QrcodeVue from 'qrcode.vue'
createApp({
data: {
value: 'https://example.com',
},
template: '<qrcode-vue :value="value"></qrcode-vue>',
components: {
QrcodeVue,
},
}).mount('#root')The second, and the one that matters for a template-driven app, uses single file components and imports three named things: the default QrcodeVue plus QrcodeCanvas and QrcodeSvg.
<template>
<qrcode-vue :value="value" :size="size" level="H" render-as="svg" />
<qrcode-canvas :value="QRCODE.VUE 😄" :size="size" level="H" />
<qrcode-svg value="QRCODE.VUE 😄" level="H" />
</template>
<script>
import QrcodeVue, { QrcodeCanvas, QrcodeSvg } from 'qrcode.vue'
</script>So there are three usable surfaces. QrcodeVue is the generic one, and it takes a render-as prop whose type is RenderAs('canvas' | 'svg') with a default of canvas. The README notes that the svg prop can work on SSR, which is the single most important technical fact in the library, because a canvas element does not exist on the server. QrcodeCanvas and QrcodeSvg are the fixed variants for when you do not want to branch on a prop.
The default for render-as is canvas, so an application rendered on the server needs to pass render-as="svg" explicitly, or use the QrcodeSvg component, or the hydration will mismatch.
The prop list is where the styling options live
The props section is the real documentation. Here is the surface with its defaults.
The value prop is a string with a default of an empty string, and it holds the content to encode. The size prop is a number defaulting to 100, and it is the pixel size of the rendered element. The margin prop is a number defaulting to 0 and defines how wide the quiet zone should be, which matters if the code sits on a background rather than on white.
The level prop takes Level('L' | 'M' | 'Q' | 'H') with a default of L, and it is the error correction level. This is the one prop with a real trade-off: a higher level encodes more redundancy, so the symbol carries more data for the same size, but it also produces a denser pattern that some scanners handle less well.
The background and foreground props are strings defaulting to #ffffff and #000000, and they are the two colors of the symbol.
The gradient props build on that. gradient is a boolean defaulting to false, gradient-type is GradientType('linear' | 'radial') defaulting to linear, gradient-start-color defaults to #000000 and gradient-end-color defaults to #ffffff.
The radius prop is the newest-looking feature in the list. It is a number defaulting to 0, expressed as a ratio of the module width, and it accepts values from 0 to 0.5. At 0 the modules are square with sharp corners, and at 0.5 they become circles. The README explains that the rounding is context aware: inner corners between adjacent dark modules stay sharp while outer corners are rounded, which is what makes a rounded code still scan cleanly.
<qrcode-vue value="test" :radius="0.35" />There is also a class prop, a string defaulting to an empty string, for styling the element from the outside.
Logo images, excavation and the crossOrigin trap
The image-settings prop takes an ImageSettings object, and the type definition is given in full.
export type ImageSettings = {
src: string // The URL of image.
x?: number // The horizontal offset. When not specified, will center the image.
y?: number // The vertical offset. When not specified, will center the image.
height: number // The height of image
width: number // The height of image
excavate?: boolean // Whether or not to "excavate" the modules around the image.
borderRadius?: number // The border radius of image.
crossOrigin?: 'anonymous' | 'use-credentials' | '' // The CORS attribute for the image. Useful when exporting canvas to an image.
}The excavate option removes the QR modules underneath the logo, which is what makes a logo-overlaid code scannable rather than decorative. The offsets default to centering the image, and borderRadius rounds the logo itself.
The crossOrigin field is the part that bites. The README carries a CORS note stating that when the QR code includes a cross-origin logo image, you should set imageSettings.crossOrigin to anonymous, and the comment in the TypeScript example repeats it: set this when you need to export the canvas to an image.
That matters because the export methods are canvas operations. The template ref methods are documented for both QrcodeCanvas and QrcodeSvg, with QrcodeVue forwarding them based on the current render-as. QrcodeCanvas exposes toDataURL with the signature (type?: string, quality?: number) => string | undefined, and download with the signature (filename?: string) => void.
<script setup>
import { ref } from 'vue'
import { QrcodeCanvas } from 'qrcode.vue'
const qrRef = ref()
const handleDownload = () => {
qrRef.value?.download('my-qrcode.png')
}
</script>Reading pixels back out of a canvas that has drawn a tainted cross-origin image is blocked by the browser, so without that setting the download and the data URL simply fail.
The id prop exists because SSR hydration breaks without it
This is the sharpest edge in the whole library and the README is unusually explicit about it.
The id prop is a string with a default of undefined, and it sets a custom ID for the SVG internal elements, that is the gradients and clip paths. The README says it is required for SSR hydration consistency, and instructs you to pass useId() so the server and the client generate matching IDs.
<script setup>
// vue 3.5+ only
import { useId } from 'vue'
const uid = useId()
// older vue versions (3.4 and below)
// const uid = 'qrcode-1'
// const uid2 = 'qrcode-2'
</script>
<qrcode-svg value="test" :id="uid" render-as="svg" />The fallback behaviour is spelled out as well: when the id is omitted, a module-level counter is used, and that is not SSR-safe across multiple requests.
A module-level counter sounds harmless until you remember it lives in the module, not the request. On a server handling concurrent renders, the counter keeps incrementing, so the server-rendered markup for the tenth QR code on a page differs from what the client expects on hydration. The id prop is therefore not a cosmetic hook, it is the mechanism that makes the SVG path safe to server render.
The useId() helper needs Vue 3.5 or newer. On 3.4 and below the README suggests passing your own literal id instead, which means taking responsibility for uniqueness yourself.
Where qrcode.vue is the wrong tool
The first and most concrete limitation is the CORS behaviour described above. If your QR code carries a remote logo and you need to export it, the export fails unless the image server sends permissive CORS headers and you set crossOrigin to anonymous. That is a dependency on a third party you may not control.
The second is the module size question behind the canvas default. A canvas render has to run on the client, so nothing about the QR code is in the server-rendered HTML and the component has nothing to show until hydration. If the goal is a QR code that is present in the initial HTML, in a static site generator or a server-rendered page that gets crawled or snapshotted, you need render-as="svg" and you need the id prop set correctly. Choosing canvas and expecting a static HTML output is the common mistake here.
The third is a Vue 2 project. The README is unambiguous that Vue 2 users should stay on 1.x. The current 3.x line declares a Vue 3 peer dependency, so a Vue 2 application either pins an old major version with its own set of trade-offs, or migrates.
The fourth is the error correction versus scan reliability trade-off. The level prop goes up to H, which maximises redundancy, but the README does not document any scanner compatibility testing, and a gradient fill or heavy rounding on top of high correction makes a denser pattern. If your codes are scanned by older or low resolution readers, the styling options can work against you, and the defaults are deliberately plain for that reason.
How it compares with a general purpose QR library
The realistic alternative is a general purpose encoder library plus a small wrapper component of your own, which is what most teams end up with before they find qrcode.vue.
The difference is in what you own afterwards. A raw encoder gives you a matrix or a data URL and leaves you to write the component: props for size, margin, colours, the canvas to SVG conversion, the logo overlay, the export methods, the SSR handling. That wrapper is the bulk of what qrcode.vue ships, and the props list above is essentially the list of decisions you would otherwise have to make and document yourself.
The other difference is dependency weight. This package declares no runtime dependencies, so a Vue 3 app that takes it does not pull an encoder into its bundle from another package. For a component that is often on a landing page or a checkout, that matters more than it sounds.
There is also the SSR story. If your app is server rendered, a component that can emit an svg is considerably easier to use than one that can only produce a canvas, and the id prop is the piece that makes the server and client agree. A wrapper you write yourself can do the same thing, but you have to know to do it.
What you give up is breadth. There is no batch generation, no structured data mode, no Micro QR, no error handling story, and no mention of the encoder algorithm or its limits. For a component whose job is a single code in a template, that is a reasonable scope, and it is a narrower one than a general purpose library.
Editorial conclusion
qrcode.vue fits a Vue 3 application that needs a QR code rendered from a live value, whether that is a URL, a wallet address or a serial number, and it is the right choice when you want to avoid a rendering dependency and keep the QR code styleable through the render-as prop. It does not fit a Vue 2 project on the current line, since the README instructs Vue 2 users to stay on version 1.x, and it does not fit a case where you must export a canvas with a cross-origin logo without thinking about CORS. Before adopting, confirm your Vue major version and pick the matching release, set the id prop from useId() if you render on the server so hydration IDs match, and set imageSettings.crossOrigin to anonymous if you intend to call toDataURL or download on a QR code containing a remote logo.
Frequently asked questions
How do I install qrcode.vue?
Run npm install --save qrcode.vue, or yarn add qrcode.vue. The package publishes CommonJS, ES module and UMD builds in dist, with the browser and unpkg fields pointing at the UMD files for direct script tag use.
Which Vue versions does qrcode.vue support?
The README says that Vue 3.x users should upgrade to qrcode.vue 3.x, and that Vue 2.x users should keep using version 1.x. The current package declares a peer dependency of vue ^3.0.0 and has no runtime dependencies.
How do I render a QR code as SVG instead of canvas in qrcode.vue?
Set the render-as prop to svg, whose type is RenderAs('canvas' | 'svg') and whose default is canvas, or import the QrcodeSvg component directly. The README notes that the svg prop can work on SSR, unlike the canvas default.
Why do I need the id prop for SSR in qrcode.vue?
The id prop sets a custom ID for the SVG internal elements such as gradients and clip paths, and the README says it is required for SSR hydration consistency so the server and client generate matching IDs. Pass useId(), which needs Vue 3.5 or newer, because when the prop is omitted a module-level counter is used, and that is not SSR-safe across multiple requests.
How do I add a logo to a QR code with qrcode.vue?
Pass the image-settings prop with an ImageSettings object holding src, width and height, and set excavate to true to remove the modules under the image. If you need to export the canvas to an image, also set imageSettings.crossOrigin to anonymous and make sure the image server allows it.
Can I download a QR code as a PNG from qrcode.vue?
Yes. QrcodeCanvas exposes toDataURL with the signature (type?: string, quality?: number) => string | undefined and download with the signature (filename?: string) => void through a template ref, and QrcodeVue forwards those methods based on the current render-as value.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/scopewu-qrcode-vue)Was this useful?