I've had some form of personal website ever since I was a kid. The early iterations were hosted on the now long defunct
Geocities
and
Angelfire
. I remember spending hours tweaking the HTML and CSS to get it just right.
During my university years, I started maintaining a website solely so I had something to show during job applications. At this point it was all static HTML/CSS/JS hosted on Github Pages .
Since my time as a consultant at Erlang Solutions , I've been using Elixir and Phoenix to power my blog.
At the time, it was all just standard dead views and controllers, but I wanted to try out LiveView , especially since the 1.0 release.
tl;dr -- if you're reading this, it works great !!
The Old Blog
The old blog was a standard Phoenix app with a few controllers and views. I decided that having to handle markdown rendering and syntax highlighting was too much of a pain to set up.
Instead, I wrote all of my posts via GitHub Issues and used the GitHub GraphQL API to:
- Fetch the issues
- Take the pre-rendered markdown body
- Write it into ets which was my "database"
This worked well enough! I had a
GenServer
responsible for polling the GitHub API every 5 minutes and upserting the posts in the
ets
table.
The query itself looked something like this:
query($owner: String!, $name: String!) {
repository(owner: $owner, name: $name) {
nameWithOwner,
issues(first: 10, orderBy: {field: CREATED_AT, direction: DESC}) {
nodes {
number
bodyHTML
createdAt
updatedAt
title
labels(first: 10) {
nodes {
name
}
}
}
totalCount
}
}
}
And all I had to do was to process the response and write it into the
ets
table.
When a dead view was requested, I would fetch the post from the
ets
table and just interpolated the HTML into the view.
This was cool because I could leverage GitHub's markdown rendering and syntax highlighting, and GitHub already supported features like tags and reactions which I planned on building on top of.
However... the iteration cycle for writing and previewing posts was too slow. Sure, I could view them on GitHub, but I wanted to see them in the context of my blog.
I'm also a neovim user, and I wanted to be able to write my posts in my editor of choice.
The New Blog
I took the opportunity a few weeks ago to rewrite the blog from scratch using LiveView.
Unlike dead views, LiveView is a stateful connection to the server. This means that I can have a single connection open and update the page in real-time as I write my posts. My blog doesn't currently actually leverage any real-time features, but I have a few fun things planned here.
Note: if you're unfamiliar with LiveView, I highly recommend checking out the official docs .
It's like HTMX or LiveWire , but better in pretty much every way.
I wanted to move away from GitHub Issues and decided the following:
-
I'd write my posts in markdown files with some frontmatter in my app's
priv
directory. -
I'd parse the markdown and frontmatter (I tried several approaches by I settled on
YamlElixir
andMd
) for this. - I needed a solution for syntax highlighting. It looked like doing this in the backend would limit my language choices, so I decided to use highlight.js on the frontend instead for now.
- Oban started supporting sqlite so I wanted to play around with that.
- I wanted to live reload my posts as I wrote them.
On start up, I'd start the "Importer" which would watch the
priv/posts
directory for changes. When a change was detected, it would parse the markdown and frontmatter and insert the post into the database.
Whenever the "Importer" ran, it would broadcast the new post to all connected clients via
Phoenix PubSub
.
I definitely want to add some more features to this blog, but I'm happy with the current state.
I'm slowly working through all my old posts and rewriting them in markdown. I'm also planning on adding a search feature and some more advanced filtering.
The previous blog engine was also run via a
SystemD
service, but with the new engine I wanted to play around with
fly.io
to eventually leverage their edge computing features in tandem with LiveView.
Poke Around!
This blog, as usual, is open source. You can find the code on GitHub .
Please see the top level
README.md
for instructions on how to run the blog locally.
Happy hacking!