TASKS-1823 WebManager module
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# Web Manager — Public Site (Next.js)
|
||||
|
||||
How the public site renders what [Web Manager](./Readme.md) publishes. Source: `apps/web/web-runtime/`, `apps/web/app/`.
|
||||
|
||||
## Structure
|
||||
|
||||
```txt
|
||||
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.
|
||||
Reference in New Issue
Block a user