Layouts and Pages

Greenwood defines two types of layouts to help layout your pages:

  • App Layout: The "app shell" that will wrap all pages. One is provided for you by Greenwood, but you can override it if needed.
  • Page Layouts: A layout for each unique page layout within your site. Common layouts are great for documentation and blog sites, but also great for single pages as well (like a splash layout for the home page).

Greenwood will handle merging the <body> and <head> tag contents when building up pages and layouts.

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 /.

Page Layouts

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. By default all pages will default to looking for a page.html in _layouts/ directory within your workspace.

In order to make a page layout, you just need to write up some HTML that can be enhanced with these special custom elements:

  • Include <content-outlet></content-outlet> to position where the processed content from the page will appear

Below is an example of a simple page.html. You can just copy / paste this to start your own page layouts and by default all your pages will start rendering using this layout.

<!DOCTYPE html>
<html lang="en" prefix="og:http://ogp.me/ns#">

  <body>
    <header>
      <h1>Welcome to my site!</h1>
    </header>

    <content-outlet></content-outlet>

  </body>

</html>

You can create more layouts and use them for pages by doing two things:

  1. Create a new layout, e.g. layouts/blog-post.html

  2. In your frontmatter, specify that layout

    ---
    layout: 'blog-post'
    ---
    
    ## My Blog Post
    Lorum Ipsum
    

See our Front Matter Docs for more information.

App Layout

If you want to customize the outer most wrapping layout of your site, in the layouts/ directory you can do this by creating an app.html file. Like a page layout, this will just be another HTML document, with some additional capabilities:

  • Include <page-outlet></page-outlet> to position where the content from the processed page layout will appear

As with page layouts, app layouts are just HTML.

<!DOCTYPE html>
<html lang="en" prefix="og:http://ogp.me/ns#">

  <body>
    <header>
      <h1>Welcome to My Site!</h1>
    </header>

    <section>
      <page-outlet></page-outlet>
    </section>

    <footer>
      <h1>&copy; My Site</h1>
    </footer>

  </body>

</html>

When an app layout is present, Greenwood will merge the <head> and <body> tags for both app and page layouts into one HTML document structure for you.

Tip: If you use an .html file instead of .md for a page, you can use that as a page layout override. (since there will be no frontmatter). This way you don't have to make a layout for a one off page like a home page.

Pages

You can create all your pages in a pages/ directory in your project's workspace which will in turn map to the generated file output and routes of your site.

For example, given this folder structure:

.
└── src
    ├── pages
        ├── blog
        │   ├── first-post.md
        │   └── second-post.md
        ├── about.md
        └── index.html

You will have the following page URLs accessible in the browser:

  • /
  • /about/
  • /blog/first-post/
  • /blog/second-post/

And the following file output in the public/ directory

.
└── public
      ├── blog
      │   ├── first-post
      │   │     └── index.html
      │   └── second-post
      │         └── index.html
      ├── about
      │     └── index.html
      └── index.html

See our Front Matter Docs for more information on how you can extend fontmatter in Greenwood.

Scripts and Styles

Since all pages and layouts are just HTML with Greenwood, you can use <script>, <style>, and <link> tags as normal, referencing paths from your layout to the location of the files in your project's workspace.

For example, here is what a standard app layout might look like:

<!DOCTYPE html>
<html lang="en" prefix="og:http://ogp.me/ns#">

  <head>
    <link rel="stylesheet" href="/styles/theme.css"/>
    <script type="module" src="/components/app-header.js"></script>
    <script type="module" src="/components/app-footer.js"></script>
  </head>

  <body>
    <app-header></app-header>

    <page-outlet></page-outlet>

    <app-footer></app-footer>
  </body>

</html>

And the directory structure for it:

.
└── src
      ├── components
      │   ├── app-header.js
      │   └── app-footer.js
      ├── pages
      │   ├── index.md
      ├── styles
      │   └── theme.css
      └── layouts/
          └── app.html

It is recommended to use the "file" based approaches for loading JavaScript and CSS; <script src="..."> and <link rel="stylesheet" href="..."> respectively. This will allow Greenwood to optimize these assets during both development and build workflows. However, inline <script> and <style> can both be super helpful for one-off cases, so in those cases we recommend only relying on "vanilla" JS / CSS syntax. For more context, examples, and background information, you can review this PR.

Not Found Page

Greenwood will automatically generate a default 404.html for you but it is fairly generic. You can create your own though by simply creating a 404.html in your pages directory.

└── src
      └── pages
           └── 404.html

It will be emitted to the output directory as a top level 404.html, which is the common convention for most hosts and web servers.

Single Page Applications

If you would like to build a SPA and only deal with client side rendering, Greenwood can support that too As the name implies, you will just need to have an index.html file in your workspace (no pages/ directory) and that's it!

Below is an example layout of a SPA, and you can see a working example in our test suite where we validate using lit-redux-router with route based code splitting.


└── src
      ├── components
      │   └── app-footer.js
      ├── routes
      │   ├── about.js
      │   └── home.js
      ├── styles.css
      ├── index.js
      └── index.html