I wanted a blog that was fast, free to host, and didn’t require me to manage a server. This post is a step-by-step account of how I built exactly that — using Hugo to generate the site and Cloudflare Pages to serve it.

No prior experience needed. If you can use a terminal and have a GitHub account, you can follow along.


First, understand what you’re building

Before touching any tools, it helps to understand what’s actually happening.

A traditional website works like this: a visitor requests a page → your server runs code → generates HTML → sends it back. Every request triggers computation.

A static site flips this: you generate all the HTML once on your own machine, then upload the result. When a visitor arrives, Cloudflare just hands them a pre-built file. No server, no database, no computation at request time. This makes it extremely fast and essentially free to host.

Hugo is the tool that generates those HTML files from your content. You write posts in plain Markdown, run one command, and Hugo produces a complete website. Cloudflare Pages is the free hosting layer — it serves your files from data centers around the world so your site loads fast for everyone.


What you’ll need

  • A terminal (Terminal on Mac, any shell on Linux, WSL on Windows)
  • Git installed
  • A GitHub account
  • A Cloudflare account (free tier is enough)
  • About 30 minutes

Step 1 — Install Hugo

Hugo is a single binary. Install it with your package manager:

Mac:

brew install hugo

Linux:

sudo snap install hugo

Windows:

winget install Hugo.Hugo.Extended

Verify it worked:

hugo version

You should see something like hugo v0.162.1+extended. The extended variant is important — some themes require it for SCSS processing.


Step 2 — Create a new site

hugo new site my-blog
cd my-blog
git init

This creates a folder with Hugo’s expected structure:

my-blog/
├── content/       ← your posts go here
├── static/        ← images, fonts, files
├── layouts/       ← HTML templates (usually from a theme)
├── archetypes/    ← templates for new content
└── hugo.toml      ← site configuration

You don’t need to touch most of this yet.


Step 3 — Add a theme

Hugo sites are unstyled by default. Themes provide the look and the layout templates. I used PaperMod — it’s minimal, fast, and well-maintained.

Hugo can pull themes as Go modules, which is cleaner than copying files into your repo:

hugo mod init github.com/your-username/my-blog

Then open hugo.toml and add:

[module]
  [[module.imports]]
    path = "github.com/adityatelange/hugo-PaperMod"

Pull the theme:

hugo mod tidy

Step 4 — Configure your site

Replace the contents of hugo.toml with a basic config:

baseURL = 'https://your-site.pages.dev/'
title   = 'Your Name'
paginate = 10

[module]
  [[module.imports]]
    path = "github.com/adityatelange/hugo-PaperMod"

[params]
  ShowReadingTime     = true
  ShowPostNavLinks    = true
  ShowBreadCrumbs     = true
  ShowCodeCopyButtons = true
  ShowToc             = true

[[menus.main]]
  name   = "Blog"
  url    = "/blog"
  weight = 10

Change baseURL to match your Cloudflare Pages domain (you’ll get this in Step 7 — you can come back and update it).


Step 5 — Write your first post

hugo new blog/my-first-post.md

This creates content/blog/my-first-post.md with front matter already filled in:

---
title: "My First Post"
date: 2026-06-05
draft: true
---

Write your post here in plain Markdown.

When draft: true, Hugo won’t publish it. Change it to false when you’re ready.

Write your post in Markdown. Hugo supports all standard Markdown syntax — headings with #, bold with **text**, code blocks with triple backticks, links with [text](url).

Preview it locally:

hugo server -D

The -D flag includes draft posts. Open http://localhost:1313 in your browser. Hugo watches for file changes and reloads automatically.


Step 6 — Push to GitHub

Cloudflare Pages deploys from a Git repository, so you need your site on GitHub.

Create a .gitignore to exclude the generated output:

public/
resources/
.hugo_build.lock

Create a new repository on GitHub (call it my-blog), then:

git add .
git commit -m "Initial commit"
git remote add origin https://github.com/your-username/my-blog.git
git push -u origin main

Step 7 — Deploy on Cloudflare Pages

  1. Log in to Cloudflare Dashboard
  2. Go to Workers & PagesCreatePages
  3. Click Connect to Git and authorize GitHub
  4. Select your my-blog repository
  5. Under Build settings, set:
    • Build command: hugo mod tidy && hugo --minify
    • Build output directory: public
  6. Click Save and Deploy

Cloudflare clones your repo, runs the build command, and publishes the public/ folder. Your site gets a free *.pages.dev subdomain.

Now go back to hugo.toml and update baseURL to your new domain, commit, and push. Cloudflare will redeploy automatically on every push to main.


How it all fits together

Here’s the full picture:

You write Markdown
       ↓
Hugo converts it to HTML (build step, runs on Cloudflare)
       ↓
Cloudflare stores the HTML files
       ↓
Visitor requests your site
       ↓
Cloudflare serves the pre-built file from the nearest data center

There is no server running your code. There is no database. Cloudflare is essentially a very fast, globally distributed file server — and the free tier is generous enough that a personal blog will never hit any limits.


What’s next

A few things worth exploring once your site is live:

  • Custom domain — Cloudflare makes this straightforward if your domain is also managed there
  • Analytics — Cloudflare Web Analytics is free and privacy-friendly, no JavaScript tracking required
  • Open Graph images — add a social preview image so your posts look good when shared on Twitter/LinkedIn
  • Commentsgiscus uses GitHub Discussions as a comment backend, no database needed

The best part of this setup: once it’s running, publishing a new post is just writing a Markdown file and pushing to GitHub. Everything else is automatic.