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:

textcode
spaces/{spaceId}/content/{model}/{contentId}/draft.json

Publishing also writes a public snapshot containing the locales that are live:

textcode
spaces/{spaceId}/content/{model}/{contentId}/published.json

The 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:

OutputUse it for
Summary shardsBroad model lists and build-time enumeration
Field indexesExact value lookups such as slug to content ID
List indexesOrdered, 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:

textcode
routing/draft.json
routing/published.json

A 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:

textcode
Logical:  spaces/main/content/article/art_123/published.json
Physical: spaces/main/_blobify/site_a1/content/article/art_123/published.json

The 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:

textcode
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.