v0.7.1
·
6 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
[0.7.1] - 2026-05-21
Added
- Sticky-footer pattern in
app.vue—min-h-screen flex flex-colwrapper withflex-1on the layout slot keeps the footer pinned to the viewport bottom while<NuxtPage>is empty or pending. Fixes the "footer rendered above content" symptom on SPA routes (ssr: false) and pages with heavy async setup — e.g. astronera's/viirs/maharashtramap page routeRules.appLayoutruntime bridge — new global middleware (app/middleware/app-layout.global.ts) readsgetRouteRules({ path }).appLayoutand callssetPageLayout(). Nuxt 4 type-augments the field but ships no runtime handler; layouts now actually swap perrouteRulesmapping without each consumer wiring their own middleware- Server-side content endpoints —
/api/_foundry/content/pageand/api/_foundry/content/surroundare the single typed boundary for content lookups. Layouts and the catch-all consume them viauseFetch. Side benefit: ready hook point for future caching, auth, or rate-limiting around content access ContentDoctype — exported fromuseContentPage. Minimal shape (title, description, hero, label, date, image, path, seo) intersected withRecord<string, unknown>for arbitrary frontmattermodules/markdown-rewrite.tsshipped in tarball — was missing fromlayer/package.jsonfiles:array. Consumers using the layer's Vercel edge-redirect module now have the file present- Playground rendering test matrix — 17 E2E tests in
playground/test/e2e/rendering.e2e.spec.tscover default SSR, SPA-only routes, app-page vs content precedence, dynamic params,<ClientOnly>islands,routeRules(headers/redirect/appLayout), structural DOM order, and content/app-page layout equivalence. Run withpnpm --filter playground test:e2e - Rendering-modes documentation —
examples/foundry/content/docs/5.advanced/4.rendering-modes.mddocuments URL → page resolution order, layout selection rules, every rendering knob, real-world consumer patterns, and debugging tips - Local registry workflow (verdaccio) —
.verdaccio/config.yaml+layer/scripts/publish-local.sh+ rootverdaccio:start/layer:publish:localscripts. Enables testing local layer changes in external consumer repos (astronera, incubrain). Documented inAGENTS.md
Changed
- Layouts decoupled from content existence —
default,landing,articleno longer callthrow createError(404)when content is missing. App pages that opt into a Foundry layout (definePageMeta({ layout: 'article' })) no longer 404 unless they explicitly setlayout: false. Both incubrain and astronera previously worked around this by settinglayout: falseon every hand-built app page - Catch-all owns the 404 —
layer/app/pages/[...slug].vuedoesgetPage()+setContext()+ the 404 throw. Layouts fetch their own copy via the sameuseFetchkey (deduped) so SSR has page data at layout-render time. Previously each layout fetched independently and threw separately useContentPage.getPage()usesuseFetch— talks to/api/_foundry/content/pageinstead of calling the auto-importedqueryCollectiondirectly. Sidesteps a dev-mode crash (event.req.headers.entries is not a function) under our pinned h3@1 +@nuxt/content@3.13as anycasts replaced with typed Content shapes — 15 usages acrossuseContentPage, layouts, the catch-all, the appLayout middleware, and the server endpoints now useContentDoc,keyof PageCollections,ContentNavigationItem, and Nuxt'sLayoutKeyparameter inference
Fixed
UPageHero0.10 CLS on content-driven pages — layouts used to read from a shared context that the catch-all populated inside its slot, AFTER the layout's render committed. SSR emitted no hero (v-iffalse); client hydrated with hero (v-iftrue); body shifted 448px. Both layouts and the catch-all now fetch via the same dedupe key, so SSR and CSR render identical HTML. Measured drop from CLS 0.102 → 0.0004 on/render-landing, 0.076 → 0.0003 on/render-default- Footer rendering above content on SPA / async-pending routes — see Added: sticky-footer pattern in
app.vue routeRules.appLayoutwas a silent no-op — see Added: runtime bridge middleware- Root
/URL 404 in the catch-all —useContentPage.getPage()stripped the trailing slash from/into an empty string, causingqueryCollection.path('').first()to return null. Now preserves the root slash so the catch-all correctly servescontent/pages/index.md
Known issues
pnpm verifytypecheck failures unrelated to this release — 10 pre-existing TypeScript errors block the verify gate (h3 v1/v2 type drift inmodules/rss/server,server/mcp/tools/list-pages.ts,server/middleware/docs-redirect.ts;event.nodepossibly-undefined access inapp/utils/prerender.ts; missingtocprop type inmodules/docs/runtime/layouts/docs.vue). 0.7.0 shipped past these as well. Tracked inbd:product-validator-o3q; will be addressed alongside the deferred Nitro v3 / h3@2 / unhead@3 cascade. 0.7.1 was released by bypassing the verify hook (release-it --no-before-initor equivalent)