About the script

This is a simple script for creating a static website.

Content is created in text files, using the markdown format, processed by the script and published on the web. That's it.

If this sounds interesting, keep reading to see how I create my own independent part of the web.

The aim is to create simple websites similar to ones generated by these services:

All in the spirit of the IndieWeb.

Table of Contents

  1. Getting started
  2. Writing
  3. Folders
  4. Menus
  5. Themes
  6. Posts lists
  7. Shortcodes
  8. Metadata
  9. Settings
  10. References

Getting started

The script is written in PHP and makes use of:

The site is hosted on Apache2 and used LetsEncrypt for the SSL certificates.

Writing

Adding content

Content is written in Markdown files, with the extension ".md". Markdown is a very simple language for writing content that will be converted to HTML when the page is published. For more details on Markdown, please see GitHub's Markdown guide.

Markdown can also contain HTML, so you can markup your content in plain HTML if you prefer. Mozilla provide a very good HTML reference, if you are new to HTML.

Only files with the extension .md are processed and converted to HTML files.

Front Matter

Each Markdown file can also contain settings specific to that page or post. This is called Front Matter and is always placed at the start of the file.

The Front Matter section of the file has a specific structure which must be followed.

Firstly it always starts and ends with the line: ---.

Secondly it contains attribute / value pairs, one per line, eg: title: Welcome to my blog. The order of the attributes within the Front Matter is not important.

Front Matter is written in YAML. Here is a good guide to YAML, although it might be a little technical for some.

If the attribute contains a list of values, it would be spread over multiple lines, eg:

tags:
- post
- travel
- photo 

The Front Matter of a typical post might therefore look something like this:

---
title: Happy New Year
date: 2025-01-01 08:00:00
tags:
- celebration
- new year
- photo
---

The following Front Matter attributes are accepted. Any other attributes will be ignored.

Attribute Value
title Free text.
date ISO format YYYY-MM-DD hh:mm:ss eg "2025-01-01 08:00:00". Used for sorting posts.
permalink Any valid URL path, eg "/about/". If not specified the link for the file will be the title.
tags Free text list of tags, one per line.
draft Entry won't be published if draft is "yes"
private Entry won't be linked to if private is "yes"
titleprefix Free text to add before the page name in the page title.
navigation For defining in which menu this page should appear.
- menu Which menu the page appears in. Default templates support "header" and "footer".
- title The text for the menu item.
- position The position of the menu item within the menu. Should be a number.
- pre Text to add before the link for the menu item.
- post Text to add after the link for the menu item.
- class CSS class to add to the menu item, for custom styling.
pagination For defining how lists of posts are created and paged. Is all on one page, no paging
- data Defines tags of the posts to include in this list. Posts must be tagged with this tag to be in this list
- size The size of the pages. If not set, it will show all posts in one list.
template The name of the template file used to process this markdown file. eg if set to "page" it will use the template "page.html.twig"

Note: you do not need to enclose the value in quotes in the Front Matter section.

A page to be placed in the header menu would look like this:

---
title: About
date: 2025-02-01 08:00:00
navigation:
- menu: header
- title: About me
- position: 3
---

Example markdown file

A typical complete Markdown file might therefore look something like this:

---
title: Happy New Year
date: 2025-01-01 08:00:00
tags:
- celebration
- new year
- photo
---

## Welcome

This is first blog post, I hope you enjoy this site.

<blockquote>Doing It Yourself Rocks!</blockquote>

Folders

Expected folders

These are the default folders. They should not be removed or renamed. More folders can be added without affecting the site.

Folder Description
assets Contains static files, such as images, styling (CSS) and scripting (JavaScript). Folder will be copied as is to your website.
data Contains configuration files, in YAML format.
feed Contains code to generate the RSS feed.
pages Contains the site pages written in Markdown. These are standalone pages that will not be processed as posts and therefore won't appear in your feed.
posts Contains the blog posts written in Markdown. Subfolders are allowed to help organise the posts (eg by year), but it won't affect how the posts are processed.
themes Contains template for the site design, using the Twig templating system.

Default Files

This is a list of specific files. You can edit them, but be sure you understand what you are doing.

Page Description
robots.txt Defines how search engines index the site. See Google for further information on robots.txt. Modify only if needed.
pages/home.md Content for the homepage. The homepage markdown file should have the permalink front matter attribute defined as: permalink: /. One page, and only one page, should have this set otherwise the site will not have a homepage and visiting the base URL will return a page not found.
pages/404.md Content to display when a page is not found. The page not found markdown file should have the permalink front matter attribute defined as: permalink: /404.html.
feed/index.md Generates the RSS feed in Atom format.
pages/sitemap.md Generate a sitemap.xml file used by search engines to index the site. Remove if a sitemap is not needed (not recommended).

