Module

orchestration.menu

Menu orchestration for Bengal SSG.

Handles navigation menu building from config and page frontmatter. Supports incremental menu building with caching, i18n localization, and active state tracking. Menus are built during content discovery and cached for template access.

Key Concepts:

  • Menu sources: Config definitions, page frontmatter, section structure
  • Incremental caching: Menu cache invalidation on content changes
  • i18n menus: Localized menu variants per language
  • Active state: Current page and active trail tracking

Related Modules:

  • bengal.core.menu: Menu data structures (MenuItem, MenuBuilder)
  • bengal.core.site: Site container that holds menus
  • bengal.rendering.template_functions.navigation: Template access to menus

See Also:

  • bengal/orchestration/menu.py: MenuOrchestrator for menu building logic

Classes

MenuOrchestrator
Orchestrates navigation menu building with incremental caching. Handles menu building from config …
8

Orchestrates navigation menu building with incremental caching.

Handles menu building from config definitions, page frontmatter, and section structure. Supports incremental menu building by caching menus when config and menu-related pages are unchanged.

Creation:

Direct instantiation: MenuOrchestrator(site)
  • Created by BuildOrchestrator during build
  • Requires Site instance with pages and config populated

Attributes

Name Type Description
site

Site instance containing menu configuration and pages

_menu_cache_key

Cache key for incremental menu building

Relationships
  • Uses: MenuBuilder for menu construction - Uses: MenuItem for menu item representation - Used by: BuildOrchestrator for menu building phase - Updates: site.menu with built menus Thread Safety: Not thread-safe. Should be used from single thread during build.

Methods 2

build
Build all menus from config and page frontmatter. With incremental building: -…
2 bool
def build(self, changed_pages: set[Path] | None = None, config_changed: bool = False) -> bool

Build all menus from config and page frontmatter.

With incremental building:

  • If config unchanged AND no pages with menu frontmatter changed
  • Skip rebuild and reuse cached menus
Parameters 2
changed_pages set[Path] | None

Set of paths for pages that changed (for incremental builds)

config_changed bool

Whether config file changed (forces rebuild)

Returns

bool

True if menus were rebuilt, False if cached menus reused

Called during site.build() after content discovery.

mark_active
Mark active menu items for the current page being rendered. Called during rende…
1 None
def mark_active(self, current_page: Page) -> None

Mark active menu items for the current page being rendered. Called during rendering for each page.

Parameters 1
current_page Page

Page currently being rendered

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

Initialize menu orchestrator.

Parameters 1
site Site

Site instance containing menu configuration

_can_skip_rebuild
Check if menu rebuild can be skipped (incremental optimization). Menus need re…
1 bool
def _can_skip_rebuild(self, changed_pages: set[Path]) -> bool

Check if menu rebuild can be skipped (incremental optimization).

Menus need rebuild only if:

  1. Config changed (menu definitions)
  2. Pages with 'menu' frontmatter changed
Parameters 1
changed_pages set[Path]

Set of changed page paths

Returns

bool

True if rebuild can be skipped (menus unchanged)

_compute_menu_cache_key
Compute cache key for current menu configuration. Key includes: - Menu config …
0 str
def _compute_menu_cache_key(self) -> str

Compute cache key for current menu configuration.

Key includes:

  • Menu config from bengal.toml
  • List of pages with menu frontmatter and their menu data
  • Dev params (repo_url)
  • Dev section names (api, cli) that affect dev menu bundling
Returns

str

SHA256 hash of menu-related data

_build_auto_menu_with_dev_bundling
Build auto-discovered menu with dev assets bundled into dropdown. This is the …
0 list[dict[str, Any]]
def _build_auto_menu_with_dev_bundling(self) -> list[dict[str, Any]]

Build auto-discovered menu with dev assets bundled into dropdown.

This is the single source of truth for auto menu generation. Integrates section discovery, dev bundling, and menu structure in one place.

Returns

list[dict[str, Any]]

List of menu item dicts ready for MenuBuilder (with deduplication)

_find_section_by_name
Find a section by its name/slug.
1 Any | None
def _find_section_by_name(self, section_name: str) -> Any | None

Find a section by its name/slug.

Parameters 1
section_name str

Section name to find (e.g., 'api', 'cli')

Returns

Any | None

Section object if found, None otherwise

_build_full
Build all menus from scratch.
0 bool
def _build_full(self) -> bool

Build all menus from scratch.

Returns

bool

True (menus were rebuilt)