These are all the supported configuration options in Greenwood, which you can define in a greenwood.config.js file in your project's root directory.

The below is a greenwood.config.js file reflecting default values:

export default {
  devServer: {
    extensions: [],
    hud: true,
    port: 1984,
    host: 'localhost'
  basePath: '',
  port: 8080,
  interpolateFrontmatter: false,
  markdown: {
    plugins: [],
    settings: {}
  prerender: false,
  staticRouter: false,
  optimization: 'default',
  plugins: [],
  workspace: new URL('./src/', import.meta.url),
  pagesDirectory: 'pages', // e.g. src/pages
  templatesDirectory: 'templates' // e.g. src/templates

Base Path

There are cases where an application might be deployed and hosted from a "sub" pathname that acts as the relative "web root". (GitHub Pages is an example of this)

So with a URL of, the basePath could be set as such:

export default {
  basePath: '/app-a'

This would then configure Greenwood's routing and <script> and <link> tags to reference this segment automatically. For example:

<script type="module" src="/app-a/some-script.a243dccss.js"></script>

For convenience, the value of basePath will also be made available as a global variable in the <head> of your pages. For example:

<script data-gwd="base-path">
  globalThis.__GWD_BASE_PATH__ = '/app-a';

User content, like <a> and <img> tags will require manually prefixing the basePath in your code.

Dev Server

Configuration for Greenwood's development server is available using the devServer option.

  • extensions: Provide an array of extensions to watch for changes and reload the live server with. By default, Greenwood will already watch all "standard" web assets (HTML, CSS, JS, etc) it supports by default, as well as any extensions set by resource plugins you are using in your greenwood.config.json.
  • hud: The HUD option (head-up display) is some additional HTML added to your site's page when Greenwood wants to help provide information to you in the browser. For example, if your HTML is detected as malformed, which could break the parser. Set this to false if you would like to turn it off.
  • port: Pick a different port when starting the dev server
  • proxy: A set of paths to match and re-route to other hosts. Highest specificity should go at the end.


export default {
  devServer: {
    extensions: ['txt', 'rtf'],
    port: 3000,
    proxy: {
      '/api': '',
      '/api/foo': ''

Interpolate Frontmatter

To support simple static templating in HTML and markdown pages and templates, the interpolateFrontmatter option can be set to true to allow the following kinds of simple static substitions using a syntax convention based on JavaScript template literals.


Given some frontmatter in a markdown file:

template: post
title: Git Explorer
published: 04.07.2020
description: Local git repository viewer
author: Owen Buckley
image: /assets/blog-post-images/git.png

It can be accessed and substituted statically in either markdown or HTML.

# My Blog Post

Published: ${}

Lorum Ipsum.
    <title>My Blog - Configuration</title>
    <meta name="author" content="${}">
    <meta property="og:title" content="My Blog">
    <meta property="og:type" content="website">
    <meta property="og:url" content="">
    <meta property="og:image" content="${}">
    <meta property="og:description" content="My Blog - ${}">


You can install and provide custom unifiedjs presets and plugins to further customize and process your markdown past what Greenwood does by default. After running an npm install you can provide their package names to Greenwood.


export default {
  markdown: {
    settings: { commonmark: true },
    plugins: [


Greenwood provides a number of different ways to send hints to Greenwood as to how JavaScript and CSS tags in your HTML should get loaded by the browser. Greenwood supplements, and builds up on top of existing resource "hints" like preload and prefetch.

OptionDescriptionUse Cases
defaultWill add a <link rel="..." src="..." as="..."></link> tag for every <script> or <link> tag in the <head> of your HTML using preload for styles and modulepreload for scripts. This setting will also minify all your JS and CSS files.General purpose.
inlineUsing this setting, all your <script> and <link> tags will get inlined right into your HTML.For sites with smaller payloads, this could work best as with inlining, you do so at the expense of long-term caching.
noneWith this setting, none of your JS or CSS will be minified or hinted at all.The best choice if you want to handle everything yourself through custom Resource plugins.
staticOnly for <script> tags, but this setting will remove <script> tags from your HTML.If your Web Components only need a single render just to emit some static HTML, or are otherwise not dynamic or needed at runtime, this will really speed up your site's performance by dropping unnecessary HTTP requests.

These settings are currently considered experimental. Additional improvements and considerations include adding none override support, SSR + hydration, and side effect free templates and pages.


export default {
  optimization: 'inline'


Additionally, you can apply overrides on a per <link> or <script> tag basis by adding a custom data-gwd-opt attribute to your HTML. The following is supported for JavaScript and CSS.

<!-- Javascript -->
<script type="module" src="/path/to/file1.js" data-gwd-opt="static"></script>
<script type="module" src="/path/to/file2.js" data-gwd-opt="inline"></script>

<!-- CSS -->
<link rel="stylesheet" href="/path/to/file1.css" data-gwd-opt="inline"/>

Just be mindful that style encapsulation provided by ShadowDOM (e.g. :host) for custom elements will now have their styles inlined in the <head> and mixed with all other global styles, and thus may collide and be susceptible to the cascade depending on their degree of specificity. Increasing specificity of selectors or using only global styles will help resolve this.

Pages Directory

By default the directory Greenwood will use to look for your local content is pages/. It is relative to your user workspace setting. (${userWorkspace}/${pagesDirectory})


export default {
  pagesDirectory: 'docs' // Greenwood will look for pages at src/docs/


Unlike the port option for devServer configuration, this option allows you to configure the port that your production server will run on when running greenwood serve.


export default {
  port: 8181


When set to true Greenwood will pre-render your application using WCC and generate HTML from any Web Components you include in your pages and templates as part of the final static HTML build output.

You can combine this with "static" components so that you can just do single pass rendering of your Web Components and get their output as static HTML and CSS at build time without having to ship any runtime JavaScript!


export default {
  prerender: true

Static Router

⚠️ This feature is experimental. Please follow along with our discussion to learn more.

Setting the staticRouter option to true will add a small router runtime in production for static pages to prevent needing full page reloads when navigation between pages that share a template. For example, the Greenwood website is entirely static, outputting an HTML file per page however, if you navigate from the Docs page to the Getting Started page, you will notice the site does not require a full page load. Instead, the router will just swap out the content of the page much like client-side SPA router would. This technique is similar to how projects like pjax and Turbolinks work, and like what you can see on websites like GitHub.


export default {
  staticRouter: true

Templates Directory

By default the directory Greenwood will use to look for your templates is templates/. It is relative to your user workspace setting. (${userWorkspace}/${templatesDirectory})


export default {
  templatesDirectory: 'layouts' // Greenwood will look for templates at src/layouts/


Path to where all your project files will be located. Using an absolute path is recommended.


Setting the workspace path to be the www/ folder in the current directory from where Greenwood is being run.

export default {
  workspace: new URL('./www/', import.meta.url)

Please note the trailing / here as for ESM, a path must end in a / for directories.