---
description: Learn how Studio indexes Post and Page text with FTS5, ranks matches, and rebuilds derived search data.
---

# Content Search

Studio searches Posts and Pages using derived, contentful FTS5 tables in
Studio D1. The saved documents remain authoritative. This index serves Studio
content lists; the public site's
[static search](https://zeropress.dev/guides/static-search/) is built separately.

## Indexed Text

Each Post and Page contributes its title, slug, excerpt, and reader-visible
body text. Autosaves and saved revisions are not separate results. Draft,
Published, and Trash documents are indexed, then filtered by the selected
status and the account's permitted content scope. All excludes Trash.

| Format | Body projection |
| --- | --- |
| HTML | Decoded text nodes; tags, attributes, comments, and script/style/template contents removed |
| Markdown | Rendered labels and text; markup, link destinations, and hidden HTML contents removed |
| Plain text | Control characters removed and whitespace collapsed |

The full projected body is indexed. The FTS row uses the document's public ID
and stores its source revision for consistency checks.

## Query and Ranking

The query is trimmed and limited to 200 UTF-16 code units. Unicode letters and
digits form tokens; internal `.`, `_`, and `-`, and names such as `C++` and
`C#`, are retained. Duplicate tokens are removed without regard to case.

Every token is required, but tokens may match different fields. Studio does
not interpret user input as raw FTS operators, wildcards, or column selectors.

The index uses the FTS5 trigram tokenizer with case-insensitive and diacritic
handling. Tokens of at least three code points use quoted FTS `MATCH` queries.
One- and two-code-point tokens use bound substring checks against the derived
text; a query containing only short tokens scans that derived table.

Long-token matches use BM25 weights of 8 for title, 5 for slug, 3 for excerpt,
and 1 for body. Short-token-only queries use the corresponding field priority.
Ties use most recently updated, then document ID. Lists without a search query
keep their normal ordering.

Excerpt and body matches can include a bounded plain-text context. The browser
adds highlighting from returned ranges; the API does not return snippet HTML.
Queries and snippets are excluded from operational logs.

## Keeping the Index Consistent

Content writes and the corresponding FTS updates share the same D1 batch.
This includes changed imports and restored revisions. A failed batch leaves
neither side changed; unchanged saves and imports do not rewrite the index.
Delete triggers remove derived rows when documents are permanently deleted.

An index rebuild uses checkpoints and revision checks so a batch cannot
overwrite a newer edit. Completion verifies counts, source revisions, orphan
rows, and FTS integrity before search becomes ready.

## Rebuilding

Fresh installations start with an empty, ready index. A logical restore or an
upgrade that invalidates search data marks it `rebuild_required`.

| State | Action |
| --- | --- |
| `rebuild_required` in operational mode | An administrator can start Rebuild from Dashboard → Service readiness → Post and Page search |
| Interrupted Dashboard rebuild | Select Continue rebuild; keep the Dashboard open to advance it |
| `recovery_required` or a forced restart | Use Operations in maintenance or recovery mode, with administrator re-verification |

The Dashboard path needs no Operations token or IP setup. Lists, editing, and
imports remain available while the index is rebuilt. Both rebuild paths share
the same saved checkpoint and cannot run conflicting database operations.

Search against a non-ready index returns `CONTENT_SEARCH_INDEX_NOT_READY`;
an index service failure returns `CONTENT_SEARCH_INDEX_UNAVAILABLE`. These
errors are not empty search results. An input with no searchable tokens returns
`CONTENT_SEARCH_QUERY_INVALID`.

## Backup and Restore

Studio logical backups preserve canonical content and the managed FTS schema,
but omit FTS shadow tables and derived rows. Restore creates an index that
needs rebuilding. Use [Studio backup and restore](../../operations/backups/index.md)
for this schema rather than native D1 export of its virtual tables.

SQLite documents the underlying
[FTS5 trigram tokenizer](https://www.sqlite.org/fts5.html#the_trigram_tokenizer).
