SEO and discovery
Apply Core's search, metadata, structured-data, and discovery contracts.
- Owner
- Foundry Core
- Source
core/docs/SEO.md- Ref
782f49b97d862e640e87c870178e600f9ce5cf83- Policy
- release-bound
Component pins for v0.2.6
| Component | Role | Version |
|---|---|---|
| core | runtime | v0.1.24 |
| theme-shield | theme | v0.1.15 |
| starter | reference | v0.1.3 |
| docs | reference | v0.1.4 |
| distribution | tooling | v0.3.4 |
| restricted-component-1 | consumer-reference | v0.1.22 |
| restricted-component-2 | consumer-reference | v1.1.21 |
Foundry now emits shared SEO from partial "foundry/seo/render.html" ..
Downstream themes should call that partial from baseof.html, not from a site overrideable head-end.html file. This keeps canonical tags, alternates, metadata, and schema from drifting between core, theme, and project repos.
What core renders
- Canonical URL, including paginator-aware URLs after list page one
- Meta description
- Robots and googlebot tags when
robots,noindex, orprivateare set - Open Graph and Twitter metadata
- Source-visible generator markers:
LikeStyle Foundry Core <version> (Hugo <version>)- a dedicated
foundry-core-versionmeta value
hreflangalternate links for multilingual pages- JSON-LD for:
WebSiteplus the home route’sWebPageWebPageorCollectionPageMedicalWebPagefor medical treatment/article pages when the site declares a medical local businessBreadcrumbListBlogPostingServicePersonFAQPage- optional
Organization/LocalBusiness
Theme responsibility
Theme head-end.html files should only add theme or brand assets such as:
- dark-mode anti-flash scripts
- theme CSS bundles
- favicons
- theme color
- project-specific preconnects
Shared SEO should not be reimplemented there.
Foundry attribution
Core owns a required bottom-of-page attribution hook at
layouts/_partials/hooks/body-end/foundry-attribution.html. It renders the
linked wording Built with LikeStyle Foundry Core, pointing to
https://likestyle.com/foundry/. The link uses a self-contained dark badge with white
text so site and theme footer colors cannot make the wording unreadable.
Sites may opt into the public
Foundry Attribution Control Runtime. The browser can then
apply an exact show or hide decision from Foundry Control. The badge remains
visible on missing configuration, service failure, timeout, or an invalid
response; source-visible generator and version markers are never removed.
The SEO partial emits generator metadata, a dedicated Core-version meta tag,
and an HTML comment naming LikeStyle Foundry Core. The attribution wrapper also
includes data-foundry-core-version, so the framework and build version remain
identifiable in generated source.
Core resolves the version from the pinned
github.com/jerrybroughton/likestyle-foundry-core entry exposed by
hugo.Deps. Sites may set params.foundry.core_version to an explicit value
such as dev+59a7b8f when a local replacement or release materializer needs to
override the dependency version. If neither source provides a version, Core
reports dev instead of claiming a release.
Custom shells that do not automatically collect Hugo Blox body-end hooks must
call partial "hooks/body-end/foundry-attribution.html" . before </body>.
Site config fields
Supported site params:
params:
description: "Site-wide fallback description"
og_image: "/images/og-default.jpg"
social:
instagram: "https://instagram.com/example"
facebook: "https://facebook.com/example"
contact:
phone: "(555) 555-5555"
email: "info@example.com"
hours: "By appointment only"
seo:
author: "Site Author"
reviewed_by_default: "author-key"
twitter_handle: "@example"
og_image_default: "/images/og-default.jpg"
organization:
name: "Example Company"
logo: "/images/logo.png"
same_as:
- "https://linkedin.com/company/example"
local_business:
types:
- "LocalBusiness"
name: "Example Company"
price_range: "$$"
address:
street_address: "123 Main St"
city: "Anywhere"
region: "CA"
postal_code: "90210"
country: "US"
Supported page params:
canonical: "https://example.com/custom-url/"
robots: "noindex,nofollow"
noindex: true
author: "author-key"
author_name: "Author Name"
author_role: "Medical Reviewer"
reviewed_by: "reviewer-key"
reviewed_on: 2026-03-04
seo:
schema_title: "Visible page heading"
image: "/images/page-social-card.jpg"
image_alt: "Concise description of the social image"
person:
key: "author-key"
service:
type: "Service"
service_type: "Primary service label"
seo.schema_title is the semantic title used by WebPage, article, and
Service JSON-LD. Set it when the editorial <h1> intentionally differs from
the SEO-oriented front matter title; it should exactly match the visible
heading. Open Graph and Twitter titles continue to use the page title.
For a custom paginated list, initialize the exact paginator before calling the
SEO partial and store its URL in the page scratch as
foundry_seo_canonical. Foundry uses that value for canonical, Open Graph, and
schema URLs. This avoids Core instantiating a second paginator with a different
collection or page size.
Foundry emits article schema only for leaf content pages. Section, taxonomy,
archive, and other list pages keep their WebPage/CollectionPage schema even
when they live under an article section.
seo.image is the canonical page-level SEO/social image field advertised by
the page manifest. og_image remains a compatibility alias. The resolved
precedence is seo.image, og_image, the shared discovery image, the
site-level params.og_image, and then params.seo.og_image_default.
reviewed_on is the canonical editorial review-date field used by the shared
article shell and JSON-LD resolver. It emits lastReviewed on the page schema,
and the date must remain visible in rendered content. reviewed_at, reviewed,
and last_reviewed remain compatibility aliases.
The discovery model infers search.kind: service for the services section
and search.kind: treatment for the treatments section. Explicit
search.kind remains preferred when a service lives elsewhere. Both service
and treatment kinds can emit Service JSON-LD; seo.service can supply the
visible service type and other supported service facts.
Robots
Set enableRobotsTXT: true in each downstream site config. Shared and site-owned theme repos can expose layouts/robots.txt wrappers that call the shared Foundry robots partial.
Projects with their own custom base layout and no theme layouts/robots.txt wrapper should add a local layouts/robots.txt file that calls:
{{ partial "foundry/seo/robots.txt" . }}
The wildcard contract remains backward compatible:
params:
seo:
robots_txt:
disallow:
- /private/
allow:
- /private/public-guide/
extra: |-
Crawl-delay: 2
Foundry also supports opt-in purpose-aware crawler profiles and per-crawler overrides:
params:
seo:
robots_txt:
profile: search-visible-no-training
crawlers:
gptbot: inherit
perplexitybot: disallow
Crawler override keys come from
data/foundry/crawler-policy-registry.json; valid values are inherit,
allow, and disallow. An allow rule preserves the wildcard path rules for
that crawler rather than bypassing site-wide private paths. A disallow rule
blocks / for that crawler. Unknown profiles safely fall back to inherit,
and unknown crawler keys produce no group.
See AI Discovery for profile intent, crawler-purpose boundaries, user-fetch limitations, and the rendered discoverability validator.