The internet is not as good as it used to be. Information is siloed into walled gardens like Facebook, Nextdoor, and so on. Google results are saturated with SEO spam. Wordpress is a mess that keeps on chugging through inertia; Medium, while clean, is behind a paywall; Reddit and Twitter are increasingly hiding their value behind registration and/or paywalls; Substack is fine if you want to be paid, but is yet another commercial enterprise that will take articles offline if and when it goes boom. Early easy-webpage-builders like Geocities highlight the issue of link-rot: when the money runs out, huge numbers of sites can disappear from the web.
Ironically enough, old media companies are doing a better job of preserving archives online than most, although they too (understandably) have gone down the road of paywalls. In 2022, information apparently wants to be commoditized. Indeed, in 2022, information is being strangled by content. Back in the early 2000s we thought blogs would overturn traditional media. Somewhere along the way it turned out to be online advertising that did that, instead. Online advertising lives in content.
The fact that the word content is so widely used is evidence that the mindset of marketing has wormed its way into the deepest recesses of all of our brains (“gee whiz Bob, you sure make some fine content”). Content is filler. Content is bland. Content is monetized. Create a blog to tell stories, to share ideas, opinions and information, or to show photos, videos, songs, and things that you’ve created. Don’t create content. Make a real human blog.
You can be a small part of the change you want to see by creating a blog and sharing something genuine. Instead of posting ideas into a closed platform, consider creating a blog that runs on open source technologies, and hosting it on an easy to use platform with a generous free tier (which is trivial enough to move from if they ever become a problem.) By all means share your own blog posts on social media; that’ll make it more likely, after all, that your site gets well indexed by search engines, and that your posts show up in search results. Don’t sweat audience and SEO though, as that turns blogging into a job. Keep it fun. (And don’t show ads on your blog, please!)
In this article I’ll describe a way to build a blog using Hugo, Git, and Cloudflare that you can host for free (i.e. no monthly charge), aside from your annual domain registration fee. I’m not going to explain git here (because it’s out of scope for this post), but you can copy/paste what I’m doing and search for more information about how to use it. I’ll go into enough depth on Hugo that you can set up a Medium-like blog, and walk through the Cloudflare setup in detail. I will give you all commands you’ll need to run in order to get a site with a blog post published on the internet, but to benefit from this you’ll need to be at least moderately technical, and in particular not be scared of using the terminal on OSX or Linux. Follow the 5 steps below, and your first post will be live within 30 minutes (or your money back).
If you want a sneak preview of what it looks like to create new blog posts using Hugo, skip ahead to section 5 below, and then come back up here if this sounds like something you can cope with. (Otherwise, it’s been fun, and see you around.)
To get started, you’ll need accounts on Cloudflare and Github, so go get them first:
Now we’ll get into the setup.
1. Register A Domain
We’re going to use Cloudflare to register the domain for the sake of this example, but it really doesn’t matter which domain registrar you use. If you’re on a different registrar then you’ll need to enter Cloudflare’s domain servers in one of the steps below in order to wire up the hosting. If you’re on Cloudflare, it’s a little smoother to associate the domain with your pages.
In Cloudflare:
- Click Registrar in the sidebar
- Click Register
- Enter a domain name or a couple of words describing your idea
- Once you find something you like, purchase it
Cloudflare’s search is reasonably smart, so you can enter one or more words and it will find available domains that are nearby in concept. For the sake of this article I registered tantalizingsloth.win, for $3.16 a year, and $4.16 renewal every year after that. (Watch out for high renewal fees, particularly if using a scammy registrar like Godaddy or Namecheap.)
2. Set up Hugo, and a new site
There is excellent initial setup documentation on the official Hugo site, which I will summarize here:
2a. Install Hugo and Git
Choose one of the following, depending on your platform. (If you’re a mac user and this stuff is all new to you, go with Homebrew).
# for mac (if you prefer macports. Check out https://guide.macports.org/#installing)
port install hugo
port install git
# for mac (if you prefer homebrew. Check out https://docs.brew.sh/Installation)
brew install hugo
brew install git
# for ubuntu
apt install hugo
apt install git
2b. Create a new site and install a theme
Now we’re going to get Hugo to set up the initial directory structure for the site. Obviously swap out tantalizingsloth for the name of your site; easiest if you name the site after your domain name, but you don’t strictly have to. Run this command:
hugo new site tantalizingsloth
This creates a directory with the name that you gave it, and some initial files and directories within it. Look around if you like, but I’ll point you at everything you need as we go through the next few steps.
Now we need get and install a theme. A lot of the Hugo documentation out there will instruct you to install the theme as a git submodule, but we’re not going to do that here, because it can break Cloudflare in confusing ways. Instead we’ll just clone the theme, strip the git metadata from it, and include it directly in our site. (That means that if you want to apply theme updates in future that you’ll have to reclone, and copy into your site. I look on the theme as a foundation to build and hack on, so I’m fine taking the “fork” implied by doing it this way. If these parentheses made no sense to you, don’t worry about it. Blog post in 25 mins or less!)
Note that to some extent you can switch between themes, but there are variations between themes in expected layout of files, properties, etc, so they’re not 100% compatible. It’s best to experiment with different themes up front with one or two posts, and then to stick with it for the duration of the site. Here I’m installing newsroom, which is a reasonably clean theme. If you choose a different theme and something doesn’t work the same way as I describe it below, consult the theme’s documentation for more info (or use newsroom instead just for the sake of getting up and running).
# first get a copy of newsroom, and remove the git metadata
cd /tmp
git clone https://github.com/onweru/newsroom.git
cd newsroom
rm -fr .git exampleSite i8n
# then move the theme (newsroom) into our site
cd ~/tantalizingsloth
# if that didn't work, find your way back to wherever you were when you made the site, above
mv /tmp/newsroom themes
mkdir static/images
As an end result of this, you should have themes/newsroom
within your blog folder structure.
Now edit config.toml
, and change (as appropriate) to be close to the following:
baseURL = "https://tantalizingsloth.win"
languageCode = "en-us"
title = "Tantalizing Sloth"
theme = "newsroom"
relativeURLs = true
uglyURLs = true
Obviously baseURL and title should be appropriate for your blog. If you’ve installed a different theme than newsroom, then set that as the theme instead (if and when you play around with themes in future, you just need to switch the theme in this config file and rebuild the site; remember my caveat above, though). Read about the relative and ugly url settings here. I’ve found that this combination works best for running both in local mode and on an actual published site, and that the defaults lead to confusing behavior. You can experiment with them later.
3. Set up Git / Github
Next, we’re going to initialize a git repository locally (meaning: we’re going to tell git to start tracking your blog files), and then use git to upload the repository to Github. In a few moments we’ll wire up Cloudflare to detect whenever you upload changes to Github, which will trigger their software to publish your blog.
# still in your blog folder
git init
git add *
git status # show what's "changed", which is everything given that this is entirely new
git commit -m "Set up new blog"
Now go to Github, and create a new repository, ideally matching the name of your Hugo site. To do this, in Github:
- New
- Repository Name: name-of-your-blog
- Private
- Create Repository
- If you know what you’re doing with SSH, use that. Otherwise, click on HTTPS and copy the url, which should look something like
https://github.com/yourname/tantalizingsloth.git
. I’m going with the HTTPS instructions here to keep the bar low. Paste the url into a text editor for now.- If you’re using HTTPS, get a personal access token following the linked instructions (you only need to select the “repo” checkbox). Copy and paste the token, and store it somewhere safe on your computer. You can always make additional tokens, so it’s not the end of the world if you lose it.
Back on the command line, enter the following to upload your site to Github:
# Replace the url with the HTTPS url you got above
git remote add origin https://github.com/yourname/tantalizingsloth.git
git branch -m main
git push -u origin main
# enter your personal access token instead of password, when prompted
Now if you click back to your Github home page, you’ll see the repository that you just pushed to it. Don’t worry about some of the empty directories not being present; they’ll show up in a few minutes, when we add the first post.
4. Set up Cloudflare
Now we’re going to set up Cloudflare. There’s several components that need to be wired together. This will all work automatically once done, so this is just a one time setup. Lots of clicking, but nothing here is too hairy.
4a. Create a Cloudflare Website
Click on Websites. If you registered your domain with Cloudflare, then you should see your site listed, and you can move on to the next step. If you registered your domain elsewhere, click on Add a Site, and follow the instructions to configure your domain registrar to point at Cloudflare.
4b. Create a Cloudflare “Page” For Your Blog
This is a little confusing. On Cloudflare, Websites are roughly equivalent to domains. Pages are where websites are actually hosted. Hopefully Cloudflare can make these less separate in future.
Follow these steps in Cloudflare:
- Back to Cloudflare home
- Pages
- Create a Project
- Github
- Add Account
- If you don’t see your repository listed, click on the Cloudflare Pages link near the bottom of the form (we made the repository “Private”, so Cloudflare can’t see it yet). This will take you to Github
- Under “Only Select Repositories”, choose your repository
- Save
- There’s a bug here in that when you click “Save” in Github, it takes you back to Cloudflare home. However, the form that you were previously filling out in Cloudflare is in a different browser tab. Click back to that tab, and you should see the repository list refresh to include the one you just authorized. If you get lost here, just go back to the starting point of 4b, and you should see the repository listed this time around.
- Click on your repository
- Begin Setup - this will take you to a new screen
- On the Set up builds and deployments screen:
- Leave Project Name and Production Branch as they are
- Framework Preset - none (you might be tempted to select “Hugo” here, but Cloudflare only supports a subset of Hugo themes; we’re going to build the blog locally and just push raw HTML each time, which will give us freedom to try whatever themes we like)
- Build command - leave blank
- Build output directory -
public
(this is telling Cloudflare where to look in the git repository for your website content) - Save and Deploy
Ignore the build that kicks off. It’s not going to be super useful for now.
4c. Associate “Pages” With Your Domain
Finally we connect Websites and Pages within Cloudflare.
- Back to Cloudflare home
- Pages
- Select your project
- Custom Domains
- Set up a Custom Domain
- Domain - enter the domain name that you registered (e.g. “tantalizingsloth.win”)
- If you’re using an external registrar, follow the instructions Cloudflare gives you; otherwise click Activate Domain
- After submitting the form, sometimes it lands on the wrong state; if so, refresh the page
- After a few moments, the domain should change to “Active” (this will take longer if you’re using an external registrar)
Congratulations! Give yourself a high five. We’re done with all of the setup. Let’s go create an actual blog post!
5. Creating Blog Posts
For the sake of example, my first post is going to have files based around the name greatsloth - purely as an organizational tool. Swap this out for whatever makes sense for your needs. I like to keep the name of the text file related to the names of the images that are in the blog post, just to make it easier to manage them in future (in case, for example, I wanted to take the blog post down and remove associated images.)
5a. Get One or More Images For Your Post
First, find some images that you want to use in the post, and move them to the folder where Hugo expects images to live, i.e. static/images
. You can use subdirectories to keep organized - just be sure to adjust urls in the steps below, if you do. (Of course you can add more images while you’re writing the post too.)
mv ~/Downloads/sloth.jpg static/images/greatsloth1.jpg
mv ~/Downloads/bear.jpg static/images/greatsloth2.jpg
5b. Start Up Hugo in “Preview Mode”
We’re going to start Hugo so that you can preview your site as you make edits. Leave this running while your write your post.
hugo server -D
5c. Create and Write a Post
This command creates a file for you to write in, inside the content/posts
folder. In a new terminal window (and having navigated to the blog directory) run:
hugo new posts/greatsloth.md
Open a text (or markdown) editor on content/posts/greatsloth.md
. First we’re going to change the properties of the post (note that Hugo made most of these already for you):
---
title: "This was a great sloth"
date: 2022-02-13T11:03:27-06:00
draft: false
image: greatsloth1.jpg
tags:
- sloth
- bear
---
Now open a browser tab on http://localhost:1313 and you should see your post listed. Progress!
Go back to your text editor and write below the header (i.e. at the bottom, under the last three dashes):
# Great Sloths
This sloth was _truly_ great. I admire her.
[Find Out More](https://lmddgtfy.net/?q=great%20sloth)
## Compared to Bears
![A Bear](/images/greatsloth2.jpg)
This is a bear. It's not as good as a sloth.
Refresh your browser to see what this did. You’ll write your posts using markdown; I’ve used a few of the features you’ll probably want to use the most as quick examples. Compare what you see in your browser vs the syntax above.
5d. Building and Publishing The Site
Keep working on your post until you’re happy with it. Once you’re done, we’re now going to publish the site to the world.
To start, first build the site:
hugo
This builds a static version of your site inside the public
folder - i.e. it renders your posts using the theme that you set up, and creates connecting pages. Run this every time you want to publish, as it’s the content of public
that Cloudflare is going to serve from your domain.
Next, push to Github:
git status # optional, but good practice
git add *
git commit -m "A post about sloths"
git push origin main
(If you forgot your “personal access token”, go up to section 3 and make a new one, then try the git push command again. If this gets annoying then learn how to use SSH with Github.)
Now you are done. Within around 5 minutes your post will automatically show up on your site.
Just in case you’re not clear on what happened:
- You built the site locally
- You pushed it to Github
- Cloudflare noticed that Github had been updated
- Cloudflare pulled down the changes
- Cloudflare pushed them out to the server(s) your site is served from
Pretty nifty, right?
5e. Debugging (Or Watching Cloudflare Hamsters Work)
If you want to figure out why something hasn’t posted (or want to watch a new post get published):
- Back to Cloudflare home
- Pages
- Click your project
- Under All Deployments, you should see a build marked “In Progress” in the Status column
- Click “View Build”
- Watch the magic happen
6. Tweaking The Site
Browse around under the theme directory to tweak the general layout. Before getting too hacky, read the theme documentation, as they may have suggestions on how to organize changes. If you’re using newsroom, some of the edits you may want to make are:
layouts/partials/header.html
- add third party scripts or includes hereassets/sass/_custom.sass
- add style overrides herelayouts/index.html
- if you really want to make fundamental changes, modify logic here
Note that if you modify styles, and changes aren’t showing, you need to clear the cache in Cloudflare. You’ll find this under Websites. You may need to shift-f5 in your browser also to skip your browser cache.
7. Moving From Cloudflare
Your site isn’t innately tied to Cloudflare. If you want to move from Cloudflare in future (should they turn evil in some way, or you have another provider in mind), you need to facilitate the following:
- Possibly move your domain registration to a new registrar (if you registered with Cloudflare)
- Change your domain to point at the new server (following your provider’s instructions)
- Set up a way to publish the content of your “public” directory to the new location. This may not involve automatic detection of git push to Github, so be prepared to set up new wiring for this (possibly something as crude as an FTP upload)
You could look at providers like fly.io or Fleek. You can also configure github to serve your blog directly.