Live at ezqr.ca.
What it does
EZQR generates QR codes. It does two things well:
- Static codes encode a URL directly into the QR pixels. They are free forever, with no watermark and no expiry. Good for posters, business cards, and anything where the destination will never change.
- Dynamic codes encode an EZQR short link that redirects to whatever destination the owner sets. The destination is editable after the code has been printed, and every scan is logged with country, device, and timestamp. This is the paid tier.
It also covers the long tail of "I just need a QR for X" — vCards, WiFi credentials, Google Drive files, PDFs, event sign-ups, and so on — with category-specific landing pages that match how people actually search.
Why I built it
Most QR generators are either ad-laden free tools or full SaaS products with a strict free tier that pushes you into a $20-per-month plan for anything useful. I wanted a generator that treated static codes as a forever-free utility and only charged for the things that genuinely need a server — dynamic redirects, scan analytics, and bulk management.
It also gave me a reason to build a real product end-to-end on my own time: marketing site, billing, authentication, dashboard, deployment, support — none of which I get to own from scratch inside a larger company.
Stack
- Backend is Go — QR generation, short-link redirects, scan ingestion, and the management API
- Marketing site is Astro, static-rendered, with content-first SEO landing pages per use case
- Dashboard is a Vue SPA for paid users to manage their codes and view analytics
- Auth is Ory Kratos — battle-tested identity infrastructure rather than rolling my own
- Billing is Stripe with subscription tiers and a Stripe-managed billing portal
- Deployment is a single Docker image, deployed with a small shell script to my own infrastructure
- Tests are end-to-end with Cypress against the running stack via docker-compose
Try the generator
The EZQR generator is also embeddable on any website in two lines of HTML — there's a live demo in that post.