Back to Blog
Dev ToolsFeb 28, 20266 min read

How I Built CodeDusk - A QR Code Chrome Extension

So it started the way most of my projects do - I got annoyed. I needed to generate a QR code real quick, opened some random website, and got hit with a wall of ads, a slow page load, and a QR code that looked like it was designed in 2005. I thought, "I could just build this myself." Famous last words, right?

Me deciding to build a Chrome extension instead of just using a website
Me deciding to build a Chrome extension instead of just using a website

The first version took me maybe a weekend. Just a basic Chrome extension popup - type some text, get a QR code, download it. Nothing fancy. I used the qrcode-generator library to draw it on a canvas. It worked. But honestly? It was boring. Just plain black-and-white squares. I looked at it and thought, "nah, we can do better than this."

That's when things got fun. I started messing with how the QR modules get drawn on the canvas. Instead of boring squares, I added rounded corners using arc paths, and then full circle dots. The difference was wild - same QR code, completely different vibe. Then I went down the gradient rabbit hole. Five direction modes: horizontal, vertical, diagonal, radial, and custom angle. Now you could make QR codes that actually matched your brand colors. Pretty cool stuff.

The scanner feature was where I really had to put my thinking cap on. Getting it to read QR codes from a camera feed sounds straightforward, but real life is messy. Bad lighting, blurry images, weird angles, inverted colors. My first attempt using jsQR worked fine for clean codes but choked on anything slightly tricky. So I built this multi-pass pipeline - try the original image first, then mess with the contrast at different levels, try inverting the colors, upscale tiny images. It's not elegant, but it catches almost everything now.

When the QR scanner finally reads a blurry code on the first try
When the QR scanner finally reads a blurry code on the first try

The feature I'm most proud of though? The animations. You can make your QR code build up piece by piece, fade in, pulse, do a color wave - five different styles. And you can export them as GIFs or Lottie files. Building that was a ride. Each animation type has its own rendering logic, frame by frame, using requestAnimationFrame. The GIF encoder runs in a Web Worker so it doesn't freeze the UI. It was a lot of work, but the first time I saw an animated QR code export perfectly... chef's kiss.

Tech-wise, the popup is React 19 + TypeScript + Vite. The background worker and scanner page are plain JS to keep things light. Everything talks through chrome.storage.local. I also added support for 9 languages, which was its own little adventure - the React side uses i18n-js, but the scanner page isn't React, so it has its own mini translation system that reads from storage. Fun times keeping those two in sync.

Honestly, CodeDusk taught me so much about how Chrome extensions actually work under the hood. Manifest V3 has its quirks - offscreen documents, service worker lifecycles, permission states. But the biggest takeaway? Sometimes the best projects come from just being annoyed enough to build something yourself.