And we're LIVE! 🎉
This blog is now live and it's come a full circle. My first blog was started in 2000. It was a static site made from HTML. After that I started blogging on various platforms, mainly Blogger but also a few others. For a six year period between 2007-2013 I ran a Wordpress blog. Around the mid 2010s I started putting content on the various social media platforms. And now after all this, this blog is back to being a static site in HTML.
Why a static site?
There are a few different reasons why I finally settled on a static site format:
- After many years of posting content on other platforms, I decided I should own my own content. Social media is fine for ephermal content, but it's not great for long form articles
- Many blogging platforms take control of your site. They will insert ads into the page, insert analytics, make your readers sign up to their platform. Worst of all, they will redirect your readers to other trending posts on the platform in an attempt to increase engagement on the platform. On the plus side, they have the users and can also drive traffic to your site, so it works both ways. Still, after more than a decade on these platforms, I decided that owning the content was the way to go
- Static sites don't require you to maintain a server and a database. Production deploy is completely painless. You don't have to worry about server patches and security vulnerabilities (Hello, Wordpress!)
- There are numerous static site generators that make the process extremely simple. Most just get out of the way and let you focus on the content. At the same time you can modify the code if there is some feature that you would like
- The content can live in a source repository, which is like an automatic backup. Plus you get all the benefits of text - diffs, version history, and so on
- You can be cool and say that you are developing a JAMStack application 😆
Which static site generator?
Once I decided on a static site, the next question was which site generator to use. You are spoilt for choice here:
- Big frontend frameworks like Next, Nuxt or Gatsby
- Smaller tools like Hugo, Jekyll and Eleventy
- or a host of other choices
I decided to go with Pelican, for two reasons. One, its Python based, so I didn't have to install another toolset on my dev box. Second, it uses Jinja for templating, which I am familiar with from working on Django.
To be fair, I also have Node on my machine and am familiar with React, so NextJS and Gatsby were tempting options, but it just seemed too heavy for what I needed. I just need static site generation and none of the other bells and whistles provided by these frameworks.
Getting started with Pelican
Getting up and running with Pelican was super easy. The quickstart covered it well. Just create a virtualenv
> python -m venv mysite
> cd mysite
Activate it (Windows)
> Scripts\activate
(Mac)
> source bin/activate
and install pelican in it
> python -m pip install "pelican[markdown]"
Then create a subdirectory for the site, cd into in and run pelican-quickstart in there. This will create all the scaffolding required to get started. You can then just put you articles in the content directory.
Pelican supports content in multiple formats. Markdown and reStructuredText are supported out of the box, while other formats are supported via plugins. Thats right, Pelican supports plugins that you can use to change it's behaviour.
For this site, I am writing the contents in reStructuredText. I used this format while writing my book Test Driven Python Development and found it easy to use while also extensible.
Themes
Pelican comes with a bunch of available themes that you can use in your site, but for this website I decided to use the Spotlight theme from the Tailwind UI site. The theme on that site is built with NextJS, so I had to do some work to port it over to Pelican. I've been wanting to use Tailwind CSS for a while, so this was a good opportunity to try it out. The process was relatively painless, though it did take some time to rewrite the whole template to work with Jinja instead of React.
I was worried that Tailwind's utility class approach might conflict with the HTML generated by Pelican, but it turned out to not be a problem. Tailwind provides a 'prose' class that you can use to style the content without any further changes required.
Pelican integrates with Pygments to provide syntax highlighting out of the box. The only thing to do there was to generate the required CSS from a pygments theme and add it to the page.
Here is an example of syntax highlighting
import random
computer = random.choice(['rock', 'paper', 'scissors'])
user = input('Rock, Paper or Scissors? ').lower()
win_patterns = [('rock', 'scissors'), ('scissors', 'paper'), ('paper', 'rock')]
if computer == user:
print('Tie')
elif (computer, user) in win_patterns:
print('Computer wins')
elif (user, computer) in win_patterns:
print('User wins')
else:
print('Invalid input')
What about search and comments ?
One of the disadvantages of a static site is it makes things like search difficult because there is no backend to process the search. There are a couple of options here:
- Just use tags to make content easier to find. Most blog readers browse tags over searching anyway
- There are a few Peican plugins available that genenrate a search index at build time and store it so that a client side javascript script can read the index and do the search fully client side. This only works for small to medium sized sites
- For larger sites the best option is to offload search capabiility to a third party service. I've seen Algolia recommended often for this purpose
As for comments, once again there are similar options: live without comments, use a pelican plugin or offload to a third party service. Disqus is the obvious choice, but I've seen sites that integrate with Discourse and even Github discussions. Another option is to share the articles on the social media platform of your choice and have the discussions there.
One drawback with some of these options is that people will have to sign up for another service in order to comment, and the discussion is owned by another platform. For those who want to create a community around their content, a nice solution is to setup a Discord server and build the commutity there.
Deployment
A static site is the easiest it gets to deploy - just copy the html files over to the server of your choice. Recently there have been a number of JAMStack deployment hosts that make the process even simpler. They will take the latest version from source control and automatically deploy it to live.
This project seemed like a good time to give these services a try. After looking around at a few, I decided to try out Render. For one, hosting a static site is free 😎
Creating an account was a breeze. You can login with an existing Github, Gitlab or Google account, or create a new account. Then it's just a single cilick to add a new static site and point it to the repository. Render auto-detected the framework as Pelican and pre-filled all the configuration perfectly. Click save and your site is live.
I did eventually need to make a couple of tweaks to the process. Render uses Python 3.7 by default, but I wanted Python 3.11. Configuring this was just a matter of setting an environment variable.
I was also using pip-tools to create pinned dependencies for deployment, so I needed to slightly change the deployment command to install the pinned dependencies.
What's next?
Overall, I have been super happy with the process.
Now that the site is up and running, I need to start importing my old posts into here. Pelican provides an import system that looks like it will do the job.
There are also a bunch of pelican plugins that I need to add. And it looks like there are no plugins to embed social media content, so I need to look into that.
Finally, I need to update the theme to add in the Atom feeds, pagination support, archive pages and an About page. That's the roadmap as of now.