From ad9bbcdde7b96dbcefcddf0bbae13765e37a7a6e Mon Sep 17 00:00:00 2001 From: Bret Comnes Date: Sat, 18 Apr 2026 11:32:33 -0700 Subject: [PATCH 1/4] document layout composition pitfalls for scripts, styles, and vars --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index 008f8fb..3d28a02 100644 --- a/README.md +++ b/README.md @@ -634,6 +634,34 @@ Now the `blog.layout.js` becomes a nested layout of `root.layout.js`. No magic, Alternatively, you could compose your layouts from re-usable template functions and strings. If you find your layouts nesting more than one or two levels, perhaps composition would be a better strategy. +#### Layout composition pitfalls + +**Scripts and styles must be forwarded explicitly.** If you call a base layout without passing `scripts` and `styles`, those arrays are lost and the rendered page will have no CSS or JS bundles. No error is reported — the page simply renders without styles: + +```js +// wrong: scripts and styles are dropped +return rootLayout({ children: wrappedContent, vars }) + +// correct: forward them along +return rootLayout({ children: wrappedContent, vars, scripts, styles }) +``` + +**Vars can be modified before forwarding.** The rest-spread pattern shown above forwards vars unchanged, but you can extend the object before passing it to the base layout. This is useful for setting layout-specific flags that the root layout reads: + +```js +const layoutVars = { ...vars, showSidebar: true, pageType: 'article' } +return rootLayout({ children: wrappedContent, vars: layoutVars, scripts, styles }) +``` + +**Forward `page`, `pages`, and `workers` when the base layout uses them.** If your root layout accesses `page.path` for canonical URLs, iterates `pages` for navigation, or uses `workers`, those params must also be forwarded: + +```js +export default function articleLayout ({ children, vars, scripts, styles, page, pages, workers }) { + const wrappedContent = wrapContent(children, vars) + return rootLayout({ children: wrappedContent, vars, scripts, styles, page, pages, workers }) +} +``` + ### Layout styles You can create a `${layout-name}.layout.css` next to any layout file. From 1ed341cb148abbec66687e0fa69fb859af2026d3 Mon Sep 17 00:00:00 2001 From: Bret Comnes Date: Sat, 18 Apr 2026 12:03:39 -0700 Subject: [PATCH 2/4] Fix undefined identifiers in layout composition pitfalls examples Replace rootLayout/wrappedContent/wrapContent with identifiers that are actually defined in the surrounding context (defaultRootLayout and children), making the snippets copy-pasteable and consistent with the nested layout example above. --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3d28a02..8085fde 100644 --- a/README.md +++ b/README.md @@ -640,25 +640,24 @@ If you find your layouts nesting more than one or two levels, perhaps compositio ```js // wrong: scripts and styles are dropped -return rootLayout({ children: wrappedContent, vars }) +return defaultRootLayout({ children, vars }) // correct: forward them along -return rootLayout({ children: wrappedContent, vars, scripts, styles }) +return defaultRootLayout({ children, vars, scripts, styles }) ``` **Vars can be modified before forwarding.** The rest-spread pattern shown above forwards vars unchanged, but you can extend the object before passing it to the base layout. This is useful for setting layout-specific flags that the root layout reads: ```js const layoutVars = { ...vars, showSidebar: true, pageType: 'article' } -return rootLayout({ children: wrappedContent, vars: layoutVars, scripts, styles }) +return defaultRootLayout({ children, vars: layoutVars, scripts, styles }) ``` **Forward `page`, `pages`, and `workers` when the base layout uses them.** If your root layout accesses `page.path` for canonical URLs, iterates `pages` for navigation, or uses `workers`, those params must also be forwarded: ```js export default function articleLayout ({ children, vars, scripts, styles, page, pages, workers }) { - const wrappedContent = wrapContent(children, vars) - return rootLayout({ children: wrappedContent, vars, scripts, styles, page, pages, workers }) + return defaultRootLayout({ children, vars, scripts, styles, page, pages, workers }) } ``` From 71bcbe0f84926fc4c6af3d2165afffe83defe0f4 Mon Sep 17 00:00:00 2001 From: Bret Comnes Date: Sat, 18 Apr 2026 12:53:32 -0700 Subject: [PATCH 3/4] Mention missing JS bundles alongside CSS in layout forwarding warning --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8085fde..9f40780 100644 --- a/README.md +++ b/README.md @@ -636,7 +636,7 @@ If you find your layouts nesting more than one or two levels, perhaps compositio #### Layout composition pitfalls -**Scripts and styles must be forwarded explicitly.** If you call a base layout without passing `scripts` and `styles`, those arrays are lost and the rendered page will have no CSS or JS bundles. No error is reported — the page simply renders without styles: +**Scripts and styles must be forwarded explicitly.** If you call a base layout without passing `scripts` and `styles`, those arrays are lost and the rendered page will have no CSS or JS bundles. No error is reported -- the page simply renders unstyled and without client-side JS: ```js // wrong: scripts and styles are dropped From fa3be9997b6c7881cfa94f573a21941a0d2aaf33 Mon Sep 17 00:00:00 2001 From: Bret Comnes Date: Sat, 18 Apr 2026 19:49:58 -0700 Subject: [PATCH 4/4] Rename layoutVars to extendedVars in vars-forwarding snippet to avoid name collision Co-Authored-By: Claude Sonnet 4.6 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9f40780..58f71ff 100644 --- a/README.md +++ b/README.md @@ -649,8 +649,8 @@ return defaultRootLayout({ children, vars, scripts, styles }) **Vars can be modified before forwarding.** The rest-spread pattern shown above forwards vars unchanged, but you can extend the object before passing it to the base layout. This is useful for setting layout-specific flags that the root layout reads: ```js -const layoutVars = { ...vars, showSidebar: true, pageType: 'article' } -return defaultRootLayout({ children, vars: layoutVars, scripts, styles }) +const extendedVars = { ...vars, showSidebar: true, pageType: 'article' } +return defaultRootLayout({ children, vars: extendedVars, scripts, styles }) ``` **Forward `page`, `pages`, and `workers` when the base layout uses them.** If your root layout accesses `page.path` for canonical URLs, iterates `pages` for navigation, or uses `workers`, those params must also be forwarded: