The freeside-* attachment module for file storage layout + static-asset CDN + NFT metadata serving + retrieval API. The canonical abstraction across NFT metadata, music, archetype images, future blob types. Closes
loa-freeside#167.
This repo is a stub today. It establishes the shape so future content has a home; substantive work lands when the parallel metadata-module-placement design session crystallizes OR when the next 502MB-music-style friction surfaces (whichever comes first).
Renamed twice: freeside-metadata → freeside-filesystem (2026-04-28 late) → freeside-storage (2026-04-29 — final canonical name; sovereign asset-surface framing per Sprint 1 of mature-freeside-operator-and-cutover cycle). See [[freeside-modules-as-installables]] §"Why the renames" and ADR-001 (in this repo) for the placement decision.
Doctrine: freeside-modules-as-installables (instance-3 of the freeside-* attachment-prefix family; siblings: freeside-worlds, freeside-score, freeside-ruggy).
NFT metadata is bytes. Static assets (music, images, archetype PNGs) are bytes. Layout (where bytes live + how they're keyed) is a storage concern. CDN delivery is storage-serving. Retrieval API is storage-querying. One abstraction; many surfaces.
The earlier freeside-filesystem framing scoped the same surface but under a metaphor that implied directory hierarchy. freeside-storage is the more accurate canonical name — it covers object stores, CDNs, IPFS, and future archival adapters under one common interface (StorageAdapter, per ADR-001).
Per loa-freeside#167: Honey Road's 502MB of static music + archetype PNGs blocked the Docker build for 37+ minutes. The fix — S3 + CloudFront with per-world buckets — is filesystem-shaped infrastructure. This module owns that pattern.
Per Eileen's adjacent file-system framing (multiple issues across the org around storage-shaped concerns): the substrate is what the org is missing. This module is its home.
freeside-storage/
├── packages/
│ ├── protocol/ 📐 StorageAdapter interface + URL contract + metadata schemas + retrieval API contract
│ ├── adapters/ 🔁 typed clients for serving + retrieval (S3, IPFS, Arweave, local)
│ ├── storage-layouts/ 🗂 per-pattern templates (NFT collection layout,
│ │ per-world music, per-Door asset bundles)
│ ├── cdn-config/ 🚀 terraform fragments for the CDN side (per #167)
│ └── cli/ 🛠 freeside-storage CLI for managing layouts + sync to S3 + invalidate
└── docs/
├── INTENT.md why this module exists
├── ADR-001-package-layout.md (Sprint 1 of mature-freeside-operator-and-cutover) lean instance-1 lock
├── EXTRACTION-MAP.md (when content lands) what to pull from where
└── INTEGRATION-PATH.md (when content lands) staged cutover plan
The packages/protocol/ slot is consistent across every freeside-* module per [[loa-org-naming-conventions]] single-vocab doctrine.
Recent friction the org hit:
- Honey Road 502MB Docker build (
loa-freeside#167): docker build hung 37+ minutes copying music. Ad-hoc fix:.dockerignore public/music. Music URLs 404 at runtime. Future worlds with big assets will hit the same wall. - Irys gateway death 2026-04-27:
mibera-honeyroad's tokenURI resolver stopped working when the metadata gateway died. Recovery required ad-hoc re-hosting + per-consumer re-coding. No shared module to swap in. - Cross-collection metadata duplication: each NFT collection (Honeycomb, Henlo, Mibera, future) reimplements its own JSON serving + CDN strategy.
- File-system layout drift: per-token JSON file naming + directory shape diverges between collections. Re-hosting requires per-collection work.
- No agent surface for metadata queries: ruggy's persona-bot can't ask "what trait does token #12345 have" without bespoke per-collection HTTP fetches.
Each wants a shared sealed contract. This repo is where that contract goes.
- Per-collection metadata content (each collection's tokenURI JSON files belong to that collection's repo)
- World-specific renderers (each world's metadata UI lives in that world's app)
- Chain-specific tokenURI implementations (live in
mibera-contracts, etc.) - The actual S3 buckets / CloudFront distributions (those are loa-freeside terraform — this repo provides the schema + module input shape)
Per [[freeside-modules-as-installables]]: design with module boundaries from day 1; let extraction follow when it earns the cycles. The repo exists; substantive content waits for either:
- the parallel
metadata-module-placementdesign session to land, OR - the next 502MB-music-style friction (when an operator hits the wall a second time)
The scaffold reserves the name + establishes shape; content flows in when design crystallizes.
| sibling | role |
|---|---|
freeside-worlds |
world manifests + creator + protocol + registry |
freeside-score |
scoring schemas; sibling pattern reference |
freeside-ruggy |
persona-bot consuming metadata schemas for collection-aware fan-out |
MIT.
🌱 instance-3 stub. Name-clarified 2026-04-28 late: filesystem, not metadata. The shape exists; the content waits for friction.