Concepts ๐Ÿง #

Inheritance ๐Ÿงฌ#

The menu in effect is the nearest ancestor with a configured menu.

  • An unset field (None) means โ€œinheritโ€; the search continues upward.

  • An explicitly saved empty menu means โ€œopt outโ€; the search stops and the viewlet renders nothing.

  • If no ancestor configures a menu, the viewlet renders nothing.

  • There is no fallback to Ploneโ€™s default main navigation.

This lets the site root define a site-wide menu, while a section can override it or opt out.

Rendering ๐ŸŽจ#

A viewlet subclasses Ploneโ€™s GlobalSectionsViewlet and replaces the plone.global_sections viewlet. It preserves the Barceloneta markup contract:

  • ul#portal-globalnav with navbar-nav;

  • li.nav-item and a.nav-link;

  • has_subtree, dropdown, and the mobile opener input/label pair;

  • pat-navigationmarker for the active/in-path behavior.

Storage ๐Ÿ’พ#

The menu is a native dict in a plone.schema.JSONField. Internal targets are also registered with plone.app.linkintegrity when the menu is saved, so deleting a referenced target shows Ploneโ€™s standard warning. External URLs and links to the Plone Site root itself are not tracked. Linkintegrity relations are created on the next save; existing menus are not backfilled.