Templates and Pages

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

  • App Template: The "app shell" that will wrap all pages. One is provided for you by Greenwood, but you can override it if needed.
  • Page Templates: A template 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 templates.

Note: You can use either relative (../) or absolute (/) paths in your templates since using ../ will allow for IDE autocomplete on your filesystem, but is marginally slower than using /.

Page Templates

Pages in your project will generally want a template 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 _templates/ directory within your workspace.

In order to make a page template, 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 templates 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 templates and use them for pages by doing two things:

  1. Create a new template, e.g. templates/blog-post.html

  2. In your frontmatter, specify that template

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

See our Front Matter Docs for more information.

App Template

If you want to customize the outer most wrapping layout of your site, in the templates/ directory you can do this by creating an app.html file. Like a page template, 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 template will appear

As with page templates, app templates 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 template is present, Greenwood will merge the <head> and <body> tags for both app and page templates 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 template override. (since there will be no frontmatter). This way you don't have to make a template 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 templates are just HTML with Greenwood, you can use <script>, <style>, and <link> tags as normal, referencing paths from your template to the location of the files in your project's workspace.

For example, here is what a standard app template 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
      └── templates/
          └── 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