# render_manifest

URL: /kida/api/render_manifest/
Section: api
Description: Kida RenderManifest — batch capture accumulation, search indexing, and diffing.

Accumulates RenderCapture objects across multiple renders (e.g., during a
static site freeze) and provides search manifest generation and semantic
diffing between deploy snapshots.

RFC: render-capture

Example:
    from kida import Environment, FileSystemLoader, captured_render
    from kida.render_manifest import RenderManifest, SearchManifestBuilder

    env = Environment(loader=FileSystemLoader("templates/"), enable_capture=True)
    manifest = RenderManifest()

    for url, template_name, ctx in pages:
        template = env.get_template(template_name)
        with captured_render(capture_context=frozenset(ctx.keys())) as cap:
            html = template.render(**ctx)
        manifest.add(url, cap)

    # Auto-derive search index from block roles
    search = SearchManifestBuilder().build(manifest)
    print(search)

---

> For a complete page index, fetch /kida/llms.txt.

Open LLM text
(/kida/api/render_manifest/index.txt)

Share with AI

Ask Claude
(https://claude.ai/new?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Frender_manifest%2Findex.txt)

Ask ChatGPT
(https://chatgpt.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Frender_manifest%2Findex.txt)

Ask Gemini
(https://gemini.google.com/app?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Frender_manifest%2Findex.txt)

Ask Copilot
(https://copilot.microsoft.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Frender_manifest%2Findex.txt)

Module

#
`render_manifest`

Kida RenderManifest — batch capture accumulation, search indexing, and diffing.

Accumulates RenderCapture objects across multiple renders (e.g., during a
static site freeze) and provides search manifest generation and semantic
diffing between deploy snapshots.

RFC: render-capture

Example:

```
from kida import Environment, FileSystemLoader, captured_render
from kida.render_manifest import RenderManifest, SearchManifestBuilder

env = Environment(loader=FileSystemLoader("templates/"), enable_capture=True)
manifest = RenderManifest()

for url, template_name, ctx in pages:
    template = env.get_template(template_name)
    with captured_render(capture_context=frozenset(ctx.keys())) as cap:
        html = template.render(**ctx)
    manifest.add(url, cap)

# Auto-derive search index from block roles
search = SearchManifestBuilder().build(manifest)
print(search)
```

7Classes1Function

## Classes

`SearchEntry`

6

▼

Fields extractable from a RenderCapture for search indexing.

All fields are optional — extractors …

Fields extractable from a RenderCapture for search indexing.

All fields are optional — extractors return only what's available.

#### Attributes

Name
Type
Description

`t`

`str`

—

`d`

`str`

—

`body`

`str`

—

`c`

`str`

—

`tags`

`list[str]`

—

`toc`

`list[dict[str, Any]]`

—

`FieldExtractor`

1

▼

Protocol for extracting search fields from a capture.

Frameworks implement this to map their data …

Protocol for extracting search fields from a capture.

Frameworks implement this to map their data models to search entries.
The default extractor reads from the`doc`context key convention.

#### Methods

Internal Methods
1

▼

`__call__`

2

`SearchEntry`

▼

`def __call__(self, url: str, capture: RenderCapture) -> SearchEntry`

##### Parameters

Name
Type
Description

`url`
`—`

`capture`
`—`

##### Returns

`SearchEntry`

`FreezeCacheStats`

4

▼

Statistics for freeze cache performance during a batch render.

Statistics for freeze cache performance during a batch render.

#### Attributes

Name
Type
Description

`cache_hits`

`int`

—

`cache_misses`

`int`

—

`invalidations`

`int`

—

`blocks_cached`

`int`

—

`FreezeCache`

7

▼

Accumulates site-scoped block cache during a freeze (batch render).

Tracks block HTML by ``(templa…

Accumulates site-scoped block cache during a freeze (batch render).

Tracks block HTML by`(template_name, block_name)`key. When a block
with`cache_scope="site"`is captured, its HTML is stored. On subsequent
renders of the same template, the cached HTML can be injected via
`_cached_blocks`to skip redundant block execution.

A`content_hash`guard detects when a "site"-scoped block unexpectedly
produces different output — indicating the`cache_scope`classification
was wrong — and skips caching that block rather than serving stale content.

#### Attributes

Name
Type
Description

`_cache`

`dict[tuple[str, str], str]`

—

`_hashes`

`dict[tuple[str, str], str]`

—

`_invalidated`

`set[tuple[str, str]]`

—

`stats`

`FreezeCacheStats`

—

#### Methods

`record`

2

▼

Record site-scoped blocks from a completed render.

Only caches blocks with ``c…

`def record(self, template_name: str, capture: RenderCapture) -> None`

Record site-scoped blocks from a completed render.

Only caches blocks with`cache_scope="site"`. If a previously cached
block produces a different`content_hash`, the entry is invalidated
(removed from cache) to prevent serving stale content.

##### Parameters

Name
Type
Description

`template_name`
`—`

Name of the template that was rendered

`capture`
`—`

The RenderCapture from the completed render

`get_cached_blocks`

1

`dict[str, str] | None`

▼

Get cached block HTML for a template.

Returns a dict suitable for passing as `…

`def get_cached_blocks(self, template_name: str) -> dict[str, str] | None`

Get cached block HTML for a template.

Returns a dict suitable for passing as`_cached_blocks`to
`template.render()`, or `None`if no blocks are cached.

##### Parameters

Name
Type
Description

`template_name`
`—`

Name of the template to look up

##### Returns

`dict[str, str] | None`

Dict of block_name -> cached HTML, or None if nothing cached

Internal Methods
1

▼

`_is_cacheable`

1

`bool`

▼

Check if a fragment is eligible for freeze caching.

Requires both ``cache_scop…

staticmethod

`def _is_cacheable(frag: Fragment) -> bool`

Check if a fragment is eligible for freeze caching.

Requires both`cache_scope="site"` AND empty `depends_on`.
A block that reads context variables (even if classified as site-scoped
by static analysis) might produce different output per page.

##### Parameters

Name
Type
Description

`frag`
`—`

##### Returns

`bool`

`ManifestDiff`

4

▼

Result of comparing two RenderManifests.

Result of comparing two RenderManifests.

#### Attributes

Name
Type
Description

`added`

`list[str]`

URLs present in new manifest but not old

`removed`

`list[str]`

URLs present in old manifest but not new

`changed`

`dict[str, dict[str, tuple[str, str]]]`

URL -> {block_name -> (old_hash, new_hash)} for changed blocks

`unchanged`

`int`

Count of URLs with identical content

`RenderManifest`

7

▼

Accumulates captures across a batch of renders.

Each entry is a (url, RenderCapture) pair represen…

Accumulates captures across a batch of renders.

Each entry is a (url, RenderCapture) pair representing one rendered page.
Provides search index generation, semantic diffing, and cache analysis.

#### Attributes

Name
Type
Description

`version`

`int`

Manifest format version

`captures`

`list[tuple[str, RenderCapture]]`

List of (url, capture) pairs in insertion order

`freeze_cache`

`FreezeCache | None`

—

#### Methods

`add`

2

▼

Add a rendered page's capture to the manifest.

If a `FreezeCache` is attached,…

`def add(self, url: str, capture: RenderCapture) -> None`

Add a rendered page's capture to the manifest.

If a`FreezeCache`is attached, automatically records
site-scoped blocks for cache reuse on subsequent renders.

##### Parameters

Name
Type
Description

`url`
`—`

The URL or path of the rendered page

`capture`
`—`

The RenderCapture from rendering this page

`all_fragments`

0

`Iterator[tuple[str, Frag…`

▼

Iterate over all (url, fragment) pairs across all captures.

`def all_fragments(self) -> Iterator[tuple[str, Fragment]]`

##### Returns

`Iterator[tuple[str, Fragment]]`

`unique_content_hashes`

0

`dict[str, int]`

▼

Count unique content hashes across all fragments.

`def unique_content_hashes(self) -> dict[str, int]`

##### Returns

`dict[str, int]`

Dict mapping content_hash -> number of occurrences.
Hashes with count > 1 represent deduplatable content.

`diff`

1

`ManifestDiff`

▼

Compute semantic diff between this manifest and another.

Compares by URL, then…

`def diff(self, other: RenderManifest) -> ManifestDiff`

Compute semantic diff between this manifest and another.

Compares by URL, then by block content_hash within each URL.

##### Parameters

Name
Type
Description

`other`
`—`

The older manifest to compare against.

##### Returns

`ManifestDiff`

ManifestDiff with added, removed, changed URLs and block-level changes.

`SearchManifestBuilder`

3

▼

Builds a search manifest from a RenderManifest.

Uses a `FieldExtractor` to pull structured fields …

Builds a search manifest from a RenderManifest.

Uses a`FieldExtractor`to pull structured fields (title, body,
tags, etc.) from captured context. The default extractor reads from the
`doc`context key convention, returning raw text — not rendered HTML.

When the extractor does not provide a`body`field, falls back to
assembling body text from rendered block HTML weighted by role.

#### Attributes

Name
Type
Description

`role_weights`

`dict[str, float]`

Mapping of role -> weight (0.0 = excluded from search). Used only for the HTML fallback path.

`field_extractor`

`Callable[[str, RenderCapture], SearchEntry] | None`

Callable that extracts search fields from a capture. Defaults to :func:`default_field_extractor`.

#### Methods

`build`

1

`dict[str, Any]`

▼

Build a search manifest from captured renders.

`def build(self, manifest: RenderManifest) -> dict[str, Any]`

##### Parameters

Name
Type
Description

`manifest`
`—`

RenderManifest containing captured page data

##### Returns

`dict[str, Any]`

Search manifest dict with version, facets, and entries.
Compatible with Chirp's search manifest format.

## Functions

`default_field_extractor`

2

`SearchEntry`

▼

Extract search fields from capture context using the ``doc`` convention.

Reads…

`def default_field_extractor(url: str, capture: RenderCapture) -> SearchEntry`

Extract search fields from capture context using the`doc`convention.

Reads`capture.context_keys["doc"]`for structured fields:

- `doc.title`→ title

- `doc.body` or `doc.content`→ body (raw text, not HTML)

- `doc.metadata.description`→ description

- `doc.metadata.category`→ category

- `doc.metadata.tags`→ tags

- `doc.toc`→ table of contents

Returns only fields that are present on the doc object.

##### Parameters

Name
Type
Description

`url`
`str`

`capture`
`RenderCapture`

##### Returns

`SearchEntry`
