New Site powered by Spress - Part II
This blog post continues on part one in which I went into detail about what I think is great about having statically generated webpages. In this post I want explain how working with Spress felt like.
So I fired up Spress without much confidence, ready to stop and try the next generator the moment it would start bothering me too much. I didn't stop. This may be the first good sign or it proves that I'm more persistent than I thought.
The main reason I tried Spress first was that I'm familiar with the technology stack from my professional daily bread and butter. It's implemented in PHP and runs off Symfony components and Twig as a templating engine. That made me hope I would be able to start working quickly and understand how it works and how I can extend it.
An easy way to use Spress is to download a PHAR file which is a package for the PHP application.
CLI
From here there are basically three important console commands to keep in memory:
spress.phar new:site
... You only need to run this once to create a page scaffold from an existing template.
spress.phar site:build
... This generates the pages in the build directory, copies all assets and can also be used as a server that rebuilds the page on every change with the --server --watch
options.
spress.phar new:post
... This is a nice wizard-like shortcut that guides you through creating the skeleton for a blog post. This is not necessary though as you can easily create the files in the right format on your own if you have seen some.
Basics
Blog Post
The main element is a blog post. It has a specific file name (e.g. 2020-05-27-new-site-powered-by-spress-ii.md) and is comprised of a header in YAML syntax separated by a line from a body that contains Markdown text.
For every post you need to defines a layout which is the Twig template that is used to render the blog page on its own. As you can define your own meta data in the header and as you can have individual templates this is quite a powerful tool. For example my photo posts don't contain a body at all. All the information is given in structured data in the header and the DOM is specified entirely in the template.
Here is an example:
---
layout: photo-post
title: "Photo #8"
categories: [photos]
tags: []
author:
name: "Marcel Pfeiffer"
images:
20140101:
date: "2014-01-01"
name: ~
url: "/assets/img/photos/20140101.jpg"
---
A minor inconvenience is the fact that pages are by default ordered by date but there is no standard way to include the time into the page ordering. That's why my photo posts are scrambled here.
Pages
Pages are a bit tricky. They are supposed to be Markdown files saved as HTML files in the project root. Again you can define a layout to be use. I use this for my simple Impressum page (impressum.html). But for some reason this doesn't work if you use pagination. In this case I had to save the file as words/index.html.
Categories, Tags and Generators
There are the concepts of categories and tags to group posts by. But there is no intrinsic difference between those apart from how you handle them.
Spless offers generators and pagination that you can use to browse through a list of posts or other collections that you have defined. That said, the documentation about those was not very understandable. But the given examples were enough for me to be able to use them.
Template
The documentation guides you into using an existing template or creating your own from scratch. As the default template doesn't look that great and the second option is badly documented this seems overwhelming at first. If you dig a bit deeper into the documentation you also notice that you can overwrite individual template assets in your layouts and includes folder. That is the route I took. I had a look at a template I wanted to change, copied it into the general directory and made my edits (or more specifically copied my existing template into it and changed the syntax to work with Twig).
The nice thing about Twig templates is that there is an easy import/include mechanism. That way I could write a base template for how an individual post should look like with header, date, author and content and then re-use this snippet through importing it into the post page, the list or the category-filtered list.
Troubleshooting
During development if you ever want to know what's inside a variable in a Twig template a trick is to transform it into a JSON string that can be written into the page.
{{ page|json_encode }}
Documentation and other flaws
Even though I got this page ported in more or less a single evening the documentation left a bad impression. Some things were badly phrased or text snippets scrambled in a paragraph (I already sent a pull request for a correction). On many page you are prominently asked to run a command first that creates an entirely new site even though you have most likely already done this if you seek out help for how to include pagination into your page.
Another thing that suprised me is the fact that there is no helping construct of how to link internal pages. You need to know into what filename and into which folder a page is going to be compiled to be able to link to it.
And the last small problem that I didn't think about beforehand is the fact that all pages are generated every time you change something or add a page or post. This is inevitable but leads to the problem that when you need to upload your page via FTP you always have to overwrite everything. Skipping mechanisms like only newer (it's always newer) or different size (my photo posts compile to the exact same number of bytes) don't help here.