Module

orchestration.related_posts

Related Posts orchestration for Bengal SSG.

Builds related posts index during build phase for O(1) template access.

Classes

RelatedPostsOrchestrator
Builds related posts relationships during build phase. Strategy: Use taxonomy index for efficient …
7

Builds related posts relationships during build phase.

Strategy: Use taxonomy index for efficient tag-based matching. Complexity: O(n·t) where n=pages, t=avg tags per page (typically 2-5)

This moves expensive related posts computation from render-time (O(n²)) to build-time (O(n·t)), resulting in O(1) template access.

Methods 1

build_index
Compute related posts for pages using tag-based matching. This is called once …
3 None
def build_index(self, limit: int = 5, parallel: bool = True, affected_pages: list[Page] | None = None) -> None

Compute related posts for pages using tag-based matching.

This is called once during the build phase. Each page gets a pre-computed list of related pages stored in page.related_posts.

Parameters 3
limit int

Maximum related posts per page (default: 5)

parallel bool

Whether to use parallel processing (default: True)

affected_pages list[Page] | None

List of pages whose related posts should be recomputed. If None, computes for all pages (full build). If provided, only updates affected pages (incremental).

Internal Methods 6
__init__
Initialize related posts orchestrator.
1 None
def __init__(self, site: Site)

Initialize related posts orchestrator.

Parameters 1
site Site

Site instance

_build_sequential
Build related posts sequentially (original implementation).
4 int
def _build_sequential(self, pages: list[Page], page_tags_map: dict[Page, set[str]], tags_dict: dict[str, dict[str, Any]], limit: int) -> int

Build related posts sequentially (original implementation).

Parameters 4
pages list[Page]

List of pages to process

page_tags_map dict[Page, set[str]]

Pre-built page -> tags mapping

tags_dict dict[str, dict[str, Any]]

Taxonomy tags dictionary

limit int

Maximum related posts per page

Returns

int

Number of pages with related posts found

_build_parallel
Build related posts in parallel using ThreadPoolExecutor. Each page's related …
4 int
def _build_parallel(self, pages: list[Page], page_tags_map: dict[Page, set[str]], tags_dict: dict[str, dict[str, Any]], limit: int) -> int

Build related posts in parallel using ThreadPoolExecutor.

Each page's related posts computation is independent, making this perfectly parallelizable. On Python 3.14t (free-threaded), this achieves true parallelism without GIL contention.

Performance:

  • Python 3.13 (GIL): 2-3x faster
  • Python 3.14t (no GIL): 6-8x faster
Parameters 4
pages list[Page]

List of pages to process

page_tags_map dict[Page, set[str]]

Pre-built page -> tags mapping

tags_dict dict[str, dict[str, Any]]

Taxonomy tags dictionary

limit int

Maximum related posts per page

Returns

int

Number of pages with related posts found

_set_empty_related_posts
Set empty related_posts list for all pages.
0 None
def _set_empty_related_posts(self) -> None

Set empty related_posts list for all pages.

_build_page_tags_map
Build mapping of page -> set of tag slugs. This creates an efficient lookup st…
0 dict[Page, set[str]]
def _build_page_tags_map(self) -> dict[Page, set[str]]

Build mapping of page -> set of tag slugs.

This creates an efficient lookup structure for checking tag overlap. Now uses pages directly as keys (hashable based on source_path).

Returns

dict[Page, set[str]]

Dictionary mapping Page to set of tag slugs

_find_related_posts
Find related posts for a single page using tag overlap scoring. Algorithm: 1. …
4 list[Page]
def _find_related_posts(self, page: Page, page_tags_map: dict[Page, set[str]], tags_dict: dict[str, dict[str, Any]], limit: int) -> list[Page]

Find related posts for a single page using tag overlap scoring.

Algorithm:

  1. For each tag on the current page
  2. Find all other pages with that tag (via taxonomy index)
  3. Score pages by number of shared tags
  4. Return top N pages sorted by score
Parameters 4
page Page

Page to find related posts for

page_tags_map dict[Page, set[str]]

Pre-built page -> tags mapping (now uses pages directly)

tags_dict dict[str, dict[str, Any]]

Taxonomy tags dictionary {slug: {pages: [...]}}

limit int

Maximum related posts to return

Returns

list[Page]

List of related pages sorted by relevance (most shared tags first)