From ada7e798ebfc54a3a09492543f5bbb7c525463a9 Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Tue, 9 Sep 2025 21:41:57 -0400 Subject: [PATCH 1/2] document latest guidelines and behaviors for pages and layouts --- src/pages/docs/pages/layouts.md | 71 ++++++++++++++---------- src/pages/docs/pages/routing.md | 2 + src/pages/docs/pages/server-rendering.md | 20 ++++--- 3 files changed, 54 insertions(+), 39 deletions(-) diff --git a/src/pages/docs/pages/layouts.md b/src/pages/docs/pages/layouts.md index 55851050..7742f5aa 100644 --- a/src/pages/docs/pages/layouts.md +++ b/src/pages/docs/pages/layouts.md @@ -31,15 +31,17 @@ src/ > **Note:** You can use either relative (_../_) or absolute (_/_) paths in your layouts since using _../_ will allow for IDE autocomplete on your filesystem, but is marginally slower than using _/_. -## Pages +## Page Layout -Pages in your project will generally want a layout so you can control the output of the HTML and include all your own custom components and styles to wrap the content. By default all pages will default to looking for a _page.html_ in the _layouts/_ directory. A placeholder of `` can be used to position where the processed content from the incoming page will go. +Pages in your project will generally want a layout so you can control the output of the HTML and include all your own custom components and styles to wrap your content; think of a shared layout for all blog posts, which might be distinct from your home or docs pages. By default all pages will default to looking for a _page.html_ in the _layouts/_ directory. A placeholder of `` can be used to position where the content from the incoming page will go. + +> Dynamic layouts are [also supported](/docs/pages/server-rendering/#layouts). Below is an example of a _page.html_ layout: - + ```html @@ -81,15 +83,15 @@ You can create more layouts and use them for pages with the following steps: -## App +## App Layout -To customize the outer most wrapping HTML of your layouts, create an _app.html_ file. Like a page layout, this will just be another HTML document and a `` placeholder that can be used to position where the content from the processed page layout will appear. +To customize the outer most wrapping HTML of _all_ your layouts, create an _app.html_ file. This is most useful for global page elements like headers, navigation, and footers. Like a page layout, this will just be another HTML document (or JS / TS file) with a `` placeholder that can be used to position where the content from the processed page layout will appear. -As with Page layouts, App layouts are just HTML: +Below is an HTML example of an app layout: - + ```html @@ -114,34 +116,43 @@ As with Page layouts, App layouts are just HTML: -> When an app layout is present, Greenwood will merge the `` and `` tags for both app and page layouts into one HTML document structure for you. +> In general, you will want to start with an app layout, then create page specific layouts as needed for more specific custom layout needs. ## Server Rendering Server rendered layouts can also be authored using Web Components: -```js -// src/layouts/app.js -export default class AppLayout extends HTMLElement { - async connectedCallback() { - const year = new Date().getFullYear(); - - this.innerHTML = ` - - - - My App - - - -

My App

- -
© ${year}
- - - `; + + + + + ```js + export default class PageLayout extends HTMLElement { + constructor({ compilation, page }) { + super(); + this.route = page.route; + this.numPages = compilation.graph.length; + } + + async connectedCallback() { + this.innerHTML = ` + + + My App + + +

Page Layout for ${this.route}

+ Number of pages ${this.numPages} + + + + `; + } } -} -``` + ``` + +
+ + > ⚠ This layout component will _only run once at build time_. Dynamic "runtime" layouts are [planned](https://github.com/ProjectEvergreen/greenwood/issues/1248). diff --git a/src/pages/docs/pages/routing.md b/src/pages/docs/pages/routing.md index 88fe999a..a0fd461f 100644 --- a/src/pages/docs/pages/routing.md +++ b/src/pages/docs/pages/routing.md @@ -84,6 +84,8 @@ src/ index.html ``` +> [SPA based projects](/docs/pages/routing/#spa) do **not** support layouts or (active) frontmatter. + ## Not Found As is a [common convention with most hosting providers](https://docs.netlify.com/routing/redirects/redirect-options/#custom-404-page-handling) and web servers, you can create a `404` page in your _pages/_ directory which will be used as the default **Not Found** page for your site. diff --git a/src/pages/docs/pages/server-rendering.md b/src/pages/docs/pages/server-rendering.md index d24820e8..8eab6e6c 100644 --- a/src/pages/docs/pages/server-rendering.md +++ b/src/pages/docs/pages/server-rendering.md @@ -67,7 +67,7 @@ This is the recommended pattern for SSR in Greenwood: - + ```js import "../components/card/card.js"; // @@ -106,6 +106,8 @@ A couple of notes: - WSCs run only on the server, thus you have full access to any APIs of the runtime, with the ability to perform one time `async` operations for [data loading](/docs/pages/server-rendering/#request-data) in `connectedCallback`. - Keep in mind that for these "page" components, you will likely want to _avoid_ rendering into a shadow root, as then your content and styles will be encapsulated. +> You can also author [dynamic layouts](/docs/pages/layouts/#server-rendering) in this way as well! + ### Body To return just the body of the page, you can use the `getBody` API. You will get access to the [compilation](/docs/reference/appendix/#compilation), page specific data, and the incoming request. @@ -114,7 +116,7 @@ In this example, we return a list of users from an API as HTML: - + ```js export async function getBody(/* compilation, page, request */) { @@ -124,11 +126,11 @@ In this example, we return a list of users from an API as HTML: const { name, imageUrl } = user; return ` - - ${name} - - - `; + + ${name} + + + `; }); return ` @@ -159,7 +161,7 @@ You can pull in data from Greenwood's [compilation](/docs/reference/appendix/#co - + ```js export async function getLayout(compilation, route) { @@ -200,7 +202,7 @@ Any Greenwood [supported frontmatter](/docs/resources/markdown/#frontmatter) can - + ```js export async function getFrontmatter(compilation, route) { From 34f497066abd04a66f5c523503d77ec13f4816f1 Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Sun, 14 Sep 2025 09:57:11 -0400 Subject: [PATCH 2/2] clarifications --- src/pages/docs/pages/layouts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/docs/pages/layouts.md b/src/pages/docs/pages/layouts.md index 7742f5aa..acb54c80 100644 --- a/src/pages/docs/pages/layouts.md +++ b/src/pages/docs/pages/layouts.md @@ -85,7 +85,7 @@ You can create more layouts and use them for pages with the following steps: ## App Layout -To customize the outer most wrapping HTML of _all_ your layouts, create an _app.html_ file. This is most useful for global page elements like headers, navigation, and footers. Like a page layout, this will just be another HTML document (or JS / TS file) with a `` placeholder that can be used to position where the content from the processed page layout will appear. +To customize the outer most wrapping HTML of _all_ your pages, create an _app.html_ file. This is most useful for global page elements like headers, navigation, and footers. Like a page layout, this will just be another HTML document (or JS / TS file) with a `` placeholder that can be used to position where the content from the processed page layout will appear. Below is an HTML example of an app layout: