Using x0 as a blog system

4 minute read

x0 is a React static site generator created by Compositor. It generates completely static HTML content from a React application so that it can be deployed without including any JavaScript at all. This is really neat because it lets you use React as a templating tool without a performance hit from running React in a visitor's web browser.

When starting to write this blog engine I wanted to use React because it makes generating UIs programmatically incredibly easy compared to other templating tools.

There are a number of React static site generators but most of them still assume you want to run React on the client side as well as in generation. This is useful if you have an actual React application as you get all the benefits of Server Side Rendering (SSR) but can generate the markup once rather than on every request. However, I wanted a totally static blog because there's nothing that I actually need React for on the client side.

After finding x0 it initially looked perfect and I had most of a blog engine in place before I found some of its shortcomings.

Shortcoming 1 — Dynamic routes

x0 doesn't (currently) deal with dynamic routes, instead they have to be specified in the package.json at build time. For a blog, each post will need its own route so this has be made dynamic.

I solved this problem by creating a prebuild script that adds every post I've written to the routes section of the package.json file.

This works but it means there will be a bunch of changes to package.json that aren't really changes at all, just adding/removing routes.

Shortcoming 2 — The filesystem and x0

I store the posts for my blog as simple Markdown files in a directory. They have some frontmatter to store the title & description and the filename is the date of the post. This works out really well and is how a lot of other Markdown based blog engines deal with posts too.

However, when using x0's development mode the fs module is disabled. There's probably a good reason for this, but it made the development mode unusable. I've worked around this by not using it and running a static build whenever a file changes instead, but this is slow and doesn't deal with Hot Module Replacement at all.

I'm considering fixing this by writing blog posts as React components instead as then they could be handled in x0's development mode.

Shortcoming 3 — Styled components and CSP headers

This issue has nothing to do with x0, but is another issue I came across. The Styled Components library and the Content-Security-Policy (CSP) header don't work well together.

I am using a CSP header that blocks everything other than self hosted styles and images. That means all inline styles will error and not be evaluated.

This is a very strict CSP and it is also incompatible with how Styled Components works — Styled Components generates a style tag to hold all of the CSS for any Styled Components that are used. This means that the CSP will block Styled Components' CSS because it is inline, rather than hosted at a URL with the same domain name as my blog.

I work around this with a postbuild script. This script looks at every .html file of my blog and removes Styled Components inline styles, generating a standard CSS file from them instead.

This obviously isn't ideal. I like Styled Components so I decided to work around the problem, but the solution isn't great and I will probably end up rewriting my CSS as CSS at some point.