- JavaScript 71.4%
- CSS 22.5%
- HTML 6.1%
Pre-AMO rename. The extension is now "Naiv-QR" everywhere it surfaces to users (toolbar tooltip, popup title, icon aria-label, README, package.json). Distribution target is AMO-listed, so the manifest no longer declares gecko.update_url — Firefox handles auto-updates from AMO directly for listed extensions, and the field is in fact rejected by Mozilla's validator outside self-distribution mode. - manifest.json: name → "Naiv-QR"; gecko.id → naiv-qr@addons.naiv.no; remove update_url. - package.json: name → "naiv-qr"; drop --self-hosted from lint script now that we're back to Mozilla-hosted validation. - popup/popup.html: <title> updated. - icons/icon.svg: aria-label updated. - README: retitled, removed Self-distribution section, updated Publishing-to-AMO section to spell out the listed-distribution flow. Build artifact is now web-ext-artifacts/naiv-qr-<ver>.zip (web-ext derives the filename from manifest.name). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .dogcats | ||
| icons | ||
| popup | ||
| scripts | ||
| vendor | ||
| .gitattributes | ||
| .gitignore | ||
| AGENTS.md | ||
| LICENSE | ||
| manifest.json | ||
| package.json | ||
| README.md | ||
| web-ext-config.cjs | ||
Naiv-QR
A small Firefox extension that turns the current tab's URL into a scannable QR code, so you can hand a page off to a phone (or another machine) without typing.
What you see
Click the toolbar icon while you're on any normal web page. A small popup opens showing:
- a black-and-white QR code (~280 px square) encoding the current URL,
- the URL itself in muted text below the QR,
- a Copy URL button that puts the URL on your clipboard.
The popup honours prefers-color-scheme, so dark-mode users get a dark
chrome around a white QR (the QR itself must stay light-on-dark for cameras
to read it).
On browser-internal pages (about:, chrome:, view-source:,
moz-extension:, data:, javascript:, resource:) the popup shows a
"This page can't be shared" message instead of attempting to encode the
URL. URLs longer than the largest QR version (~2.9 KB) get a "too long to
encode" message.
Supported Firefox versions
manifest.json sets strict_min_version: 142.0. That floor exists because
the manifest declares
browser_specific_settings.gecko.data_collection_permissions, which was
introduced in Firefox 140 (desktop) / 142 (Android).
Develop
This project uses bun as both the script runner and the
bundler. popup/popup.js imports the vendored QR library; bun build
inlines it into a single minified ESM file under dist/. Firefox loads the
extension from dist/, never from the source tree directly.
There are no runtime dependencies and no node_modules to install — bunx
pulls web-ext on demand. The first run is slow (download + cache); later
runs are fast.
bun run build # bundle popup.js + assets into dist/
bun run lint # build + web-ext lint (must be 0 errors / 0 warnings)
bun run package # build + produce a signable .zip in web-ext-artifacts/
bun run start # build + launch Firefox with the extension loaded
Loading the extension manually
After bun run build:
- Open
about:debugging#/runtime/this-firefoxin Firefox 142+. - Click Load Temporary Add-on… and pick
dist/manifest.json. - The QR icon appears in the toolbar. Click it on any normal page.
The temporary install is wiped when Firefox restarts; reload the same way
during dev. For a more persistent dev loop use bun run start, which
launches Firefox with the extension already loaded and auto-reloads on file
changes.
Build flow
popup/popup.js ──┐
│ bun build (esm, minified, browser target)
vendor/qrcode.js ─┘ │
▼
dist/popup/popup.js (~23 KB)
manifest.json, popup/{html,css}, icons/, vendor/LICENSE.qrcode-generator
└──── copied verbatim into dist/ ───────► dist/
web-ext operates on dist/ only, so the packaged zip contains exactly what
the build emitted — never AGENTS.md, .dogcats/, scripts/, or other repo-only
files.
Privacy
The extension makes no network requests. The QR code is generated
locally in the popup using the bundled vendor/qrcode.js library. The
browser_specific_settings.gecko.data_collection_permissions field in the
manifest declares "none" accordingly, which surfaces during AMO review and
in the install prompt.
Permissions used (both are the minimum the feature needs):
| Permission | Why |
|---|---|
activeTab |
Read the active tab's URL when the popup opens. |
clipboardWrite |
Implement the Copy URL button. |
Publishing to AMO
The plan is to distribute Naiv-QR through
addons.mozilla.org as a listed extension.
With listed distribution Firefox handles auto-updates from AMO directly —
the manifest must therefore not declare gecko.update_url.
bun run package produces web-ext-artifacts/naiv_qr-<ver>.zip from a
clean checkout. The zip contains only the files in dist/:
dist/
manifest.json
LICENSE.qrcode-generator
icons/icon.svg
popup/popup.html
popup/popup.css
popup/popup.js (bundled, minified)
For first-time AMO submission, use the web UI at
https://addons.mozilla.org/developers/addon/submit/ — upload the zip, then
fill in summary, description, screenshots, categories, and license (MIT).
Subsequent versions can be uploaded via the API with web-ext sign --channel listed once you have AMO credentials.
For the AMO source-code review step (required because of the bun build
step), point the reviewer at this repository and the pinned upstream commit
of vendor/qrcode.js documented below.
Third-party code
vendor/qrcode.js— kazuhikoarase/qrcode-generator, pinned to commit83b7e8fe3fddd3b0368dbafd6ce56995bd25e3c8. MIT licensed; full license text invendor/LICENSE.qrcode-generator(also copied intodist/so it ships with every build).
License
This project is MIT-licensed; see LICENSE.
Project layout
manifest.json MV3 manifest
popup/ Toolbar popup source (HTML/CSS/JS)
vendor/qrcode.js Bundled QR encoder (MIT, vendored, imported by popup.js)
icons/icon.svg Toolbar icon (single SVG, used at every size)
scripts/build.mjs Bun build + asset copy → dist/
web-ext-config.cjs Tells web-ext to operate on dist/
dist/ Build output (gitignored). What ships.