Back to Blog

How to Create and Download a Styled QR Code in Next.js Using QRCodeStyling

Learn how to create a customized QR code with rounded dots, logos, and a download button in your Next.js application using the qr-code-styling library.


This tutorial covers dynamic imports, client-side rendering, and customizing QR codes for better visual appeal and branding. QR codes have become a standard tool for sharing URLs and other data with ease. In this tutorial, we will learn how to generate a QR code in a Next.js application, style it with colors, shapes, and logos, and allow users to download it as an image. We'll be using the powerful qr-code-styling library for generating the QR code and customizing it to match our branding.

Step-by-Step Guide

1. Set Up the Project

To get started, make sure you have a Next.js project set up. You can create one by running:

npx create-next-app@latest

Once your project is set up, install the necessary qr-code-styling package:

npm install qr-code-styling

2. Create the QR Code Component

In your Next.js project, create a new component that will handle the QR code generation and download functionality. Here's a cleaned-up and optimized version of the QR code creation and download logic:

'use client';

import { useRef, useEffect } from 'react';
import QRCodeStyling, { Options as QRCodeStylingOptions } from 'qr-code-styling';
import site from '@/app/site';

const useQRCodeStyling = (options: QRCodeStylingOptions): QRCodeStyling | null => {
  // Ensure this runs only on the client side
  if (typeof window !== 'undefined') {
    const QRCodeStylingLib = require('qr-code-styling');
    return new QRCodeStylingLib(options);
  }
  return null;
};

type Props = {
  code: string;
};

export default function ActionButtons({ code }: Props) {
  const referralUrl = `${site.url}/r/${code}`;
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const qrCodeRef = useRef<QRCodeStyling | null>(null);

  const qrCodeOptions: QRCodeStylingOptions = {
    width: 512,
    height: 512,
    data: referralUrl,
    margin: 20,
    dotsOptions: { color: '#7A2F0D', type: 'rounded' },
    cornersSquareOptions: { type: 'extra-rounded' },
    imageOptions: { imageSize: 0.2, margin: 10, crossOrigin: 'anonymous', hideBackgroundDots: true },
    backgroundOptions: { color: '#ffffff' },
    image: '/img/qr-code/icon.png',
  };

  qrCodeRef.current = useQRCodeStyling(qrCodeOptions);

  useEffect(() => {
    if (qrCodeRef.current && canvasRef.current) {
      qrCodeRef.current.append(canvasRef.current);
    }
  }, []);

  const handleDownload = async () => {
    if (qrCodeRef.current) {
      const qrBlob = await qrCodeRef.current.getRawData('png');
      if (qrBlob) {
        const img = new Image();
        img.src = URL.createObjectURL(qrBlob);
        img.onload = () => {
          const newCanvas = document.createElement('canvas');
          const context = newCanvas.getContext('2d');
          const qrSize = 512;
          const textHeight = 40;

          newCanvas.width = qrSize;
          newCanvas.height = qrSize + textHeight;

          if (context) {
            context.drawImage(img, 0, 0, qrSize, qrSize);
            context.fillStyle = '#7A2F0D';
            context.fillRect(0, qrSize, qrSize, textHeight);
            context.font = 'bold 19px monospace';
            context.textAlign = 'center';
            context.fillStyle = '#ffffff';
            context.fillText(referralUrl, qrSize / 2, qrSize + 26);

            const link = document.createElement('a');
            link.href = newCanvas.toDataURL('image/png');
            link.download = `referral-${code}-qrcode.png`;
            link.click();
          }
        };
      }
    }
  };

  return (
    <div>
      <button onClick={handleDownload}>Download QR Code</button>
      <div style={{ display: 'none' }}>
        <canvas ref={canvasRef}></canvas>
      </div>
    </div>
  );
}

Key Features of the Code:

  • Dynamic Import: We use dynamic import to ensure that the QRCodeStyling library is imported only on the client side, preventing any server-side issues.
  • Custom QR Code Design: You can easily customize the QR code using the dotsOptions, cornersSquareOptions, and background options. We've styled the QR code to use rounded dots and included a custom image logo.
  • Downloadable QR Code: The handleDownload() function generates a downloadable PNG image with the referral link displayed below the QR code.

3. Enhancing the QR Code with Text

The QR code is drawn on a canvas, and the referral URL is added below it using the canvas drawText function. This creates a custom image that includes both the QR code and the referral URL, ensuring a better user experience and branding consistency.

4. Implementing the Download Button

The download button triggers the handleDownload function, allowing users to download the generated QR code as an image file with a referral link. This is ideal for sharing referral codes across platforms.

Conclusion

By following this guide, you’ve successfully implemented a styled QR code generator in your Next.js project using the qr-code-styling library. Not only is the QR code visually enhanced with colors and logos, but it also allows users to download it as an image, providing a better user experience. This approach is flexible and can be customized further to match any design or branding guidelines.