Next post Archive

A Very Meta Post - An adventure in unnecessarily reinventing the wheel

This post is written in my own markup language, compiled to HTML and rendered by a custom blog service, and finally served by a custom HTTP server.

There is an abundance of open-source software capable of everything I could want from all of these compnents. As the tantruming child I am however, I have decided that it is only morally acceptable for software to operate is in a way understood and approved by me. The flaws, inconsistencies and bugs that I refuse to fix are of course justified by reasonable technical constraints (anyone else's are unacceptable).

Designing an HTTP Server

I decided to write my webserver in async Rust with Tokio. In my view, async is Rust's biggest killer feature, and Tokio provides a fantastic runtime and std-library replacement for writing IO-oriented async applications like webservers.

I wanted the content for my webserver to be deployable from a single directory, so that the content of the website could easily be stored in a git repository, which could be easily cloned to setup the website.

The webserver is split into different services - A service might be static files, a blog, or a CGI handler. HTTP requests are distributed by matching their URIs to different services. A list of all the services and their configuratuons is stored in a single .toml file.

It does not properly support HTTP - at the moment, only the first line of the request is read to obtain the URI and method, and request headers are ignored. This will need to be fixed to enable proper caching support, but disabling all caching and watching each webpage load like it did in the 90s is also an option.

Designing a Markup Language

I chose to make a Markup language once I ran into a specific problem - Each blog post would need metadata associated with it. It would be convenient if this metadata could be in the same file as its content. And so work on a new markup language that could include metadata began!

I called this language "MatthewDown", as a biblical pun, opening up opportunities for two follow-up projects following the same naming scheme.

I decided to maintain slight compatibility with MarkDown, so that a simple document might be understood by both, but to ignore the details, as there is already disagreement about everything markdown-esque.

The grammar of the language is specified using the fantastic Pest library - the first method of specifing the grammar of a language that I could work out how to use.

MatthewDown contains block elements, such as paragraphs or list items, and inline elements, such as links or italics. All block elements can be indented to make them children of preceding elements.

The syntax $$element(args, ...) content... is used for MatthewDown-specific block elements, while $element(args, ...)[content...] declares MatthewDown-specific inline elements. This only introduces special behaviour for one character - the dollar symbol, and as I'm English, and the pounds sterling symbol is unaffected, this works out perfectly. It also mirrors the syntax of links in the case of inline elements, and lists in the case of block elements.

The metadata (wasn't that the point of this language anyway?) is represented by a block element, $$metadata. It's child elements contain the metadata content. Ordered lists (1., 2., etc) represent sequences, while unordered lists (*) represent key value pairs. The metadata can be deserialized into structures using the serde library.

The result is a flexible way of including metadata in MatthewDown files while leveraging the existing syntax, rather than introducing new syntax or embedding another language like JSON.

Designing a Website

The website is built with a mix of generated and static content, to make it a little interesting. The recipe section in particular takes an unnecessary, yet fun, approach.

The webserver uses a library of templates to generate its HTML content, and so the style of the website is easy enough to alter.

I went for a design that tries to resemble a notebook, which should to some extent excuse how ad-hoc the website is, and picked out some Google Fonts that looked nice.

Putting everything together

Now that all these components are in place and working together, I have a functioning website.

It brings me immense joy when it drags itself along on it's belly far enough to serve a page, and I'm immensely excited to write this post, knowing and understanding all the bits of software machinery it will pass through to end up as a webpage.

I know that sooner or later, I'll get bored of this project, and eventually I'll become different enough from the person who wrote it that all its flaws will become annoying rather than charming, and I'll throw it out and start again. Until that time though, isn't it great fun!

Written by Francis Wharf
Next post Archive