From dfebf75052af29bcdcd1f2f820aa9b442493c3c2 Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Mon, 11 May 2026 16:39:49 +0200 Subject: [PATCH 1/5] v0.1.1: change gecko.id to share-as-qr@addons.naiv.no, bump version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- manifest.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index e93b490..e4fafb4 100644 --- a/manifest.json +++ b/manifest.json @@ -1,11 +1,11 @@ { "manifest_version": 3, "name": "Share as QR", - "version": "0.1.0", + "version": "0.1.1", "description": "Share the current tab's URL as a scannable QR code.", "browser_specific_settings": { "gecko": { - "id": "share-as-qr@olemd.local", + "id": "share-as-qr@addons.naiv.no", "strict_min_version": "142.0", "data_collection_permissions": { "required": ["none"] diff --git a/package.json b/package.json index b45a3f3..8a23303 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "share-as-qr", - "version": "0.1.0", + "version": "0.1.1", "private": true, "description": "Firefox extension: share the current tab's URL as a QR code.", "license": "MIT", From 1f82d7f0d36dc40def64fb6107778bde3de292d1 Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Mon, 11 May 2026 16:51:54 +0200 Subject: [PATCH 2/5] v0.1.2: rebrand to Naiv-QR, target AMO-listed distribution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: 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> --- README.md | 22 +++++++++++++++++----- icons/icon.svg | 2 +- manifest.json | 6 +++--- package.json | 4 ++-- popup/popup.html | 2 +- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2a28be3..1fde9e0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Share as QR +# 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 @@ -95,8 +95,13 @@ Permissions used (both are the minimum the feature needs): ## 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/`: +The plan is to distribute Naiv-QR through +[addons.mozilla.org](https://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/ @@ -108,8 +113,15 @@ dist/ 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. +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 diff --git a/icons/icon.svg b/icons/icon.svg index ec7e228..8397aff 100644 --- a/icons/icon.svg +++ b/icons/icon.svg @@ -1,4 +1,4 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" role="img" aria-label="Share as QR"> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" role="img" aria-label="Naiv-QR"> <rect width="32" height="32" rx="6" fill="#1f2937"/> <g fill="#f9fafb"> <!-- Top-left finder --> diff --git a/manifest.json b/manifest.json index e4fafb4..13812d9 100644 --- a/manifest.json +++ b/manifest.json @@ -1,11 +1,11 @@ { "manifest_version": 3, - "name": "Share as QR", - "version": "0.1.1", + "name": "Naiv-QR", + "version": "0.1.2", "description": "Share the current tab's URL as a scannable QR code.", "browser_specific_settings": { "gecko": { - "id": "share-as-qr@addons.naiv.no", + "id": "naiv-qr@addons.naiv.no", "strict_min_version": "142.0", "data_collection_permissions": { "required": ["none"] diff --git a/package.json b/package.json index 8a23303..25df07a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "share-as-qr", - "version": "0.1.1", + "name": "naiv-qr", + "version": "0.1.2", "private": true, "description": "Firefox extension: share the current tab's URL as a QR code.", "license": "MIT", diff --git a/popup/popup.html b/popup/popup.html index 2deadc8..15a9792 100644 --- a/popup/popup.html +++ b/popup/popup.html @@ -2,7 +2,7 @@ <html lang="en"> <head> <meta charset="utf-8"> - <title>Share as QR + Naiv-QR From 004b63f51c91f1e01edee70e0c4a7c320d08e16e Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Mon, 11 May 2026 17:02:48 +0200 Subject: [PATCH 3/5] Add CLAUDE.md with build and architecture guidance Documents the dcat issue workflow rule, bun commands, and the non-obvious invariants future agents need: dist/ is the single source of truth for what ships, the Firefox 142 floor and no-gecko.update_url constraint for AMO-listed distribution, the pinned qrcode-generator SHA and UTF-8 override, and the popup error-path conventions. Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..b3e3b5b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,58 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Workflow + +- **Read `AGENTS.md` first.** It defines the mandatory `dcat` (dogcat) issue-tracking workflow used here. The hard rule: **before writing any code for a new bug, feature, or change, ask the user whether to create an issue first** — no exceptions for "small" tasks. Run `dcat prime` after compaction, `/clear`, or starting a new session. +- After committing, show a short summary of what was committed and why (per the user's global guidelines). + +## Commands + +```sh +bun run build # bundle popup.js + copy assets into dist/ +bun run lint # build, then web-ext lint (must be 0 errors / 0 warnings) +bun run package # build, then produce a signable .zip in web-ext-artifacts/ +bun run start # build, then launch Firefox with the extension (auto-reload) +``` + +There is no test suite. `bun run lint` is the closest thing to CI — it must pass clean before publishing. The first invocation downloads `web-ext` via `bunx`; subsequent runs are fast. + +Always use `bun` / `bunx` (never `npm`/`npx`/`yarn`). + +## Architecture + +Naiv-QR is a Manifest V3 Firefox extension with no background script and no content script — just a toolbar action that opens a popup. When the user clicks the icon, `popup/popup.js` runs once, reads the active tab's URL via `browser.tabs.query` (allowed by `activeTab` only on user gesture), and renders an SVG QR code locally using the vendored `qrcode-generator` library. There are zero network requests. + +### `dist/` is the only thing that ships + +`scripts/build.mjs` is the **single source of truth** for what the extension contains. It: + +1. Wipes `dist/`. +2. Runs `Bun.build` on `popup/popup.js` (esm, browser target, minified). The `import qrcode from "../vendor/qrcode.js"` line is what causes the vendored library to get inlined — there is no global `qrcode` at runtime. +3. Copies `manifest.json`, `popup/popup.html`, `popup/popup.css`, `icons/`, and `vendor/LICENSE.qrcode-generator` verbatim into `dist/`. + +`web-ext-config.cjs` points `web-ext` at `dist/` only, so lint/package/run all operate on the build output. **Adding a file to the repo does not put it in the extension** — if a new asset (icon, locale, script) needs to ship, update `scripts/build.mjs` to copy it. + +### Compatibility & distribution constraints + +- `manifest.json` sets `strict_min_version: 142.0`. This floor exists because `browser_specific_settings.gecko.data_collection_permissions` was introduced in Firefox 140 desktop / 142 Android. Don't lower it without also removing that field. +- Target distribution is **AMO-listed**. The manifest must **not** declare `gecko.update_url` — AMO handles auto-updates for listed extensions, and adding an update URL breaks the listed-channel review. +- Permissions are deliberately minimal: `activeTab` (read current tab on click) and `clipboardWrite` (Copy URL button). Adding a new permission needs explicit justification — it's user-visible at install/upgrade and surfaces during AMO review. +- `data_collection_permissions` declares `"none"`. If any code is ever added that does collect data (telemetry, error reporting, etc.), that field must be updated honestly — it's surfaced to users during AMO review and at install time. + +### Vendored QR library + +`vendor/qrcode.js` is [kazuhikoarase/qrcode-generator](https://github.com/kazuhikoarase/qrcode-generator), pinned to commit `83b7e8fe3fddd3b0368dbafd6ce56995bd25e3c8`. AMO source-code review requires we point reviewers at this pinned upstream. If the vendored file is updated, update the pinned SHA in `README.md` and `vendor/LICENSE.qrcode-generator` if needed. + +`popup.js` sets `qrcode.stringToBytes = qrcode.stringToBytesFuncs["UTF-8"]` because the library defaults to SJIS — without this, non-ASCII URLs would be misencoded. + +### Popup error paths + +`popup.js` has three "can't render" branches that all route through `showMessage()`: + +- `browser.tabs.query` throws → "Could not read the active tab." +- URL protocol is in `PRIVILEGED_PROTOCOLS` (`about:`, `moz-extension:`, `chrome:`, `view-source:`, `resource:`, `javascript:`, `data:`) → "This page can't be shared." +- `qrcode-generator` throws because the URL exceeds the largest QR version (~2,953 bytes for EC level L; we use M ≈ ~2,331) → "URL is too long to encode." + +When adding new error states, keep them on this same `showMessage()` path so the popup never ends up in an inconsistent half-rendered state. From 3fef3d85a8136a2074eca6e6beb2d31d67214469 Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Mon, 11 May 2026 17:14:00 +0200 Subject: [PATCH 4/5] Forbid TodoWrite in CLAUDE.md; point at dcat workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors the rule we already have in ønskenytt.no/CLAUDE.md so fresh agents don't reach for the built-in task tools when this repo manages work via dcat. Also switches the prime invocation to the recommended `dcat prime --opinionated` form. Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index b3e3b5b..4096d9a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Workflow -- **Read `AGENTS.md` first.** It defines the mandatory `dcat` (dogcat) issue-tracking workflow used here. The hard rule: **before writing any code for a new bug, feature, or change, ask the user whether to create an issue first** — no exceptions for "small" tasks. Run `dcat prime` after compaction, `/clear`, or starting a new session. +- **Read `AGENTS.md` first.** It defines the mandatory `dcat` (dogcat) issue-tracking workflow used here. The hard rule: **before writing any code for a new bug, feature, or change, ask the user whether to create an issue first** — no exceptions for "small" tasks. Run `dcat prime --opinionated` after compaction, `/clear`, or starting a new session. +- **Do NOT use the `TodoWrite` / task tools in this project.** Issue tracking and progress is managed with `dcat` as specified in `AGENTS.md` — see that file for the full workflow (`dcat prime --opinionated`, `dcat list --agent-only`, status transitions, closing rules, etc.). - After committing, show a short summary of what was committed and why (per the user's global guidelines). ## Commands From 31ffddfcf452c1ce8f3ba5655942962b7a7364d2 Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Mon, 11 May 2026 17:14:41 +0200 Subject: [PATCH 5/5] Use `dcat prime --opinionated` in AGENTS.md Aligns with CLAUDE.md (commit 3fef3d8) so both files agree on the recommended prime invocation. Co-Authored-By: Claude Opus 4.7 (1M context) --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 2949866..6e4d794 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ DOGCAT WORKFLOW GUIDE ## Rules - Run `dcat prime` after compaction, clear, or new session + Run `dcat prime --opinionated` after compaction, clear, or new session BEFORE writing any code for a new bug, feature, or change: ask the user if you should create an issue first. No exceptions for 'small' tasks — the rule exists for traceability, not