Defining an index

An index is schema. It lives in project config and deploys with your code, the way sections and fields do. Everything derived from it — records, artifacts, dependency edges — stays in the database and on disk.

Sources

Where records come from. Entries, categories, tags, assets, users and Commerce products are built in, and a plugin can register its own element type.

Each source is scoped to containers (section handles for entries, group handles for categories, volume handles for assets) and optionally types (entry types, or file kinds for assets). Leave either empty to include everything.

The status is almost always live. An index is a public artifact served as a static file — it cannot check who is asking, so a disabled entry that reached it would be visible to everyone.

Attributes

One row per key in a record. An attribute reads a value off the element and gives it one or more roles, which decide what Caffeine does with it.

RoleWhat it does
searchableText is tokenised into the artifact’s inverted index.
facetValues become a refinable facet.
sortableAn ordering over this key is precomputed into the artifact.
payloadThe value rides along on the hit, so Twig can render a card without a database round trip.

Roles are deliberately not exclusive. A product’s title is usually searchable, sortable and payload; its brand is usually facet and payload. Modelling them as a set rather than one “type” keeps the screen honest about the fact that one field feeds several parts of the artifact.

Where the value comes from

An attribute reads either an element attribute (title, slug, uri, postDate) or a custom field, by handle.

The path can descend, with dots:

PathReaches
titleThe element’s own title.
category.titleThe title of every related category.
specs.materialA field inside a Matrix field’s blocks.
venue.cityA named part of an extracted value — here, an address.

Descending into a relation denormalises: the category’s title is copied into the record at build time, which is what makes the count instant. Caffeine records every element it read in a dependency map, so renaming that category marks every record that copied it as stale. Without that, the artifact would serve a label that exists nowhere in the CMS.

Transforms

A fixed vocabulary applied to values in order — trim, lower, upper, stripTags, slug, unique, first, compact, date:FORMAT. Deliberately not an expression language: this runs over every value of every record on every build, and it arrives from project config, which is neither a safe nor a fast place for arbitrary code.

Sortings

Each named sorting is worked out once at build time and stored as a list of record IDs, so switching sort at query time is a pointer swap rather than a sort. They are Algolia’s “replicas” in everything but storage cost.

relevance always exists and needs no row. A sorting must name an attribute with the sortable role — one over a key with no precomputed order would have to sort at query time, which is the cost the whole plugin exists to avoid.

The rest

SettingWhat it does
TransportHow refinements reach the browser. See Transports.
Hits per pageThe default page size. A template can override it.
Values per facetHow many values a facet returns before “show more”.
Publish debounceSeconds to wait after a change before republishing, so a burst of edits costs one build. 0 republishes immediately.
Shard the payloadSplit the card data into its own file, so a facet-count request never fetches it.
SitesWhich sites to build records for. One record per element per site, because a facet value in French is not the same value as its English twin.

Checking your work

Two tools on the edit screen, both Pro:

The record preview runs the definition against one real element and shows exactly what the mapper produced — facets, sortable values, payload, tokens with their weights, and the elements the record now depends on. It is the fastest way to find out why a facet is empty.

The query playground runs a state against the published artifact and shows the result JSON with timing. Deliberately the published one rather than a fresh compile: the question it answers is “what are visitors getting”, and a playground that quietly recompiled would answer a different one.

Changing a definition

A changed definition invalidates every record built under the old one — a renamed key or a new facet means the stored records no longer match what the artifact needs. Rather than working out which changes are compatible, Caffeine marks the whole index stale and lets the next build settle it. Rebuilds are background work; a subtly stale artifact is a bug report.