Historical documentation Bundle v1.1.2 Core v1.1.2 Distribution v0.3.19 Released 2026-08-31T00:00:00Z
Release history
Site shell contract Configure the shared Foundry header, navigation, footer, and shell behavior. v1.1.2 core current site-builderscore-developers

core · Current reference

Site shell contract

Configure the shared Foundry header, navigation, footer, and shell behavior.

Applies to v1.1.2

Component pins for v1.1.2
ComponentRoleVersion
coreruntimev1.1.2
theme-shieldthemev0.1.15
docsreferencev0.1.6
distributiontoolingv0.3.19

Phase: 08-shell-contract-governance Status: Stable (v1)

The Foundry shell contract defines how downstream themes and sites configure site chrome — header, navigation, footer, utility surfaces, and page-level exceptions — without copying shell partials locally.


Why a Shell Contract?

Without a contract, every site ends up with:

  • Local copies of layouts/partials/header/, layouts/partials/footer/, and layouts/_default/baseof.html
  • Bespoke template conditions scattered across dozens of partials
  • No machine-readable ownership model → AI editors can’t safely touch shell code
  • Governance by tribal knowledge rather than validated structure

The shell contract moves this behaviour into typed, schema-backed Core ownership that downstream repos configure rather than copy.


Artifacts

FilePurpose
schemas/foundry/shell-manifest.schema.jsonTyped contract for all shell surfaces
schemas/foundry/page-shell.schema.jsonPage-level chrome exception fields
layouts/partials/helpers/shell-model.htmlNormalizes the optional site manifest with backward-compatible defaults
layouts/partials/helpers/page-shell-params.htmlHugo partial that normalizes page front matter into the contract
layouts/partials/header/site-header.htmlShared header consuming brand, nav, utilities, search, preferences, and CTA fields
layouts/partials/shell/contact-bar.htmlOptional contact/action composition called once by the site base layout
foundry validate shellGo-native Core contract validation
foundry validate shell-overridesGo-native audit for unallowlisted consumer shell shadows

Shell Surfaces (shell-manifest)

The shell manifest covers these surfaces:

SurfaceRequiredDescription
brandSite name, logo assets, home URL
navPrimary navigation (menu-driven or explicit links)
utility_navSecondary nav (language, preferences, auth)
searchSearch entry point
preferencesLanguage/theme/locale toggles
announcementTop-of-page announcement banner
primary_ctaHeader call-to-action button
contact_barOptional group of one to three consumer-configured links
footerFooter columns, legal nav, contact, social

The shared header consumes the normalized model directly. Without a manifest, it preserves the established site-title, home-link, and main menu behavior. Themes still own density, typography, color, and responsive presentation.

The contact bar is deliberately not injected by a universal base layout. A site that wants it calls the portable composition once near body-end:

{{ partial "foundry/shell/contact-bar.html" (dict "page" .) }}

All link entries in the manifest use a typed kind field:

