I decided to give my site a much-needed redesign, so in the spirit of making things harder than they need to be, I decided to make a static site generator. You might see "Made with Roxy" at the bottom of this page (unless you're reading this so far in the future that I've changed it again). Roxy is what I've decided to call this generator. I wanted to write a little about my experiences creating it.
Initially, I planned to create everything from scratch -- the file reader, the markdown parser, the syntax highlighter, everything. After a few attempts, I decided that this was entirely silly and scrapped that idea. I also toyed with the idea of using a compile-time layout system but I didn't want to have to recompile a Rust executable every time I made changes to the layouts.
I finally settled on using Tera as my templating engine. It's Jinja-like and made for Rust with a lot of really useful features. It's significantly slower than compile-time engines but also much more flexible. In addition to a templating engine, I also needed something to parse Markdown files which would be the basis for the content of each page. For this, I used pulldown-cmark.
With these two things decided on, my idea was simple: layouts would be defined in one location and content would be defined in another. Most fancy layout stuff would be handled by Tera (includes, extensions, etc) and the data would live in the Markdown. This created two distinct types of data: layouts
and content
. I also had the idea that the content
directory structure should define the site's structure as well. (eg. content/blog/my-post.md
becomes domain.com/blog/my-post
).
Creating it was straightforward -- in fact, it was so simple that I accidentally deleted the project while trying to push it to git and had to rewrite it. I did it in a few hours (and stayed up until 6 am doing it).
It only performs a few steps.
content
directory
.
(dot), skip itHashMap
content
directory. This will become relevant later.HashMap
is serialized and given to each layout. One major use would be to iterate their contents, eg. a blog index that displays all posts. Subdirectories can't be accessed if they aren't recognized as content themselves).content/blog/my-post.md
becomes output/blog/my-post/index.md
)layout
frontmatter field, try to use that layout, otherwise, use index.html
as a defaultThere were a few things I didn't consider in my original plan. Most notably, syntax highlighting and command-line argument parsing. I ended up adding syntect
for syntax highlighting and clap
for argument parsing. Additionally, there's a quirk based on my decision to tie content
to page layout: to create a page, even if it's entirely layout driven, it requires a content file as a placeholder.
There's a bunch of things Roxy doesn't do
I ended up making bash files to do all that though and they're available in the repository for this website if you'd like to see or use them.
The code is a disaster and needs to be refactored. I'll do that the minute I have a really good reason to. For now, it works well enough for me, and I really like using it. This is one of the times I'm very happy I decided to make something superfluous for myself.