When we launched shareable tracks on beats.bitwrap.io, every render got a content-addressed URL — a CIDv1 that is the track, so the same bytes always resolve to the same address. That worked well enough that the renderfarm started producing more artifacts than any single app wanted to own: mixes, stems, provenance envelopes, arrangement writeups.
cdn.stackdump.com is where they landed. It's a content-addressed file host — cdn.stackdump.com/ipfs/<CID>/<path> — but the interesting part isn't the storage. It's that every entry is a small markdown document whose YAML frontmatter is the metadata of record, and the whole site reads and presents that frontmatter as a first-class feature. A polydocument host: one storage contract, many content types, no per-type code.
An entry is a directory named after its CID, sitting under data/blobs/<CID>/. Whatever files you put inside become public paths — audio.webm shows up at cdn.stackdump.com/ipfs/<CID>/audio.webm. Because a CID is immutable, nginx serves everything under it with Cache-Control: public, max-age=31536000, immutable. The address can't drift, so the cache never has to expire.
Two rules keep the corpus honest:
index.md. No index.md, and the scanner ignores the directory entirely — it isn't indexed and it isn't served.cid: field in that frontmatter must match the directory name. A mismatch is a loud error at scan time, not a silent 404 later.The index.md markdown body becomes the rendered landing page. The frontmatter becomes everything else.
Every entry declares what it is before it says anything else. The minimum viable frontmatter is four fields:
title: "Cohesion v2 · trance · seed 14"
cid: z4EBG9j1EeuXVzM6TSfgWdiTLkhV4srzufQwJvMyMnPJcmZGtD4
source: beats-bitwrap-io
schema: BeatsShare/v1
source is the producing project — the repo directory name, so you can always trace an artifact back to the thing that made it. schema is a versioned type name, <TypeName>/v<int>, describing what's inside the CID rather than which app emitted it. BeatsShare/v1 is a beats render envelope; BeatsRemix/v1 is a renderfarm arrangement; BlogPost/v1, PetriNet/v1, and Dataset/v1 are all shapes a producer could add tomorrow without touching the host.
The versioning is the point. Bump BeatsShare/v1 to v2 when the shape changes and every old v1 entry keeps resolving exactly as it did. Two projects emitting the same logical thing share a schema; the same project evolving its output forks a version. This is the same discipline we run on Petri-net models — pin the specification, let the implementations move — applied to stored artifacts.
Beyond the four required fields, frontmatter is open. A beats render carries genre, seed, tempo, cohesion, provenance, farm, renderedAt, and a tags list. A Petri-net entry could carry metamodel, net, place and transition counts. The host doesn't have a column for any of these, and it doesn't need one.
The indexer keeps a generic key-value table over every scalar frontmatter field — and every element of a scalar array — so any field you write is queryable the moment it's indexed. Exact match is ?meta.<key>=<value>; anything that parses as a number gets a range filter, ?meta.<key>.min= and ?meta.<key>.max=. Add bpm: 140 to your frontmatter and ?meta.bpm.min=120 works immediately, with no migration and no code.
That table is what makes the frontend build itself. On load the search page hits /api/facets, which reports the distinct source, schema, genre, and tag values that actually exist plus the list of metadata keys present across the corpus — then populates its dropdowns from that, counts and all (techno (5)). The advanced panel exposes a raw key/value pair that folds straight into a meta.<key>=<value> filter. A field you invented for your own producer becomes a live query control the same day, with zero UI code written for it.
The CID landing page does the mirror image. The server renders a definition list of the well-known fields, then iterates every remaining producer-defined scalar and renders it generically underneath. A non-beats entry surfaces its own vocabulary — metamodel: petri-arrangement, net: petri-cycle — without the template knowing those keys exist. Result cards lead with source and schema as type badges, then pick a preview by content: an audio player for a mix, a thumbnail grid for images, a file list for everything else. Any object type is at least navigable.
Content addressing gives you deduplication for free. It also gives you provenance, if you write it down. Entries carry an optional parents: list — the CIDs they were derived from:
source: beats-builder
schema: BeatsRemix/v1
metamodel: petri-arrangement
net: petri-cycle
parents:
- bafyreie841526edd53002a8e54cfb31326b61e
- bafyrei47dd48f108dae83db7d543ceb5f0786e
Because parents are named by CID and CIDs are immutable, the lineage is a real DAG — you can't rewrite an ancestor without changing its address, and changing its address means it's a different node. A remix that claims two parents is claiming two exact prior states, byte for byte. It's the past-tense witnessing we keep coming back to: the audit trail isn't a log written alongside the artifact, it's the artifact's own addresses all the way down.
The showpiece entry is a petri-cycle arrangement whose markdown body is a Petri-net writeup: song sections are places, section moves are transitions, inhibitor arcs cap how often the track revisits a section. The stored document explains its own structure in the same abstraction the rest of the ecosystem runs on.
The same binary runs in two modes. The master lives on the local valoper workstation, bound to loopback, and is the only thing that accepts writes. The mirror runs on the pflow.dev host, read-only, and serves the public cdn.stackdump.com vhost.
Publishing writes a CID directory on the master, pings its /admin/reload?cid=<CID> to index that one directory, then rsyncs only the blobs to the mirror and pings the mirror's reload to rebuild its index in place. The SQLite index file itself is never copied — a running WAL-mode process that finds its database swapped out from under it fails with database disk image is malformed, so the mirror rebuilds through its own healthy connection instead of ever receiving a foreign file. Blobs move; indexes are always local.
Most of what's in the corpus today was written by Claude — renderfarm output, generated arrangements, envelopes with stego provenance baked in. That's a fine way to fill a content-addressed store quickly, but it's not what the store is for.
The four-field contract — title, CID, source, schema — is exactly as useful for a human dropping in a dataset, a model export, a snapshot of a blog post, or a set of field notes. Write the frontmatter, and the search facets, the range filters, the type badges, and the auto-rendered metadata list all come for free. The lineage fields are there when you want a remix or a revision to point at what it came from. draft: true keeps a work-in-progress out of the feed and search while still reachable by its direct URL, so you can stage before you publish.
The premise is the same one we apply to everything here: pin a small, explicit schema, and let the tooling read it. The producer can be a renderfarm or a person. The host doesn't care, and that's the feature.
Browse it at cdn.stackdump.com.