No description
  • JavaScript 71.4%
  • CSS 22.5%
  • HTML 6.1%
Find a file
Ole-Morten Duesund dfebf75052 v0.1.1: change gecko.id to share-as-qr@addons.naiv.no, bump version
Move the extension ID off the dev-placeholder .local TLD onto the
naiv.no domain so it's stable for any future AMO submission. AMO locks
the ID for the lifetime of a listing, so this needs to happen before
the first listed upload — not after.

No code or behaviour changes. Lint and package both still clean
(0 errors / 0 warnings, ~12 KB zip).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:39:49 +02:00
.dogcats Document the extension and add MIT LICENSE 2026-05-11 16:12:34 +02:00
icons Initial commit: Share-as-QR Firefox extension with bun build 2026-05-11 16:04:22 +02:00
popup Document the extension and add MIT LICENSE 2026-05-11 16:12:34 +02:00
scripts Document the extension and add MIT LICENSE 2026-05-11 16:12:34 +02:00
vendor Initial commit: Share-as-QR Firefox extension with bun build 2026-05-11 16:04:22 +02:00
.gitattributes Initial commit: Share-as-QR Firefox extension with bun build 2026-05-11 16:04:22 +02:00
.gitignore Initial commit: Share-as-QR Firefox extension with bun build 2026-05-11 16:04:22 +02:00
AGENTS.md Initial commit: Share-as-QR Firefox extension with bun build 2026-05-11 16:04:22 +02:00
LICENSE Document the extension and add MIT LICENSE 2026-05-11 16:12:34 +02:00
manifest.json v0.1.1: change gecko.id to share-as-qr@addons.naiv.no, bump version 2026-05-11 16:39:49 +02:00
package.json v0.1.1: change gecko.id to share-as-qr@addons.naiv.no, bump version 2026-05-11 16:39:49 +02:00
README.md Document the extension and add MIT LICENSE 2026-05-11 16:12:34 +02:00
web-ext-config.cjs Initial commit: Share-as-QR Firefox extension with bun build 2026-05-11 16:04:22 +02:00

Share as 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:

  1. Open about:debugging#/runtime/this-firefox in Firefox 142+.
  2. Click Load Temporary Add-on… and pick dist/manifest.json.
  3. 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

bun run package produces a deterministic web-ext-artifacts/share_as_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 AMO source-code review, point the reviewer at this repository and the pinned upstream commit of vendor/qrcode.js documented below.

Third-party code

  • vendor/qrcode.jskazuhikoarase/qrcode-generator, pinned to commit 83b7e8fe3fddd3b0368dbafd6ce56995bd25e3c8. MIT licensed; full license text in vendor/LICENSE.qrcode-generator (also copied into dist/ 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.