A modern, open-source QR scanner and generator that runs entirely in your browser. Built with Next.js (App Router, static export), TypeScript, Tailwind CSS v4, and a Material Design 3 theme. Hosted on GitHub Pages.
Privacy-first. Camera frames, uploaded images, and generated QR codes never leave your device. There are no accounts, trackers, analytics, or required backend services.
- Real-time camera scanning with throttled, low-CPU decoding (preview and decode loop are separate; frames are downscaled).
- Rear/front camera switching, plus torch and zoom when the device supports them.
- Proper camera lifecycle - streams are stopped on success, unmount, tab hidden, and device removal.
- Sound and haptic feedback (progressive enhancement).
- Image scanning via file upload, drag & drop, and Ctrl/⌘+V paste
- all through one local decode pipeline with multi-scale/crop/contrast preprocessing.
- Duplicate detection and a manual scan again action.
- Clear error states for denied permission, no camera, and busy camera.
Parses and shows tailored actions for: URLs, text, email, phone, SMS, WhatsApp, Wi-Fi, vCard, calendar events, and geo coordinates.
- URLs show the hostname first, warn on suspicious links, and are never
opened automatically;
javascript:/data:/file:are blocked. - Wi-Fi shows SSID/security with reveal/hide password and copy.
- vCard downloads
.vcf; events download.ics. - Geo opens in maps; text downloads
.txt. - Copy and Web Share are used with fallbacks.
- Saved locally in
localStorage(timestamp, type, raw value, parsed data). - Favorites, per-item delete, and clear (keeps favorites), capped at 200 non-favorite entries.
A step-based builder (Content → Design → Logo → Download):
- Presets for link, text, e-mail, call, SMS, WhatsApp, Wi-Fi, vCard, event, geo, social, app/deep link, image, and video (media presets encode a link to where the media is hosted).
- Colors, transparent background, size, quiet zone, error correction (L–H), dot/module styles, finder styles, and an optional label frame.
- Browser-only logo/image embedding - preview, resize, padding, and rounded background; error correction is forced to H and oversized logos warn you.
- PNG, SVG, and WebP download with meaningful filenames (
recqr-qr.*). - Settings persist in
localStorage.
- Next.js (App Router,
output: "export") - React 19 + TypeScript
- Tailwind CSS v4 with Material Design 3 tokens
- jsQR for decoding
qrcodefor matrix generation- Zustand for persisted history
- Vitest for tests
npm install
npm run dev # http://localhost:3000npm run lint
npm test # unit tests + SVG->pixels->jsQR decode round-trips (resvg)
npm run build # static export into ./outBrowser-level checks (require a running npm run dev, a one-off
npm i --no-save playwright esbuild, and a Chromium binary - set
CHROMIUM_PATH to use one you already have):
npm run test:render # Canvas/SVG rendered in real Chromium, decoded with jsQR
npm run test:visual # 7 viewports x 6 routes: horizontal overflow, clipping,
# QR bounds, preview decode, mobile section order
npm run test:download # downloads PNG/SVG from the UI and decodes themThe included workflow (.github/workflows/nextjs.yml) builds and deploys on
push to main. basePath/assetPrefix are configured automatically from the
repository name. See docs/github-pages.md.
worker/ contains an optional Hono Worker that generates QR SVGs over
HTTP. The web app does not use it - scanning and generation are 100%
client-side. There is no server-side decode endpoint by design. See
docs/api.md.
See the docs/ directory:
- Getting started
- Scanner
- Generator
- Supported QR formats
- Privacy
- Security model
- Browser support
- GitHub Pages
- Architecture
- Optional Edge API
- Troubleshooting
- Contributing
To avoid overpromising, RECQR does not provide:
- Dynamic/editable QR codes
- Analytics or scan tracking
- Official SDKs (JS/React/Flutter/etc.)
- Webhooks
- A server-side QR image decoder
These could exist as separate services but are intentionally out of scope of the privacy-first web app.
MIT - see LICENSE.