Greenwood has two types of templates:

  • App Template: The app shell if you will, that wraps all pages. This is provided for you by Greenwood, but you can override if needed. (though not recommended)
  • Page Template:. Nested within the app template, and how you define different pages / layouts for your site. Common layouts would be used for a home page, documentation pages, blog posts, etc.

Page Template

In order to make a page template, you need to create a LitElement based custom element that contains a number of pre-defined variables, elements, and imports. You need to do this in a file within your templates/ directory named -template.js.

Here is an example page-template.js (the default one included with Greenwood). You can just copy / paste this to start your own page template.

import { html, LitElement } from 'lit-element';

class PageTemplate extends LitElement {
  render() {
    return html`
      <div class='gwd-wrapper'>
        <div class='gwd-page-template gwd-content'>

customElements.define('page-template', PageTemplate);

Note: the filename must be in the format <label>-templates.js and the customElements name must be page-template.

Template Hooks

A number of hook variables are defined that tell greenwood to do different things


MDIMPORT; Tells Greenwood to import a markdown file into this component. But we also have to define where the compiled markdown element(page) will be placed within our page-template. Hence below within our render() method you will see the <entry></entry> element. That defines exactly where to place it.


METAIMPORT; and METADATA; hook variables import the default greenwood meta component and data which handles all your configured meta data. You can then render this component within the render() method using the METAELEMENT variable hook.

The complete example can be found in the greenwood source which is the default page-template.js if no other is defined.

With a completed page-template.js present in your src/templates/ folder you can define which page uses it via front-matter at the top of any markdown file. See Front Matter Docs for more information. Simply including a file named page-template.js will overwrite the greenwood default template for all markdown files, without needing to declare the template at the top of markdown file.

App Template

In order to make an app template, you need to create a LitElement component that contains a number of pre-defined variables, elements, and imports. You need to do this in a file called your templates/app-template.js.

First, we need our app template to use routes, by default greenwood uses lit-redux-router.

Here is Greenwood's app-template, which you can copy / paste as a starting point for your own custom app template, though it is recommended to let Greenwood manage this for you.

import { html, LitElement } from 'lit-element';
import { connectRouter } from 'lit-redux-router';
import { applyMiddleware, createStore, compose as origCompose, combineReducers } from 'redux';
import { lazyReducerEnhancer } from 'pwa-helpers/lazy-reducer-enhancer.js';
import thunk from 'redux-thunk';

// initialize a redux store
const compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || origCompose;
const store = createStore(
  (state, action) => state,
    compose(lazyReducerEnhancer(combineReducers), applyMiddleware(thunk)));

// Next we need to import a list of files that will be generated when Greenwood is run
import '../index/index.js';

// Finally we can connect to our store and define our component.

// Add the MY-ROUTES(without dash) predefined hook. This is where all your routes will be loaded.
// You may also opt to define a custom 404 route here.
// You must define the app-template with the element name eve-app
class AppComponent extends LitElement {
  render() {
    return html`
      <lit-route><h1>404 Not found</h1></lit-route>

customElements.define('eve-app', AppComponent);

A working example can be found in the greenwood source which is the default app-template.js if no other is defined.


You can create all your pages in a pages/ directory in your projects workspace. You can also create nested pages and the page paths will map accordingly.

For example, given this folder structure:

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

You will have the following page URLs:

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