Introduction
Today I spent about 8 hours building this blog from scratch. This post documents the complete process, including technology choices, pitfalls encountered, and their solutions. Hope this helps anyone looking to build their own blog.
Tech Stack Overview
Hugo - Static Site Generator
Hugo is a static site generator written in Go, marketed as “the world’s fastest static site generator.”
Pros:
- ⚡ Lightning-fast builds (thousands of pages per second)
- 🎨 Rich theme ecosystem (300+ official themes)
- 📝 Native Markdown support
- 🔧 Single binary deployment
Cons:
- Theme versions may be incompatible with Hugo versions
- Learning curve involved
GitHub - Code Hosting
GitHub hosts the blog source code with Git version control.
Functions:
- Code version management
- Markdown file storage
- Automatic deployment integration with Vercel
Vercel - Static Site Hosting
Vercel is a frontend deployment platform with excellent static site support.
Pros:
- 🚀 Automatic deployment (deploy on every push)
- 🌍 Global CDN acceleration
- 🆓 Free tier sufficient for personal blogs
- 🔒 Automatic HTTPS
Notes:
- Deployment Protection may be enabled by default (needs to be disabled for public access)
- Hugo version environment variable needs to be configured correctly
Cloudflare - DNS + CDN
Cloudflare provides DNS resolution and CDN acceleration.
Functions:
- Domain DNS management
- SSL/TLS certificates (automatic)
- DDoS protection
- Global CDN acceleration
Step-by-Step Setup
Step 1: Domain Purchase
I chose d5n.xyz - Duran (5 letters) + N.
Tips:
- 3-letter
.comdomains are mostly premium ($1000+) .xyzis cheap for the first year ($1-3), but check renewal prices- Cloudflare offers domain registration at cost (no markup)
Step 2: Initialize Hugo Site
hugo new site duranblog
cd duranblog
git init
git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
Configure hugo.toml:
baseURL = 'https://d5n.xyz'
languageCode = 'zh-CN'
title = 'D5N'
theme = 'PaperMod'
Step 3: Create GitHub Repository
- Repository name:
duranblog - Type: Public (Vercel free tier has no limits for public repos)
- Initialize with README
Step 4: Push Code to GitHub
Issue 1: Git Authentication Failure
Error:
fatal: could not read Username for 'https://github.com'
Solution: Use Personal Access Token authentication:
git remote set-url origin https://openduran:[email protected]/openduran/duranblog.git
Step 5: Vercel Deployment
Issue 2: Raw HTML Source Displayed
Symptom: Browser shows raw HTML code instead of rendered webpage.
Investigation:
- Checked GitHub repo, found
public/directory was committed - Vercel has auto-build; no need to commit built files
- Remove
public/and add.gitignore
Solution:
rm -rf public/
echo "public/" >> .gitignore
git add . && git commit -m "Remove public dir" && git push
Issue 3: Hugo Version Incompatibility
Error:
WARN Module "PaperMod" is not compatible with this Hugo version: Min 0.146.0
ERROR render of "/404" failed
Cause: Vercel’s default Hugo version is too old; PaperMod requires 0.146.0+
Solution: Add environment variable in Vercel project settings:
- Name:
HUGO_VERSION - Value:
0.146.5
Issue 4: Login Required (401 Error)
Symptom: Website shows “Vercel Authentication”
Solution:
- Go to Vercel project Settings → General
- Find “Deployment Protection”
- Change to “Disabled”
- Save and redeploy
Step 6: Configure Cloudflare DNS
Issue 5: SSL Handshake Failed (525 Error)
Error:
525: SSL handshake failed
Cause: Cloudflare SSL mode incompatible with Vercel
Solution:
- Go to Cloudflare → SSL/TLS → Overview
- Change mode from “Flexible” to “Full” or “Full (strict)”
Issue 6: Root Domain Not Accessible
Symptom: www.d5n.xyz works, but d5n.xyz doesn’t
Cause: Missing DNS record for root domain
Solution: Add in Cloudflare DNS:
- Type: CNAME
- Name:
@(or www) - Target:
cname.vercel-dns.com - Proxy: Orange ☁️ (Proxied)
Deployment Workflow
Local Development
↓
Hugo Build Test
↓
Git push to GitHub
↓
Vercel Auto-detect → Auto-deploy
↓
Cloudflare DNS Resolution
↓
User visits d5n.xyz
Key Configuration Summary
Hugo Version Control
Always specify Hugo version in Vercel environment variables:
HUGO_VERSION=0.146.5
Vercel Build Settings
- Build Command:
hugo --gc --minify - Output Directory:
public - Install Command: (leave blank or
yarn install)
Cloudflare SSL Settings
- Mode: Full or Full (strict)
- Don’t use: Flexible (causes 525 error)
Final Result
- Domain: https://d5n.xyz
- Source: https://github.com/openduran/duranblog
- Stack: Hugo + PaperMod + Vercel + Cloudflare
- Cost: $12/year for domain, everything else free
Lessons Learned
- Don’t commit public/ directory - Let Vercel build it
- Specify Hugo version - Avoid theme compatibility issues
- Disable Deployment Protection - Otherwise login is required
- Use Full SSL mode - Flexible causes handshake failures
- Complete DNS records - Both root and www subdomains need configuration
Next Steps
- Add Google Analytics
- Configure comments (Giscus/Utterances)
- Add RSS feed
- Optimize SEO (sitemap, robots.txt)
- Configure image CDN
Conclusion: Building a blog from scratch isn’t complicated—it’s mostly about troubleshooting. Once the automated deployment pipeline is set up, publishing posts is just a git push away. Hope this guide helps!