DEV Community

Xiao Ling
Xiao Ling

Posted on • Originally published at dynamsoft.com

How to Build a Chrome Extension for Barcode & QR Code Generation from Scratch

A barcode or QR Code generator can be incredibly useful for quickly sharing links, managing inventory, or encoding information. In this tutorial, we'll walk you through building a Chrome extension that generates both 1D and 2D barcodes from the current webpage URL or user-inputted text.

Demo Video: 1D/2D Barcode Generator for Chrome

Chrome Extension Installation

Barcode & QR Code Generator

What We're Building

A Chrome extension that can:

  • Generate QR codes from any webpage with one click
  • Support mainstream barcode types (QR Code, EAN13, CODE128, PDF417, etc.)
  • Allow manual text input for custom barcodes
  • Download barcodes as PNG images
  • Copy barcodes to clipboard
  • Work completely offline with no data collection

Prerequisites

Step 1: Project Setup

Create a new directory for your extension:

mkdir barcode-generator-extension
cd barcode-generator-extension
Enter fullscreen mode Exit fullscreen mode

Create the following file structure:

barcode-generator-extension/
├── manifest.json
├── popup.html
├── popup.css
├── popup.js
├── bwip-js.min.js
└── icons/
    ├── icon16.png
    ├── icon48.png
    └── icon128.png
Enter fullscreen mode Exit fullscreen mode

Step 2: Create the Manifest File

The manifest.json is the heart of any Chrome extension. It defines metadata, permissions, and entry points.

Create manifest.json:

{
  "manifest_version": 3,
  "name": "Barcode & QR Code Generator",
  "version": "1.0",
  "description": "Generate 1D/2D barcodes from current page URL or custom text",
  "permissions": [
    "activeTab"
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icons/icon16.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "icons": {
    "16": "icons/icon16.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  }
}
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • manifest_version: 3 - Uses the latest Manifest V3 specification
  • activeTab permission - Only accesses the current tab when user clicks the extension
  • action.default_popup - Defines the popup HTML file

Step 3: Build the User Interface

Create popup.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="popup.css">
    <title>Barcode Generator</title>
</head>
<body>
    <div class="container">
        <h1>Barcode Generator</h1>

        <div class="input-section">
            <div class="button-group">
                <button id="useUrl" class="btn btn-primary">Use Current URL</button>
                <button id="useManual" class="btn btn-secondary">Manual Input</button>
            </div>

            <div class="input-group">
                <label for="text">Text:</label>
                <input type="text" id="text" placeholder="Enter text or click 'Use Current URL'">
            </div>

            <div class="input-group">
                <label for="barcodeType">Barcode Type:</label>
                <select id="barcodeType">
                    <option value="qrcode">QR Code</option>
                    <option value="dotcode">Dotcode</option>
                    <option value="pdf417">PDF417</option>
                    <option value="maxicode">MaxiCode</option>
                    <option value="azteccode">AztecCode</option>
                    <option value="datamatrix">DataMatrix</option>
                    <option value="ean13">EAN13</option>
                    <option value="code128">CODE128</option>
                    <option value="code39">CODE39</option>
                    <option value="interleaved2of5">ITF</option>
                    <option value="msi">MSI</option>
                    <option value="pharmacode">Pharmacode</option>
                    <option value="rationalizedCodabar">Codabar</option>
                </select>
            </div>

            <button id="generate" class="btn btn-generate">Generate Barcode</button>
        </div>

        <div id="result" class="result-section" style="display: none;">
            <canvas id="barcodeCanvas"></canvas>
            <div class="action-buttons">
                <button id="download" class="btn btn-success">Download</button>
                <button id="copy" class="btn btn-info">Copy to Clipboard</button>
            </div>
        </div>

        <div id="error" class="error-message" style="display: none;"></div>
    </div>

    <script src="bwip-js.min.js"></script>
    <script src="popup.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

UI of the Barcode Generator Extension

Step 4: Style the Extension

Create popup.css:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    width: 400px;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background: #f5f5f5;
}

.container {
    padding: 20px;
}

h1 {
    font-size: 20px;
    color: #333;
    margin-bottom: 20px;
    text-align: center;
}

.input-section {
    background: white;
    padding: 15px;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    margin-bottom: 15px;
}

.button-group {
    display: flex;
    gap: 10px;
    margin-bottom: 15px;
}

.input-group {
    margin-bottom: 15px;
}

.input-group label {
    display: block;
    margin-bottom: 5px;
    font-size: 14px;
    color: #555;
    font-weight: 500;
}

.input-group input,
.input-group select {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 14px;
    transition: border-color 0.3s;
}

.input-group input:focus,
.input-group select:focus {
    outline: none;
    border-color: #007BFF;
}

.btn {
    padding: 10px 15px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 14px;
    font-weight: 500;
    transition: all 0.3s;
}

.btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}

