May 11, 2025
The first rev of my blog has been doing fine, but I really wanted something a little bit richer and easier to navigate. I wanted a page for each post as well as a homepage that shows all the posts in order. I also wanted to add an RSS feed (as requested by my coworker Michael).
I started out by moving my blog out from under my homepage
project into its
own dedicated site. I also gave it a new URL, blog.jamesmassucco.com
. While
adding this into my cloudflare-ddns
container configuration (which, by the
way, makes it insanely easy to establish new subdomains directly in code), I realized
that it was clunky to be defining my list of domains in a gitignore'd
.env
file and so I moved it into the docker-compose.yml
. Now
it'll be even easier to add (and keep track of) new subdomains, since I seem to be
adding at least 1~2 of them every week!
The first thing I did was restructure my markdown files to have a proper metadata
section. I used the frontmatter
specification, which allows encoding
metadata by inserting a block like this at the top of a file:
---
title: 'Leveling Up My Blog'
date: '2025-05-11'
tags: [blog]
summary: 'Turning my blog into a dedicated app with a page for each post'
slug: blog-levelup
---
The title and date were already existing. I added tags
for potential future
use, the summary
for displaying on the main page, and
slug
will be the name of each posts' HTML page (e.g.
blog.jamesmassucco.com/posts/blog-levelup.html
). Parsing the data out is
pretty simple - just import frontmatter
in python and then
frontmatter.load(<md_path>)
and you get a result with
content
and metadata
. The content
was the same as
the markdown I was used to working with (doesn't include the metadata), while the
metadata
made available a dictionary of key-value pairs with the metadata I
had encoded. To make it easier to access the metadata, I created a
pydantic
class so that instead of metadata['title']
, I could
do metadata.title
. I hate typing quotation marks lol. I also added a class
to represent each blog post, handle parsing it with frontmatter
, and do a
few more convenience functions.
Once I had all the posts parsed, I needed to generate 3 sets of outputs:
- An
index.html
to serve as the new blog homepage - A
<post-slug>.html
for each blog post - An
rss.xml
to provide RSS feed functionality
For each of these, I created a jinja2
template. Jinja is a powerful python
templating engine. It allows you to write a document (e.g. html) that includes special
tags like {{ post.metadata.date }}
, and then feed in a
post
object to the render
operation and it will replace the
{{ }}
blocks with rendered data from your object. It also has a very useful
for-loop function, and a few other functions that proved useful for this exercise. I
used ChatGPT to get basic versions of each of the 3 templates, and then spent some time
tweaking them to fit the style of the rest of the site. After an hour or so, the site
was looking pretty rad.
To finish it off, I killed off the old static blog and replaced it with a link to this
new blog.jamesmassucco.com
I also made each blog post page include a
Blog Home
button in the top-left, as opposed to the typical
Home
button found on the other pages. That way, if someone is viewing a
blog post, they can click back to the main page of the blog. The main page of the blog
then includes a Home
link to go back to the main site home, but I figured
if someone is reading a blog post, it's more likely that they want to go back to the
blog index than the top-level site home. Maybe sometime soon I'll add some more
navigational functionality - but this should work fine for now.