Treasure-hunt chains
A treasure hunt is the one occasion on this site that is inherently plural: a hunt of 5 clues is 5 codes, and running a single-code generator that many times is most of the work of making one. The chain module on the treasure-hunt page turns a list of clues into a numbered, ordered set of cards in one pass. This guide explains what that module decides and what it leaves alone, using a fictional chain built by the engine when this page was built; every number below comes from that build.
What the treasure-hunt preset encodes
The treasure-hunt preset starts on the Ring frame style and carries a
message payload: the clue is the
content, not a link to a page about the clue. The frame’s default art colour is
#a16207.
A ring frame is one of the 5 frame templates (heart, floral, ring, classic, confetti), and all of them follow one measured rule: the code itself is not modified at all. The rendered QR, quiet zone included, is nested verbatim on an opaque panel drawn above the frame art, so decoration cannot touch a module by construction, and recolouring the ring changes nothing inside the panel. The caption under the panel is limited to 200 characters over at most 4 lines. The framed-codes guide covers the panel in detail.
The preset’s own example, rendered at build time by the engine the tool runs: a fictional clue carried as an offline note, the words in the code itself.
Clue 4 of 6: I keep winter warm and summer waiting. Look inside me. (Hint: hallway)
83 characters; version 8 at 49 × 49 modules, 57 across with the 4-module quiet zone, error correction H.
From a pasted draft to clue texts
The chain module is pure: it takes a list of strings and decides what each card says, its number and its caption; the chain page then encodes each card as a reveal link. Before the module runs, a parser splits the textarea into clue texts under rules that are short and tested: one clue per line, Windows and Unix line endings both accepted, every line trimmed, and blank lines dropped rather than turned into empty cards. Line-per-clue is used because, in the module’s reasoning, a hunt is usually drafted somewhere else and pasted in whole.
This guide’s fictional draft was written with blank lines, stray indentation and Windows line endings on purpose. It is 7 lines long and parses to 5 clues:
- Start where the kettle sleeps.
- I have four legs but never walk. Look under me.
- Cold inside, humming outside. Check my door.
- I hold the coats that nobody wears in summer.
- You found it. The prize is yours.
From clue texts to a numbered chain
The chain builder numbers the clues against the total. Numbering is explicit on every card because, as the module’s header puts it, a hunt’s cards are hidden around a house or a park and inevitably found out of order; without a number, a card found early silently skips the hunt. The last card is flagged as final so it can be captioned as the prize rather than as another step. The captions for the 5 clues above:
- Clue 1 of 5
- Clue 2 of 5
- Clue 3 of 5
- Clue 4 of 5
- The prize · 5 of 5 — marked final
The builder also enforces the chain’s length: at least 2 clues — a first one and whatever it leads to — and at most 20, beyond which, in the module’s words, a hunt stops being a hunt. Both refusals are plain messages, quoted in the FAQ below; whitespace-only lines count toward neither limit.
What each card’s code carries
A clue is a message, so a clue card is a message keepsake and the measured facts about message keepsakes apply to it unchanged. A QR code containing bare text carries no scheme, so a phone has nothing to act on. Apple’s Camera and Google’s ML Kit both recognise links, phone numbers, email addresses, contact cards, calendar events and Wi-Fi joins — and no plain-text type. Faced with bare text, an iPhone offers to copy or search it and Google Lens simply runs a web search, so the message is the one thing the reader never sees. Samsung phones and dedicated scanner apps do display it, but a keepsake cannot depend on which phone opens it.
So a clue gets the same two honest modes as any message. A reveal link encodes a
normal URL to the reveal page at /m/ on this site, with the clue carried in
the URL’s fragment — the part after the #. Per RFC 3986 a fragment is stripped
before a request is made, so the clue never reaches a server, a CDN or a log; it is decoded
entirely on the reader’s device. An offline note writes the words into the code itself,
needs no connection ever, and accepts the display caveat above. In both modes the clue is also printed
on the card. The chain page encodes every card as a reveal link, the mode the rest of the site defaults
to; the preset’s example above shows the offline-note form.
The fragment format is published so the codes stay readable with or without this site:
#, one flag character (A for UTF-8 bytes,
B for raw-deflate compressed bytes), the payload in unpadded uppercase base32
(RFC 4648), then one base32 checksum character. Base32 is used because some scanners change the case
of what they read and base32 survives that; its alphabet is also a subset of the QR alphanumeric character
set. The first card of the fictional chain, exactly as the engine built it:
https://KEEPSAKECODES.NET/M/#AKN2GC4TUEB3WQZLSMUQHI2DFEBVWK5DUNRSSA43MMVSXA4ZOF
The clue is 30 characters; its fragment is 50: the flag
A, a 48-character base32 body, and the checksum
F. The engine confirms the whole fragment sits inside the QR
alphanumeric set: true. The flag is
A because no compressor was supplied: the generators on this site pass none,
so every card the chain page produces carries flag A. Given a compressor,
the engine encodes both ways and keeps whichever base32 payload is shorter. Rather than assume
which way that goes for clues this short, this page handed the engine a raw-deflate compressor
when it was built and recorded the result card by card — card 1: 30 bytes raw, 32 deflated, flag A; card 2: 47 bytes raw, 49 deflated, flag A; card 3: 44 bytes raw, 44 deflated, flag A; card 4: 45 bytes raw, 47 deflated, flag A; card 5: 33 bytes raw, 35 deflated, flag A. For these 5 clues the raw encoding won every time, so each kept flag A. A reveal message is accepted up to 300 characters. The
message-keepsakes guide walks through the
format and the self-contained HTML download.
The fictional chain, measured
Each card below was built by the chain module, then encoded twice by the engine at error correction H: as the reveal link the chain page produces, and as an offline note of the same words. “Across” adds the 4-module quiet zone on each side, which is what actually gets printed. The last column is the engine’s minimum print width for the reveal-link card, computed from its working minimum module of 0.5 mm.
| Card | Clue (chars) | Reveal link | Offline note | Min. width |
|---|---|---|---|---|
| Clue 1 of 5 | 30 | v8, 49 × 49 (57 across) | v4, 33 × 33 (41 across) | 28.5 mm |
| Clue 2 of 5 | 47 | v10, 57 × 57 (65 across) | v6, 41 × 41 (49 across) | 32.5 mm |
| Clue 3 of 5 | 44 | v10, 57 × 57 (65 across) | v5, 37 × 37 (45 across) | 32.5 mm |
| Clue 4 of 5 | 45 | v10, 57 × 57 (65 across) | v6, 41 × 41 (49 across) | 32.5 mm |
| The prize · 5 of 5 | 33 | v8, 49 × 49 (57 across) | v4, 33 × 33 (41 across) | 28.5 mm |
Two things are visible. The reveal link costs modules — the URL’s scheme, host and path ride in every card and base32 expands the clue’s bytes — so the same words encode to a higher version as a link than as a note. And the clue’s length in UTF-8 bytes is the only lever — these clues are plain ASCII, so bytes equal characters: the shortest clue (30 characters) is version 8, the longest (47 characters) version 10.
The engine’s comfortable ceiling for a printed keepsake is 65 modules across, quiet zone included; past that, a code stops fitting the objects these codes go on. No card in this fictional chain exceeds it. The preset’s 83-character example is version 8 as an offline note but would be version 13 — 77 across — as a reveal link, past the ceiling. When a card fails verification, the chain page asks for a shorter clue rather than printing around it; the ceiling here is the engine’s separate print-size limit.
What verification proves for a chain, and what it cannot
The chain module changes nothing about verification. After each card is rendered, the browser rasterises the finished artwork and runs a real decoder (jsQR) on the pixels at 3 raster sizes, 800, 1200, 1600 px, comparing the decoded bytes to the card’s exact payload. A single fixed raster can false-negative through sampling resonance, so the “Verified scannable” badge is earned when at least 2 of the 3 rasters match byte for byte. A card that falls short is marked unverified, and the chain is not offered for printing until every card has earned the badge. The decode-verification guide explains the rule and its measurements.
Verification cannot see past the screen: it proves the artwork decodes cleanly at screen resolution, not what your printer, your paper, or the scanning phone will do. The methodology’s general guidance applies to a clue card as to any keepsake: print at least 2 × 2 cm for arm’s-length scanning, keep the quiet zone uncropped, and scan a test print with a real phone before the moment that matters. The engine also computes a floor of its own for each card — the width at which that card’s modules reach 0.5 mm — and that is the minimum-width column above, from 28.5 mm to 32.5 mm across this chain. Every one of those floors is above the general 2 cm, so for these cards the engine’s figure is the one that governs. Print each card at whichever of the two is larger. The printing guide covers the size readouts in full.
Common misreadings
Cropping the quiet zone. The 4-module quiet zone is a mandatory clear margin on all four sides of the symbol; the engine always draws it and cannot be told not to, so it is required, not optional padding. On a framed card it sits inside the opaque panel, so the frame art can never cover it — but a crop made after download can. That is why the “across” figures include it: a 49 × 49 symbol is printed as 57 modules, not 49.
Expecting bare text to display. An offline note is bare text, and the facts above say what that means on the phones named; the reveal link side-steps the question, and both modes print the clue on the card.
Confusing the frame’s colour with the code’s colour. The preset’s default ring gold,
#a16207, measures 4.92:1 against white by the
engine’s WCAG contrast function. For a frame that number is irrelevant, because frame art never
touches a module: the code inside the panel is the engine’s default black on white, at
21.00:1. It matters as the module colour of a code — the artistic engine
requires at least 4.5:1 for heart and halftone styles and rejects
weaker pairs rather than warning. This gold
would pass that gate; the
heart-module guide shows accepted and rejected
pairs.
Treasure-hunt chain FAQ
How many clues can one chain hold?
Between 2 and 20. Below the minimum the chain module returns “A hunt needs at least 2 clues — the first one and whatever it leads to”; above the maximum it returns “A chain holds at most 20 clues”. Both limits are engine constants and both refusals are tested.
Why is every card numbered, and why is the last one different?
Because, in the module’s own words, a hunt’s cards are inevitably found out of order, and without a number a card found early silently skips the hunt. The final card is marked and captioned as the prize (“The prize · 5 of 5” here) rather than as another step.
Does each card in a chain get its own verification?
Yes. The chain module only decides what each card says, its number and its caption; rendering and verification are unchanged, so every card must earn the same scannable claim individually — 3 raster sizes, at least 2 exact byte matches.
What will a phone show when it scans a clue card?
A clue is a message, so the message rules apply: bare text carries no scheme, so a phone has nothing to act on — an iPhone offers to copy or search it and Google Lens runs a web search, while Samsung phones and dedicated scanner apps do display it. A reveal link encodes an ordinary URL with the clue in its fragment instead, and both modes also print the clue on the card.
Why does a longer clue make a denser code?
The encoder sizes each code to fit its payload at error correction H. In this guide’s fictional chain the shortest clue (30 characters) is a version 8 reveal-link code and the longest (47 characters) is version 10; the engine treats 65 modules across, quiet zone included, as the comfortable ceiling for a card.
Can I paste a hunt drafted somewhere else?
Yes: one clue per line, Windows or Unix line endings, each line trimmed, blank lines ignored rather than turned into empty cards. This guide’s fictional draft has 7 lines and parses to 5 clues.
Build a chain on the treasure-hunt page, or read the other guides. Every render is decode-verified in your browser before it can leave the page as a finished keepsake; the rules behind that check, and the measured limits of every style, are on the methodology page.