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)

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 thedoccontext 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 withcache_scope="site"is captured, its HTML is stored. On subsequent renders of the same template, the cached HTML can be injected via _cached_blocksto skip redundant block execution.

Acontent_hashguard detects when a "site"-scoped block unexpectedly produces different output — indicating thecache_scopeclassification 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 withcache_scope="site". If a previously cached block produces a differentcontent_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_blocksto template.render(), or Noneif 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 bothcache_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 aFreezeCacheis 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 aFieldExtractorto pull structured fields (title, body, tags, etc.) from captured context. The default extractor reads from the doccontext key convention, returning raw text — not rendered HTML.

When the extractor does not provide abodyfield, 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 thedocconvention.

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