How I Built my Jamstack Blog With Hugo, Cloudflare, & Git
- 6 minutes read
I had been putting off creating a blog for years, but finally got around to it. Better late than never, right?
I knew I wanted a static Jamstack site for maximum performance.
A static site needs a generator (or headless CMS) to assemble the pages, sitemaps, and anything else.
And if you want to publish your static site, you’re going to need a network you can deploy it to.
Going into the process, I had requirements for each part of the stack:
-
Generation: The generator had to be static, for maximum performance and easy publishing.
-
Design: The generator had to let me make everything from scratch, for full customization.
-
Deployment: The deployer needed to have a robust and fast network with modern support for HTTP/3, QUIC, etc.
So I needed a smooth way to publish my posts and a flexible static site generator that would give me full control.
Here’s how it played out.
Generation
I picked Hugo for generating my site. All pages are built ahead of time, each time a change is pushed to the deployer.
Figuring out the weird parts of its templating engine and perfecting your configuration is a bit of a hassle, but it’s well worth the time.
Design
All of the HTML/CSS on this site is from scratch, but I use Hugo’s templates to offload the grunt work, such as automatically placing a footer at the bottom of every page.
I also use Autoprefixer and PostCSS for ensuring cross-browser style compatibility.
Currently, I’m not using any external or non-standard fonts, and I’ve set Segoe UI as the default.
Deployment
In terms of performance, Cloudflare Pages and their edge network dwarfs the competition by a landslide. So that’s what I went with.
I’m a simple git push
away from pushing the latest copy of my repository to Cloudflare, who will build my site using my Hugo configuration and serve it in about 3-4 minutes.
Maintenance
Once the templating, SEO adjustments, and other modifications have been tuned to your liking, writing posts is a walk in the park.
My publishing process looks like this:
-
I run
hugo new path/to/example.md
, which will create a new post with the current timestamp. -
I modify the post’s default front matter. I can add a description for SEO, include an affiliate link disclosure in the footer, add category tags, and things like that.
-
I write and edit the post in Markdown and custom HTML, which Hugo supports out of the box. For LaTeX support, I use a JavaScript library called KaTeX.
-
Once I’m happy with my post, I stage and commit the file, then run
git push
. -
Cloudflare builds the site and pushes it to
natclark.pages.dev
. I have aCNAME
record on this domain pointing to that Pages environment.
And that’s all for publishing! I can just focus on writing while my templates do all the heavy lifting in the background for me, and I can easily modify them if I need to.
Analytics
I use Simple Analytics for lightweight, tracking-free analytics without having to worry about cookie banners, GDPR/CCPA/PECR, or data requests.
SEO
I’ve optimized my meta tags, page structure, and semantic templates to help search engines better understand my pages.
I’ve begun to set up Schema.org structured data, which is a critical component of SEO. I use JSON-LD, because it has better support for Google’s rich results than RDFa.
Also, I am yet to start using something like Ahrefs for keyword research.
I haven’t done much with Microformats yet, either.
And I haven’t done much to improve my “domain authority” either. This website is pretty new as of writing this sentence, and I’m just focused on two things:
-
Creating quality content.
-
Consistently creating quality content.
Security
This website is heavily reliant on Cloudflare.
Not only am I using Cloudflare Pages to build and deploy this site, but I’m also using Cloudflare Workers to inject my Content Security Policy, detect spam, and things like that.
For what it’s worth, I’m also using DNSSEC, HSTS, a web application firewall, and other similar basic measures. Not that you can cover all your bases these days anyway.
Accessibility
I do my accessibility from scratch. I’ve made changes like adding “skip navigation” links to the top of each page and disabling animations for browsers that request reduced motion.
I also use my own product, Page Speaker, for detecting errors and WCAG violations that I need to fix.
RSS/Atom
Hugo generates my feeds for me. I have a primary feed for all posts, and six smaller feeds - for each of the six categories on this site.
I’m currently only offering RSS feeds, but will get around to adding Atom feeds.
Sitemaps
Hugo automatically generates my sitemap, but I’ve changed the default sitemap template quite a bit.
Preview images
When someone shares a page from your site on another site, such as a social media platform, it’s important to provide a preview image.
Most sites use the
Open Graph Protocol, but some use the <link rel="image_src">
tag or
Twitter Cards. I support all three.
Currently, I’m using Slickr to generate my preview images, but I might switch to Bannerbear.
Source control
I use a private GitHub repository for source control.
There are definitely advantages and disadvantages to open-sourcing your website.
Advantages:
-
If your theme is popular, you’ll get lots visibility and stars on your repository.
-
People might submit PRs to translate some of your pages for you (this is actually quite common).
Disadvantages:
-
The more hard work you put into building a quality theme, the more people will be likely to blatantly copy it.
-
Dealing with
bug reportssupport tickets and reviewing PRs is time-consuming and exhausting.
Conclusion
Well, that’s how I built (and maintain) my blog! When people ask me, this is the post I’ll link to them.
I’ll also try and remember to keep this up-to-date, as things will be moving around over time.