Menus can be defined for the header and footer. This is done in the file "/data/menus.yaml". The syntax of this file is a little more complicated as it is written in YAML.

Learn more about the YAML syntax here.

As an example this file menus.yaml file for a site with two menus, a header and a footer menu. You can add as many menus as you wish, but the default template only knows the header and footer menus.

header:
    - title: Home
      link: /home/
    - title: About
      link: /about/
    - title: Blog
      link: /blog/
    - title: /walking
      link: /walking/
      pre: 'and '
    - title: dog 🐕‍🦺
      link: /tagging/dog/
      pre: 'the '
      post: '. '
- footer:
    - title: RSS
      link: /feed/
      class: ally-statement
    - title: Accessibility
      link: /accessibility/
    - title: Site info
      link: /my-site/

If menu items are defined in the menus.yaml file as well as in the Front Matter of specific pages, they are merged based on the position of the items. It is better to not define menu items in both the menus.yaml file and the page Front Matter as the results can be unexpected.

Posts Lists

Lists of posts can be defined using the pagination Front Matter attribute. If your page has this attribute set, the page will display a list of relevant posts. Note though that you need to ensure the page uses a template designed to show posts. By default the template "archive.hmtl.twig" can be used.`

Themes

Themes can be set in the settings.yaml file.

Themes are created in the /templates/ folder. They are build using the Twig template language.

If not set it will take the default templates from the folder: /templates/default/. If that folder does not exist, the site cannot be built.

A theme can extend another theme, as defined by the themeExtends setting.

Shortcodes

Markdown files are sent through the Twig processor before they are themselves rendered to HTML. Any Twig statements in the Markdown file will therefore be processed, including any such statements in the Front Matter.

Examples

The pages.yaml file looks like this:

template: page
permalink: /{ { filename }}/

{ { filename }} will be processed by Twig and replaced with the value of "filename" before the page is handled during the site generation.

If the Twig statement includes a double quote: " then it needs to be hidden from the Markdown converter, else it will be converted to an HTML entity: &quot;.

The best approach is to use single quotes: ' . eg:

{ { include('./templates/default/includes/postslist-fixed.html.twig') } }

If this is not possible then the statement needs to be inside an HTML comment:

<!--{ { include("./templates/default/includes/postslist-fixed.html.twig") }}-->

(Note that for the examples above a space has been added between the opening curly brackets).

The Markdown converter will not convert the content of the HTML commment. Later on the script changes <!--{ { }}--> back to { { }}.

Likewise if there are any other characters in the Twig statement that Markdown will convert, the statement needs to be wrapped in HTML comments. Some example characters include <, > and &.

Metadata

Metadata is information about the site. It is stored in YAML format in the file /data/metadata.yaml. This metadata can be accessed from the site's template, for example to display the title of the site.

This is an example the metadata.yaml file for a basic site:

title: Robin's
url: https://www.robin.is/
urlShort: robin.is
language: en
description: Setup and host your own independent blog
startYear: 2025
relMe: https://github.com/robindotis/
gitHubRepo: https://github.com/robindotis/robin.is/
theme: sky
feed:
  subtitle: Setup and host your own independent blog
  filename: index.xml
  path: /feed/index.xml
  id: https://www.robin.is/
author:
  name: robindotis
  email: admin@robin.is
  url: https://www.robin.is/about/
  webmention: https://github.com/robindotis/

Settings

Settings are set in the file: /data/setting.yaml. These settings define how the content should be processed. Do not touch unless you are sure you know what you are doing.

Allowed settings are:

Name Example Default Description
staticDirs [assets] [assets] List of folders containing static files to be copied as is to the output directory.
staticFiles [robots.txt] [robots.txt,feed/pretty-feed-v3.xsl] List of static files to be copied as is to the output directory.
sourceDirs [posts] [posts, pages, feed] List of folders to be processed. Only Markdown files will be processed.
outputDir /_site/ /_site/ The folder in to which the files for the static site will be placed.
showSpeed true false A gimmick to output the site generation speed to the home page (the root index.html file). Will replace the token CW_SPEED with the time in seconds and remove any HTML comments surrounding it. HTML comments can therefore be used to hide the token from other pages
theme matrix default The name of the folder containing the templates for the site.
themeExtends default The name of the folder containing the theme that theme builds up on, if any.

All settings are optional. If they are not provided, defaults will be used.

The default settings.yaml file looks like this:

staticDirs: [assets]
staticFiles: [robots.txt,feed/pretty-feed-v3.xsl]
sourceDirs: [posts, pages, feed]
outputDir: /_site/

References

Below are some excellent links to further technical information and documentation on the technologies used for this site generator.