Files
admin/docs/core/web-manager/web.md
T

4.0 KiB

Web Manager — Public Site (Next.js)

How the public site renders what Web Manager publishes. Source: apps/web/web-runtime/, apps/web/app/.

Structure

app/[locale]/[[...path]]/page.tsx   localized catch-all
app/[locale]/preview/page.tsx       token-gated draft rendering, noindex, force-dynamic
app/api/revalidate/route.ts         secret-guarded tag purge
app/sitemap.ts, app/robots.ts       generated from the public API
web-runtime/api/                    HTTP client, render-data resolution, cache tags
web-runtime/data/                   transport normalization
web-runtime/blocks/                 block renderers + registry
web-runtime/layouts/                page layouts and hero
web-runtime/chrome/                 header and footer
web-runtime/components/             link, rich text and media primitives
web-runtime/lib/                    metadata, site URL, sitemap, structured data
web-runtime/types.ts                normalized public contract
web-runtime/renderer.tsx            header + layout + footer

Locales come from site.config.ts (en, uk, de, default en); with more than one locale next-intl always prefixes the URL.

Everything degrades rather than fails. An unknown page_type falls back to the standard layout; an unknown block type renders a dev-only "renderer missing" banner and nothing at all in production; the normalizer degrades malformed payloads instead of throwing. Publishing a block type the web app does not know yet can therefore never take the site down.

Hero

Hero impact is an intensity choice, not a block type:

Impact Use for Rendering
none pages that start with content hero omitted
low legal, utility, index pages compact padding, smallest title scale
middle default marketing and content medium padding, balanced scale
high campaigns, launches, conversion near-viewport height, largest scale, radial accent wash

Media beside the hero switches it to a two-column grid at every impact. A page with no hero object falls back to a page-type eyebrow plus the title.

SEO

generateMetadata delegates to pageMetadata (web-runtime/lib/page-metadata.ts), a pure function of the resolved render data:

  • title / description — the SEO fields, falling back to the page title; an empty description is omitted rather than sent blank.
  • canonical — the page's own locale-prefixed path.
  • hreflang — one alternate per locale in languageAlternatives, plus x-default pointing at the default locale, or at this page when the default locale has no version. Omitted for a page with no translations.
  • Open Graph / Twitter — the hero image becomes the share card with width, height and alt when supplied; summary_large_image with an image, summary without; og:type is article for blog-item, website otherwise.

app/sitemap.ts walks the paginated sitemap endpoint (capped at 50 requests — the protocol's 50,000-URL limit) and hands entries to buildSitemap; pages sharing a groupKey link to each other through alternates.languages, and lastModified uses updatedAt falling back to publishedAt. app/robots.ts allows everything except /*/preview and advertises the sitemap. web-runtime/lib/structured-data.tsx emits BreadcrumbList on every page with a trail and Article on editorial pages — skipped entirely without a publication date rather than shipping markup a crawler discards.

SITE_URL must be set. metadataBase comes from siteUrl(), and Next resolves every relative metadata URL against it. Without it Next falls back to http://localhost:3000: the build succeeds and pages look fine, but canonicals and share cards point at localhost. A production build without it logs an error; a malformed value throws.