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:

  1. Generation: The generator had to be static, for maximum performance and easy publishing.

  2. Design: The generator had to let me make everything from scratch, for full customization.

  3. 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.

Link to this section 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.

Link to this section 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.

Link to this section 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.

Link to this section 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:

  1. I run hugo new path/to/example.md, which will create a new post with the current timestamp.

  2. 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.

  3. 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.

  4. Once I’m happy with my post, I stage and commit the file, then run git push.

  5. Cloudflare builds the site and pushes it to natclark.pages.dev. I have a CNAME 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.

Link to this section Analytics

I use Simple Analytics for lightweight, tracking-free analytics without having to worry about cookie banners, GDPR/CCPA/PECR, or data requests.

Link to this section 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:

  1. Creating quality content.

  2. Consistently creating quality content.

Link to this section 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.

Link to this section 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.

Link to this section 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.

Link to this section Sitemaps

Hugo automatically generates my sitemap, but I’ve changed the default sitemap template quite a bit.

Link to this section 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.

Link to this section Source control

I use a private GitHub repository for source control.

There are definitely advantages and disadvantages to open-sourcing your website.

Advantages:

Disadvantages:

Link to this section 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.