What We’re Building

A URL shortener that automatically generates a QR code for every shortened link. Users paste a long URL, get a short link, and can download a QR code that points to it.

We’ll use Node.js with Express for the backend and the ToolCenter QR Code API for generating QR codes.

Prerequisites

  • Node.js 18+ installed
  • A ToolCenter key
  • Basic knowledge of Express.js

Project Setup

mkdir url-shortener-qr
cd url-shortener-qr
npm init -y
npm install express nanoid

Project Structure

url-ssppheuaorbcrvlkteiiaercngn./deeje.rsxj-.sqhortn/ml

Step 1: Build the Server

Create server.js:

const express = require('express');
const { nanoid } = require('nanoid');
const app = express();

app.use(express.json());
app.use(express.static('public'));

// In-memory store (use a database in production)
const urls = new Map();
const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
const DEVTOOLBOX_KEY = process.env.DEVTOOLBOX_API_KEY;

// Shorten a URL
app.post('/api/shorten', async (req, res) => {
  const { url } = req.body;

  if (!url || !isValidUrl(url)) {
    return res.status(400).json({ error: 'Invalid URL' });
  }

  const code = nanoid(7);
  const shortUrl = `${BASE_URL}/${code}`;

  urls.set(code, {
    originalUrl: url,
    shortUrl,
    createdAt: new Date().toISOString(),
    clicks: 0,
  });

  // Generate QR code via ToolCenter
  const qrCodeUrl = await generateQRCode(shortUrl);

  res.json({
    shortUrl,
    originalUrl: url,
    qrCode: qrCodeUrl,
    code,
  });
});

// Redirect short URLs
app.get('/:code', (req, res) => {
  const entry = urls.get(req.params.code);
  if (!entry) {
    return res.status(404).send('URL not found');
  }
  entry.clicks++;
  res.redirect(301, entry.originalUrl);
});

// Get URL stats
app.get('/api/stats/:code', (req, res) => {
  const entry = urls.get(req.params.code);
  if (!entry) {
    return res.status(404).json({ error: 'Not found' });
  }
  res.json(entry);
});

function isValidUrl(string) {
  try {
    new URL(string);
    return true;
  } catch {
    return false;
  }
}

app.listen(3000, () => console.log('Server running on port 3000'));

Step 2: Integrate the QR Code API

Add the QR code generation function to server.js:

const https = require('https');

async function generateQRCode(url) {
  const response = await fetch('https://api.toolcenter.dev/v1/qrcode', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${DEVTOOLBOX_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      data: url,
      size: 300,
      format: 'png',
      errorCorrection: 'M',
      foregroundColor: '#000000',
      backgroundColor: '#ffffff',
    }),
  });

  if (!response.ok) {
    throw new Error(`QR code generation failed: ${response.status}`);
  }

  // Convert to base64 data URL for embedding
  const buffer = await response.arrayBuffer();
  const base64 = Buffer.from(buffer).toString('base64');
  return `data:image/png;base64,${base64}`;
}

Step 3: Build the Frontend

Create public/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>URL Shortener + QR Code</title>
  <style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body { font-family: system-ui; max-width: 600px; margin: 50px auto; padding: 20px; }
    h1 { margin-bottom: 30px; }
    .input-group { display: flex; gap: 10px; margin-bottom: 20px; }
    input { flex: 1; padding: 12px; border: 2px solid #ddd; border-radius: 8px; font-size: 16px; }
    button { padding: 12px 24px; background: #667eea; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 16px; }
    button:hover { background: #5a6fd6; }
    .result { display: none; background: #f8f9fa; padding: 20px; border-radius: 8px; text-align: center; }
    .result.show { display: block; }
    .short-url { font-size: 20px; font-weight: bold; color: #667eea; margin: 15px 0; word-break: break-all; }
    .qr-code img { max-width: 200px; margin: 15px 0; }
    .stats { font-size: 14px; color: #666; }
  </style>
</head>
<body>
  <h1>🔗 URL Shortener + QR</h1>
  <div class="input-group">
    <input type="url" id="urlInput" placeholder="Paste your long URL here..." />
    <button onclick="shortenUrl()">Shorten</button>
  </div>
  <div class="result" id="result">
    <p>Your shortened URL:</p>
    <div class="short-url" id="shortUrl"></div>
    <div class="qr-code"><img id="qrCode" alt="QR Code" /></div>
    <p class="stats">QR code generated via ToolCenter</p>
  </div>

  <script>
    async function shortenUrl() {
      const url = document.getElementById('urlInput').value;
      if (!url) return;

      const response = await fetch('/api/shorten', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ url }),
      });

      const data = await response.json();

      document.getElementById('shortUrl').textContent = data.shortUrl;
      document.getElementById('qrCode').src = data.qrCode;
      document.getElementById('result').classList.add('show');
    }
  </script>
</body>
</html>

Step 4: Custom QR Code Styling

Make your QR codes branded with custom colors:

async function generateBrandedQR(url, options = {}) {
  const response = await fetch('https://api.toolcenter.dev/v1/qrcode', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${DEVTOOLBOX_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      data: url,
      size: options.size || 400,
      format: 'png',
      errorCorrection: 'H',  // High correction for logo overlay
      foregroundColor: options.color || '#667eea',
      backgroundColor: '#ffffff',
      margin: 2,
    }),
  });

  return response;
}

Step 5: Adding Analytics

Track clicks and display stats:

app.get('/api/analytics', (req, res) => {
  const allUrls = Array.from(urls.entries()).map(([code, data]) => ({
    code,
    ...data,
  }));

  const totalClicks = allUrls.reduce((sum, u) => sum + u.clicks, 0);

  res.json({
    totalUrls: allUrls.length,
    totalClicks,
    urls: allUrls.sort((a, b) => b.clicks - a.clicks),
  });
});

Step 6: Run It

DEVTOOLBOX_API_KEY=your_key_here node server.js

Visit http://localhost:3000, paste a URL, and get a shortened link with a QR code.

Production Considerations

Before deploying to production:

  1. Use a real database — Replace the in-memory Map with PostgreSQL or Redis
  2. Add rate limiting — Prevent abuse with express-rate-limit
  3. Custom domains — Use a short domain like sho.rt
  4. Bulk generation — Add an endpoint that accepts multiple URLs
  5. QR code caching — Cache generated QR codes to avoid redundant API calls
const cache = new Map();

async function getCachedQR(url) {
  if (cache.has(url)) return cache.get(url);
  const qr = await generateQRCode(url);
  cache.set(url, qr);
  return qr;
}

Conclusion

You’ve built a functional URL shortener with automatic QR code generation. The ToolCenter QR Code API handles the heavy lifting of generating high-quality, customizable QR codes. From here, you can extend the project with user accounts, custom slugs, analytics dashboards, and branded QR code designs.