Summaries and indexes
Blobify publishes derived JSON so a frontend can enumerate content, find one entry by a known value, or page through an ordered feed without scanning every content document.
Summary shards
Summary shards are the broad listing layer. Each draft or published state has one manifest and a set of per-model immutable shard files.
spaces/main/summaries/published/index.json
spaces/main/summaries/published/article/s000.1783796607793.json
spaces/main/summaries/draft/index.json
spaces/main/summaries/draft/article/s000.1783796607793.jsonThe manifest uses format version 2 and maps each logical shard name to its current versioned object key:
{
"formatVersion": 2,
"state": "published",
"models": {
"article": {
"total": 2,
"shardCount": 1,
"shards": {
"s000": "s000.1783796607793.json"
},
"version": 1783796607793
}
}
}Always fetch index.json first, then fetch the file names in the model's shards map. Shard files are immutable. Clients must not guess the current version from a timestamp or build s000.{version}.json themselves.
Shard count is adaptive. Blobify uses 1, 16, or 64 shards based on the size and current tier of the dataset, so consumers must follow the manifest instead of assuming a fixed count.
summaryFields controls which content fields appear. summaryMetadata controls configurable system metadata in published summaries. Draft summaries also include the metadata required by the dashboard, including publishedLocales, publish and update status, and the draft-only updatedBy audit event. Published summaries never expose the editor actor.
The dashboard's content list reads the draft summary manifest and the immutable shard keys it names. Published sites normally read the published state.
Field indexes
Field indexes support exact lookups such as slug to content ID. Configure them with fieldIndexes on a model.
{
"fieldIndexes": [
{ "field": "slug", "normalizer": "slug-v1", "unique": true }
]
}Non-translatable and translatable fields use different logical paths:
spaces/main/lookups/published/article/sku/s076.json
spaces/main/lookups/published/article/slug/en/s076.jsonThe shard is chosen from the normalized field value, not the content ID. slug-v1 trims and lowercases its input before lookup. exact-v1 keeps exact-value semantics.
The generated client's getOne(...) reads the relevant value shard and then loads the content document. API upsert uses the same index path, with a content-document scan as a correctness fallback while derived output is still converging.
Field indexes maintain internal reverse-pointer shards under lookups/{state}/{model}/_reverse/ so the worker can remove stale values after an edit. Direct clients read the value shards, not those reverse pointers.
Unique fields
Saving a model automatically derives a required field index for each text or slug field marked unique: true. Translatable fields are unique per locale. Non-translatable fields are unique globally.
List indexes
List indexes provide ordered, locale-specific feeds. A model config chooses a field or metadata sort source and an ascending or descending order.
{
"listIndexes": [
{
"id": "latest",
"source": { "kind": "metadata", "name": "lastPublished" },
"order": "desc",
"state": "published"
}
]
}List index v2 uses one manifest and generational page files:
spaces/main/list-indexes/published/article/latest/en/index.json
spaces/main/list-indexes/published/article/latest/en/g3/p00000.json
spaces/main/list-indexes/published/article/latest/en/g3/p00001-v4.jsonThe manifest is the ordered source of truth:
{
"formatVersion": 2,
"model": "article",
"indexId": "latest",
"state": "published",
"locale": "en",
"gen": 3,
"total": 2011,
"pages": [
{ "key": "g3/p00000.json", "count": 1024 },
{ "key": "g3/p00001-v4.json", "count": 987 }
]
}pages[].key is relative to the locale directory and must be treated as opaque. Storage-page counts vary, and the manifest count is authoritative. There is no model pageSize setting for these storage pages, no reverse-shard directory, and no nextPage cursor chain between page files.
The generated client's listByIndex(model, indexId, locale, { page, pageSize }) computes UI pagination across one or more storage pages and returns { items, total, totalPages, page, nextPage }. That runtime pageSize is independent of storage page sizing.
Rebuild derived output
Schema saves do not rebuild existing derived files. After changing summary fields, field indexes, list indexes, display fields, or unique flags on an existing model, run the narrowest rebuild that covers the change.
| Scope | Endpoint |
|---|---|
| All spaces | POST /v1/orgs/{orgId}/schemas/models/{model}/rebuild-summaries |
| All spaces | POST /v1/orgs/{orgId}/schemas/models/{model}/rebuild-field-indexes |
| All spaces | POST /v1/orgs/{orgId}/schemas/models/{model}/rebuild-list-indexes |
| All spaces | POST /v1/orgs/{orgId}/schemas/models/{model}/rebuild-all |
| One space | POST /v1/orgs/{orgId}/content/{spaceId}/{model}/rebuild-summaries |
| One space | POST /v1/orgs/{orgId}/content/{spaceId}/{model}/rebuild-field-indexes |
| One space | POST /v1/orgs/{orgId}/content/{spaceId}/{model}/rebuild-list-indexes |
| One space | POST /v1/orgs/{orgId}/content/{spaceId}/{model}/rebuild-all |
Each endpoint accepts optional ?state=draft or ?state=published. With no state, it rebuilds both. A valid request returns 202 Accepted after enqueueing work. The queue worker performs the rebuild asynchronously.
Content prefixes
If a space sets contentPrefix, Blobify rewrites summary, lookup, and list-index keys under the physical prefix:
spaces/main/_blobify/site_a1/summaries/published/index.json
spaces/main/_blobify/site_a1/lookups/published/article/slug/en/s076.json
spaces/main/_blobify/site_a1/list-indexes/published/article/latest/en/index.jsonThe dashboard and generated client handle this automatically.
Pick the right output
- Use a content document when you know the content ID and need full fields.
- Use summaries for broad enumeration and build-time lists.
- Use a field index for an exact lookup by a configured value.
- Use a list index when ordering and scalable UI pagination matter.
Summary fields, field indexes, and list indexes are independent model settings. Including slug in a summary does not create a field index, and adding a field index does not add that field to summaries.