KindMeaning
internalSite-local link (Hugo relURL)
externalOff-site link (opens with explicit rel)
anchorOn-page anchor (#section-id)
menu-drivenResolved from Hugo menus at build time
route-ownerPoints to the canonical owner of a content section

Page-Level Chrome Exceptions (page-shell)

Pages declare shell behaviour through front matter fields that are normalized by helpers/page-shell-params.html:

---
title: Landing Page
header_mode: transparent      # overlays first content block
footer_mode: minimal          # legal links only
hide_site_chrome: false       # true = full chrome suppression
route_owner: services         # canonical section key
utility_surface: cta-only     # show only primary CTA in header
show_breadcrumbs: true        # render visible breadcrumbs when shell supports it
noindex: false
suppress_announcement: false
suppress_contact_bar: false
shell_compat_mode: false       # set true only during phased migration
---

Field Reference

FieldTypeDefaultValues
hide_site_chromeboolfalseSuppresses header + footer
header_modestring"default"default, transparent, minimal, hidden
footer_modestring"default"default, minimal, hidden
announcement_keystringMaps to data/announcements/{key}.yaml
suppress_announcementboolfalseHides site-level announcement on this page
suppress_contact_barboolfalseHides the optional contact bar on this page
route_ownerstringContent section key (e.g. services, journal)
utility_surfacestring"default"default, none, cta-only, search-only
show_breadcrumbsboolfalseOpts the page into visible breadcrumbs
breadcrumb_home_labelstringsite home titleOptional home crumb label
breadcrumb_labelstring"Breadcrumb"Accessible nav label
breadcrumb_include_currentbooltrueIncludes current page as final crumb
noindexboolfalseAdds <meta name="robots" content="noindex">
shell_compat_modeboolfalseEnables legacy param resolution during migration

Using the Helper Partial

In your base layout or shell partial, resolve page-shell params once at the top:

{{/* layouts/_default/baseof.html */}}
{{ $shell := partial "foundry/helpers/page-shell-params.html" . }}

{{ if not $shell.hide_site_chrome }}
  {{ partial "header/site-header.html" (dict "page" . "shell" $shell) }}
{{ end }}

{{ block "main" . }}{{ end }}

{{ if not $shell.hide_site_chrome }}
  {{ partial "footer/site-footer.html" (dict "page" . "shell" $shell) }}
  {{ partial "foundry/shell/contact-bar.html" (dict "page" .) }}
{{ end }}

The helper handles:

  • Reading typed contract fields from .Params
  • Applying defaults for missing fields
  • Legacy compat: falls back to older param names during migration

Visible Breadcrumbs

Foundry already emits breadcrumb structured data through SEO schema. For visible page breadcrumbs, call the shared partial from the shell where the site wants breadcrumbs to appear:

{{ partial "foundry/navigation/breadcrumbs.html" (dict "page" . "shell" $shell) }}

The partial renders only when show_breadcrumbs: true and when the current page has more than one crumb. It uses Hugo ancestors, respects breadcrumb_home_label, and marks the current page with aria-current="page".

Foundry Core owns the portable interaction behavior for menus. Themes and sites continue to own menu content, density, visual styling, and information architecture.

The Core header loads assets/js/foundry-navigation.js through foundry/framework/foundry-navigation.html. The controller provides:

  • synchronized Menu / Close labels and aria-expanded state
  • mobile scroll locking, contained focus, scroll reset, and outside dismissal
  • submenu-first Escape handling with focus restoration
  • viewport-change cleanup so desktop and mobile state cannot leak across modes
  • click activation for touch/coarse pointers and optional hover activation for fine pointers
  • pointer-safe submenu state and automatic closure when a navigation link or another header surface is selected
  • an is-scrolled header state for theme-owned transparent/sticky treatments

The default Core header switches at 48rem. A custom header must declare the same mobile maximum used by its CSS:

<header
  data-foundry-header
  data-foundry-nav-breakpoint="899px"
  data-foundry-nav-hover="true"
  data-foundry-nav-scroll-lock="true"
  data-foundry-nav-contain-focus="true">
  <button data-foundry-nav-toggle>...</button>
  <nav data-foundry-nav>...</nav>
</header>

Submenu buttons use data-foundry-submenu-toggle; their owning list item uses foundry-nav-item--has-submenu; and the panel uses data-foundry-submenu. Core applies is-menu-open, is-mobile-navigation, is-submenu-open, and foundry-nav-open as runtime state hooks.

Custom shells that shadow the Core header must load the shared controller after their navigation markup:

{{ partial "foundry/framework/foundry-navigation.html" . }}

Sites should not copy the controller into a local inline script. Brand-specific mega-menu columns, mobile content priorities, icons, and CTA copy remain in the theme or site layer.

Shared Layer Tokens

Core exposes a stacking contract so a downstream sticky header cannot cover a search overlay or modal:

TokenDefaultIntended surface
--foundry-layer-sticky30Sticky in-page controls
--foundry-layer-nav-backdrop35Mobile navigation backdrop
--foundry-layer-header40Sticky site header
--foundry-layer-popover60Submenus and preference popovers
--foundry-layer-overlay100Full-screen search and overlays
--foundry-layer-modal120Modal dialogs requiring top priority

Themes may raise the scale, but must preserve that ordering. Override the tokens instead of patching individual Core selectors with unrelated z-index values.


Ownership Model

LayerOwns
Foundry CoreShell schemas, typed surface definitions, validators, helper partial
ThemeShell variant implementations, menu density, responsive visual treatment, and brand presentation
SiteShell configuration, menu keys/grouping, CTA copy, contact info, and route priorities

Sites configure shell behaviour through the contract. They do not copy shell partials unless:

  1. The needed behaviour cannot be expressed through the contract
  2. The shadow is documented in .planning/shadow-copy-review.md with a reason and migration phase
  3. The shadow passes the override validator with an explicit allowlist entry

Validation

foundry validate shell --root /path/to/likestyle-foundry-core --json
foundry validate shell-overrides --site /path/to/downstream-repo --json
foundry validate shell-overrides --site /path/to/downstream-repo \
  --allowlist /path/to/downstream-repo/.planning/shell-shadow-allowlist.json \
  --json

Core’s Go validators are the only supported shell-contract maintenance path. See CLI Reference and Tooling Policy.


Shell Shadow Migration Path

If a downstream repo has temporary shell shadows (common during initial adoption):

  1. Document each shadow in .planning/shadow-copy-review.md under “Shell Shadows” with a reason and target phase.
  2. Create .planning/shell-shadow-allowlist.json listing the shadow paths.
  3. Run foundry validate shell-overrides --allowlist <file> in CI to catch any new unreviewed shadows.
  4. Retire the shadow in the designated phase by adopting the Core contract field or theme variant.
  5. Remove the allowlist entry and confirm the validator exits 0.

Compatibility Mode

During migration, set shell_compat_mode: true in page front matter to enable legacy param resolution alongside the new contract. This allows incremental per-page migration without a big-bang rewrite. Remove shell_compat_mode once all pages in a section are migrated.


What This Phase Does Not Do

  • Move high-consideration service proof site route labels, CTA copy, or contact info into Core defaults
  • Implement final header/footer rendering for any specific theme
  • Expand into runtime personalization or non-shell product work
  • Promote any shell primitive to “shield” status before a second consumer proves genericity

These are targets for Phase 09 (Theme Capability & Shared Shell Rendering) and Phase 10 (high-consideration service proof site Pilot & Exception Retirement).

Static Pagefind search

Search Foundry documentation

Type at least two characters
Search the full documentation system

Results stay inside this build profile and can be filtered by version, component, audience, and lifecycle.

By LikeStyle
Site details
Site release
Foundry Documentation 1.3.9
Foundry bundle
v1.1.11
Foundry Core
v1.1.11
Credit
Powered by Foundry, a LikeStyle product.