How Blobify works
Blobify stores content as JSON in an S3-compatible bucket owned by your organization. The API handles authenticated writes and management operations. Websites, static builds, and generated clients read published JSON directly from the bucket.
The write and read paths
Saving a draft writes one mutable source document:
spaces/{spaceId}/content/{model}/{contentId}/draft.jsonPublishing also writes a public snapshot containing the locales that are live:
spaces/{spaceId}/content/{model}/{contentId}/published.jsonThe source documents are written during the API request. Blobify then queues a reconcile job that updates derived summaries and indexes. Lifecycle webhooks are sent after the worker has converged those derived files, so a receiver can fetch the new output immediately.
The dashboard follows the same storage contract. It reads the summary manifest and the immutable shard versions named by that manifest instead of guessing object names.
Draft and published data
Draft documents contain all editable locales and audit events with actors. Published documents contain only published locales and strip actor identities from public audit timestamps.
This separation keeps unpublished work private while giving a website a stable snapshot. See Content JSON for the exact document shapes.
Summaries and indexes
Blobify creates three kinds of derived read output:
| Output | Use it for |
|---|---|
| Summary shards | Broad model lists and build-time enumeration |
| Field indexes | Exact value lookups such as slug to content ID |
| List indexes | Ordered, paginated feeds such as latest articles |
Summary shards are immutable, versioned files. A state manifest at summaries/{state}/index.json identifies the current file for every non-empty shard. Field indexes are value-keyed. List indexes use a v2 manifest whose pages array points to immutable files such as g3/p00000.json.
Read Summaries and indexes before constructing any bucket URL yourself. The generated TypeScript client already implements these read rules.
Routing
Routing is generated separately from content and stored at the organization level:
routing/draft.json
routing/published.jsonA model route can turn semantic fields such as slug into a URL without storing that URL in the content document. Routing can therefore be rebuilt or changed without rewriting every entry.
Assets
Each asset has a metadata document, an asset-catalog projection, and an original media file. Content stores a semantic reference such as { "type": "asset", "assetId": "img_456" }. Generated clients resolve that reference against asset metadata and the configured delivery URL.
Media files remain under spaces/{spaceId}/assets/media/. They are not moved by a content prefix.
Content prefixes
A space can set contentPrefix to make predictable JSON keys harder to discover. Blobify keeps logical paths stable but rewrites physical keys for content, summaries, field indexes, list indexes, and archived content:
Logical: spaces/main/content/article/art_123/published.json
Physical: spaces/main/_blobify/site_a1/content/article/art_123/published.jsonThe generated client and dashboard apply this mapping automatically. Asset media files remain unprefixed. The asset catalog follows the prefix because it is JSON derived data.
Archive-first deletion
Deleting a live entry moves its current draft and published files to:
spaces/{spaceId}/archive/{model}/{contentId}/The entry can then be restored. A permanent delete is the second action on an already archived entry. Archive and restore also reconcile summaries, field indexes, and list indexes so normal readers do not return archived content.
Permissions
Organization members and API keys use the same role hierarchy and space scopes. A key can be limited to named spaces, so automation behaves like a service member instead of using a separate permission model. See Security and access for the role boundaries.