Back to notes

Exploration note

NFC tokens pointing at a manifest

Cassettes, diskettes, and cartridges as physical handles for digital media. The rule that makes the whole family of projects work: the tag points, it never hosts.

Hardware contracts / Published Jun 10, 2026 / Revised Sep 7, 2026

A cluster of retro media projects in progress: a cassette shell with decoder electronics, powered inductively through a coil in the player’s door; cartridge- and diskette-shaped tokens that select games on a small player; mini diskettes that resolve to music playlists on an ESP32 player, meant to be handed out to family alongside the player — a music library you can physically give someone.

The hardware varies. The architecture is one decision applied three times: NFC tags identify, they never carry. A tag holds a key and nothing else. The key resolves through a manifest — best described as a hosts file for media — with one entry per key: source, destination, protocol. The reader dispatches on protocol: jellyfin, youtube, http, local. Repointing a token means editing a text file, not reprogramming a tag that may be glued inside a cassette shell in someone else’s house.

The manifest lives somewhere boring with git history, which turns out to be most of the value. “What did this diskette point at last year” is a log lookup, and a bad repoint rolls back. Because the manifest layer is public, it carries no credentials — those live in each reader’s local config, so the contract layer stays publishable and the secrets stay at the edge where they belong.

The failure mode worth designing against is the one Toniebox-style products ship with: a keepsake whose function depends on a link staying alive. These tokens are gifts, and a gift shouldn’t have planned obsolescence built in. So readers cache last-known-good resolutions, and the pre-loaded variants exist precisely so the physical object outlives the playlist, the server, and if necessary the curator’s infrastructure.

One fork deliberately left open per project: key on the tag’s factory UID, or on a value written to tag memory. UID keying identifies a specific enrolled tag but requires enrolling every physical tag into the manifest; written keys make tokens interchangeable and freely reskinnable. What UID keying does not buy is authenticity: a factory-programmed identifier only shows that a reader saw that identifier, and commodity emulators can present a chosen UID — NXP’s own system-security guidance discusses exactly this. If an application ever needs proof that the object is the original, that is a separate cryptographic requirement on the tag, not a property of the UID. A family music token needs none of it. Enrolment friction points one way, reskinnability the other, and a game cartridge and a gifted diskette can reasonably choose differently.

This sits in a different register from the rest of the site, but it’s the same instinct in a toy shell: a thin, versioned contract between the thing you hold and the thing it means, so either side can change without breaking the other.

Reference:MarkdownDownload

Optional exploration template

Portable task language, not part of the note.

A post-hoc prompt for applying and extending this note. It is not a reconstruction of how the note was written.

Use this note as a worked contract, not a hardware project. The transferable question: when a physical object stands for digital content, what should the object carry, and what has to live somewhere you can still edit after the object has left your hands? The worked answer is one decision applied across three unrelated builds: the tag identifies, it never hosts. It holds a key and nothing else; the key resolves through a manifest with one entry per key giving source, destination, and protocol, and the reader dispatches on protocol. Repointing means editing a text file rather than reprogramming a tag glued inside someone else's device. The manifest lives in version control, so what a token pointed at last year is a log lookup and a bad repoint rolls back; because that layer is public it carries no credentials, which stay in each reader's local config. The failure mode designed against is a keepsake whose function depends on a link staying alive, so readers cache last-known-good resolutions. One fork is left open: keying on factory UID identifies an enrolled tag but requires enrolment and is identification rather than authenticity -- emulators can present a chosen UID -- while written keys make tokens interchangeable and reskinnable, and cryptographic authenticity is a separate requirement an application may not need at all. Apply the question to an artifact you are building that stands for something remote. Name the indirection layer, where it is versioned, and what the object does when the far side is gone. Say where your constraints differ, and produce the contract plus the fork you are leaving open.