.btn-primary {
    background-color: #007BFF;
    color: white;
    flex: 1;
}

.btn-secondary {
    background-color: #6c757d;
    color: white;
    flex: 1;
}

.btn-generate {
    width: 100%;
    background-color: #28a745;
    color: white;
    padding: 12px;
    font-size: 16px;
}

.btn-success {
    background-color: #17a2b8;
    color: white;
    flex: 1;
}

.btn-info {
    background-color: #ffc107;
    color: #333;
    flex: 1;
}

.result-section {
    background: white;
    padding: 15px;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    text-align: center;
}

#barcodeCanvas {
    max-width: 100%;
    height: auto;
    margin-bottom: 15px;
}

.action-buttons {
    display: flex;
    gap: 10px;
}

.error-message {
    background: #f8d7da;
    color: #721c24;
    padding: 12px;
    border-radius: 5px;
    border: 1px solid #f5c6cb;
    font-size: 14px;
    text-align: center;
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Implement the Core Functionality

Create popup.js:

// Helper functions
function getDefaultValue(barcodeType) {
    if (barcodeType === 'pharmacode') {
        return '12345';
    } else if (barcodeType === 'rationalizedCodabar') {
        return 'A1234567890B';
    } else {
        return '123456789012';
    }
}

function showError(message) {
    const errorDiv = document.getElementById('error');
    errorDiv.textContent = message;
    errorDiv.style.display = 'block';
    setTimeout(() => {
        errorDiv.style.display = 'none';
    }, 3000);
}

function showSuccess(message) {
    const resultDiv = document.getElementById('result');
    let successMsg = resultDiv.querySelector('.success-message');
    if (!successMsg) {
        successMsg = document.createElement('div');
        successMsg.className = 'success-message';
        successMsg.style.cssText = 'background: #d4edda; color: #155724; padding: 10px; border-radius: 5px; margin-top: 10px;';
        resultDiv.appendChild(successMsg);
    }
    successMsg.textContent = message;
    successMsg.style.display = 'block';
    setTimeout(() => {
        successMsg.style.display = 'none';
    }, 2000);
}

// Generate barcode
function generateBarcode() {
    const text = document.getElementById('text').value.trim();
    const barcodeType = document.getElementById('barcodeType').value;
    const canvas = document.getElementById('barcodeCanvas');
    const resultDiv = document.getElementById('result');

    if (!text) {
        showError('Please enter text or click "Use Current URL"');
        return;
    }

    try {
        bwipjs.toCanvas(canvas, {
            bcid: barcodeType,
            text: text,
            scale: 3,
            includetext: true,
        });

        resultDiv.style.display = 'block';
        document.getElementById('error').style.display = 'none';
    } catch (error) {
        showError('Error generating barcode: ' + error.message);
        resultDiv.style.display = 'none';
    }
}

// Download barcode
function downloadBarcode() {
    const canvas = document.getElementById('barcodeCanvas');
    const link = document.createElement('a');
    const barcodeType = document.getElementById('barcodeType').value;
    link.download = `barcode_${barcodeType}_${Date.now()}.png`;
    link.href = canvas.toDataURL();
    link.click();
    showSuccess('Barcode downloaded!');
}

// Copy to clipboard
async function copyToClipboard() {
    try {
        const canvas = document.getElementById('barcodeCanvas');
        const blob = await new Promise(resolve => canvas.toBlob(resolve));
        await navigator.clipboard.write([
            new ClipboardItem({ 'image/png': blob })
        ]);
        showSuccess('Barcode copied to clipboard!');
    } catch (error) {
        showError('Failed to copy to clipboard: ' + error.message);
    }
}

// Get current tab URL
async function getCurrentTabUrl() {
    try {
        const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
        return tab.url;
    } catch (error) {
        showError('Failed to get current URL: ' + error.message);
        return '';
    }
}

// Event listeners
document.getElementById('useUrl').addEventListener('click', async () => {
    const url = await getCurrentTabUrl();
    if (url) {
        document.getElementById('text').value = url;
        document.getElementById('barcodeType').value = 'qrcode';
    }
});

document.getElementById('useManual').addEventListener('click', () => {
    document.getElementById('text').value = '';
    document.getElementById('text').focus();
});

document.getElementById('generate').addEventListener('click', generateBarcode);

document.getElementById('download').addEventListener('click', downloadBarcode);

document.getElementById('copy').addEventListener('click', copyToClipboard);

document.getElementById('barcodeType').addEventListener('change', (e) => {
    const currentValue = document.getElementById('text').value;
    if (!currentValue || currentValue === getDefaultValue(e.target.value)) {
        document.getElementById('text').value = getDefaultValue(e.target.value);
    }
});

document.getElementById('text').addEventListener('keypress', (e) => {
    if (e.key === 'Enter') {
        generateBarcode();
    }
});

// Initialize
window.addEventListener('load', () => {
    const barcodeType = document.getElementById('barcodeType').value;
    document.getElementById('text').value = getDefaultValue(barcodeType);
});
Enter fullscreen mode Exit fullscreen mode

Step 6: Download the Barcode Library

Note: Chrome extensions cannot use external CDN libraries due to Content Security Policy (CSP). We need to include the library locally.

Download bwip-js:

curl -o bwip-js.min.js https://cdn.jsdelivr.net/npm/bwip-js@4.1.2/dist/bwip-js-min.js
Enter fullscreen mode Exit fullscreen mode

Or manually download from bwip-js GitHub releases.

Step 7: Test Your Extension Locally

  1. Open Chrome and navigate to chrome://extensions/
  2. Enable Developer mode (toggle in top-right corner)
  3. Click Load unpacked
  4. Select your extension folder
  5. The extension should now appear in your toolbar

Test the features:

  1. Click the extension icon
  2. Click "Use Current URL" - it should populate the URL field
  3. Click "Generate Barcode" - a QR code should appear
  4. Try "Download" and "Copy to Clipboard" buttons
  5. Test different barcode types from the dropdown

Chrome Extension for Barcode Generation

Step 8: Package for Chrome Web Store

Create a ZIP file with only the essential files:

zip -r barcode-extension.zip manifest.json popup.html popup.css popup.js bwip-js.min.js README.md icons/
Enter fullscreen mode Exit fullscreen mode

Step 9: Submit to Chrome Web Store

To submit your extension to the Chrome Web Store, follow these steps:

  1. Go to Chrome Web Store Developer Dashboard.
  2. Click "New Item".
  3. Upload your ZIP file.
  4. Fill in Store listing (screenshots, description, categories), Privacy, and Distribution.
  5. Click Submit for Review (approval is typically 1–3 business days).

Chrome Web Store Submission

Source Code

https://github.com/yushulx/barcode-qrcode-generator/tree/main/chrome-extension

Top comments (0)