Skip to content

Add a QR code — six presets, and the ones you saved in Universal QR - #158

Merged
JamesmarkeyUK merged 1 commit into
mainfrom
claude/qr-code-generator-presets-sriuwr
Aug 12, 2026
Merged

Add a QR code — six presets, and the ones you saved in Universal QR#158
JamesmarkeyUK merged 1 commit into
mainfrom
claude/qr-code-generator-presets-sriuwr

Conversation

@JamesmarkeyUK

Copy link
Copy Markdown
Collaborator

A QR button in the toolbar (desktop: beside the image button; mobile: beside Image) opens a cut-down Universal QR — a link box and six style presets — and drops the generated code on the page.

It is an image annotation, not a new type

"Add to page" renders a 1024px PNG, hands it to setUploadedImageSrc and arms the existing image tool, so placing, moving, resizing, undoing and baking into the export are all machinery that already existed. At the default ~200pt that works out around 360dpi, so the code scans off a printed page rather than only off a screen.

Sharing a design model with Universal QR

src/lib/qr/ is a port of Universal QR's renderer, kept faithful on purpose:

File From Notes
design.ts its lib/qr.ts QrDesign is a field-for-field copy of its QrConfig; the six presets are its PRESETS verbatim
frames.ts its lib/frames.ts shaped plates (circle/star/hexagon/…), canvas path only
decor.ts its lib/decor.ts the burst/scatter marks a shaped plate is filled with
render.ts its lib/compose.ts one canvas composite for plain and shaped codes alike

The editor is what is simplified, not the format — a design imported from Universal QR is restored whole, and a code that rendered differently in the two apps would be the version of this feature nobody trusts.

Your saved codes, with no backend

Universal QR keeps designs in localStorage under unisim.qr.designs.v1, and in production the two apps are the same origin (opensource.unisim.co.uk/pdf and /qr, both behind the opensource-portal Worker) — so the dialog simply lists them, and clicking one restores its link, colours, plate and any uploaded logo. No account, no API, no round trip.

That store is read-only here: it belongs to another app, is capped at 12 entries, and evicting someone's saved design because they added a QR to a PDF would be a bad trade. The origin is not guaranteed either (pdf.unisim.co.uk, the Electron build), so a .uniqr.json backup import covers everywhere else.

Colours

qrContrastIssue warns on an inverted code (light modules on dark — strict decoders reject those) or a low-contrast one (right polarity, too thin a ratio). The six presets all pass; the check is for designs arriving from Universal QR's full studio, where a code can scan on a screen and fail in print — and an exported PDF is the place nobody notices until the poster comes back.

Verification

Driven in a real headless browser, not eyeballed:

  • Parity — all six presets rendered through both apps' pipelines and diffed pixel by pixel: identical. The sole delta is the centre mark's antialiasing (Universal QR inlines a 256px data URI of the icon; here the shipped unisim-icon.png is downscaled by the browser).
  • End to end — design → place → export → re-render the exported page with pdf.js → decode the QR back out of it: passes.
  • Decoding — every preset decodes with @zxing/library (the decoder Universal QR validated against) at every size the app renders. They fail only at 96px and, for Star, 256px — sizes nothing renders at; placement is 1024px, preview 448px.
  • Fixed one layout bug found this way: the preset grid truncated every name to "Cla…" on a phone — now two columns below sm.

npm run typecheck and npm run build both clean. No new dependencies — qr-code-styling was already here for the sign-on-phone QR.

Note, unrelated to this change

src/lib/brandedQr.ts (the sign-on-phone QR) renders orange modules on near-black — an inverted code by the standard Universal QR documents at length, and one its own scanner rejects. It evidently works in practice for that flow, so it is untouched here, but it may be worth a look.

🤖 Generated with Claude Code

https://claude.ai/code/session_01J76Zc6mr4RsdYpqVGenDdk


Generated by Claude Code

A QR button in the toolbar (desktop: beside the image button; mobile: beside
Image) opens a cut-down Universal QR — a link box and six style presets — and
drops the generated code on the page.

It is an image annotation, not a new type. "Add to page" renders a 1024px PNG,
hands it to setUploadedImageSrc and arms the existing image tool, so placing,
moving, resizing, undoing and baking into the export are all machinery that
already existed. At the default ~200pt that works out around 360dpi, so the
code scans off a printed page rather than only off a screen.

src/lib/qr/ is a port of Universal QR's renderer, kept faithful on purpose:
QrDesign is a field-for-field copy of its QrConfig, the presets are its PRESETS
verbatim, and the shaped-plate geometry and decoration come across whole. The
EDITOR is what is simplified, not the format — a design imported from Universal
QR is restored whole, and a code that rendered differently in the two apps
would be the version of this feature nobody trusts. Checked by rendering all
six presets through both pipelines and diffing the pixels: identical, the sole
delta being the centre mark's antialiasing (Universal QR inlines a 256px data
URI; here the shipped icon is downscaled by the browser).

Your saved codes arrive with no backend at all. Universal QR keeps designs in
localStorage under unisim.qr.designs.v1, and in production the two apps are the
same origin — opensource.unisim.co.uk/pdf and /qr — so the dialog simply lists
them, and clicking one restores its link, colours, plate and logo. That store
is read-only here: it belongs to another app, is capped at 12 entries, and
evicting someone's design because they added a QR to a PDF would be a bad
trade. The origin is not guaranteed either (pdf.unisim.co.uk, Electron), so a
.uniqr.json backup import covers everywhere else.

qrContrastIssue warns on an inverted or thin-contrast code. The six presets all
pass; the check is for designs arriving from Universal QR's full studio, where
a code can scan on a screen and fail in print — and an exported PDF is the
place nobody notices until the poster comes back.

Verified end to end in a browser: design → place → export → re-render the
exported page with pdf.js → decode the QR back out of it. All six presets
decode with @zxing/library at every size the app renders.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J76Zc6mr4RsdYpqVGenDdk
@JamesmarkeyUK
JamesmarkeyUK merged commit 611256a into main Aug 12, 2026
2 checks passed
@JamesmarkeyUK
JamesmarkeyUK deleted the claude/qr-code-generator-presets-sriuwr branch August 12, 2026 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants