If you want a personal blog that is fast, beautiful, and completely free β no ads, quick loading, and a full-featured comment system (emoji, reactions, anonymous commenting…) β this combo is the perfect choice in 2026:
- Hugo (a blazing-fast static site generator)
- Stack Theme (modern, minimalist design with a gorgeous dark mode)
- GitHub Pages (free hosting)
- Waline (open-source comment system, self-hosted on Vercel + Neon Postgres, supports anonymous comments that appear instantly)
Prerequisites
- A GitHub account (public repo)
- A Vercel account (free, sign in with GitHub)
- A Neon account (free, serverless Postgres)
- A machine with Git + Hugo installed (extended version recommended)
Step 1: Clone the Hugo Stack Template and Set Up the Basic Site
Go to the official starter repo:
https://github.com/CaiJimmy/hugo-theme-stack-starterClick Use this template β Create a new repository
- Name your repo:
- For a root domain:
username.github.io(e.g., pngocthach.github.io) - For a subpath: any name (e.g., my-blog) β your domain will be
username.github.io/my-blog
- For a root domain:
- Name your repo:
Clone the repo to your machine:
git clone https://github.com/username/username.github.io.git cd username.github.ioInstall Hugo if you haven’t already:
- macOS:
brew install hugo - Windows: use Scoop/Chocolatey or download the extended binary from https://github.com/gohugoio/hugo/releases
- Linux (varies by distro):
sudo apt install hugo(or extended)
Verify:
hugo version(should be β₯ 0.120)- macOS:
Run the site locally:
hugo serverOpen http://localhost:1313 β if you see the Stack demo page, you’re good to go.
Deploy to GitHub Pages:
- Go to your repo’s Settings β Pages
- Source: Deploy from a branch β Branch: main β Folder: / (root) β Save
- The template already includes a GitHub Actions workflow (
.github/workflows/hugo.yml), so every push will automatically trigger a build.
Your site will be live within 1β3 minutes at https://username.github.io (or
/my-blog)
Step 2: Set Up the Waline Comment Backend (Vercel + Neon Postgres)
Waline is a lightweight, open-source comment system that supports anonymous commenting and beautiful emoji/reactions.
Deploy Waline on Vercel (free):
- Visit: https://waline.js.org/en/guide/deploy/vercel.html
- Click the Deploy button (blue)
- Sign in to Vercel with GitHub β Name your project (e.g.,
my-waline-backend) β Create - Wait for deployment (1β2 minutes) β Copy your backend URL: https://my-waline-backend.vercel.app
Create a Neon Postgres database (free tier):
- In Vercel Dashboard β Storage tab β Create Database β Select Neon
- Region: Singapore (aws-ap-southeast-1) (lowest latency from Southeast Asia)
- Create the DB β Open in Neon console
- In the Neon SQL Editor β Paste the init script from:
https://github.com/walinejs/waline/blob/main/assets/waline.pgsql
β Run to create the tables
Connect Neon to Vercel:
- In Vercel β Storage β Select the Neon DB you just created β Connect
- Check all Environments: Development, Preview, Production
- Check Preview for branching (uncheck Production if not needed)
- Custom Prefix: Leave blank
- Connect β Vercel will automatically inject the environment variables
Create the admin account:
- Visit: https://my-waline-backend.vercel.app/ui/register
- Register the first user β this account becomes the admin
- Log in at
/uito manage comments later (e.g., review spam)
Step 3: Integrate Waline into Hugo Stack
Edit the config file (
config/_default/params.toml):[comments] enabled = true provider = "waline" [comments.waline] serverURL = "https://waline-backend-iota.vercel.app" # Replace with your Vercel URL lang = "en" reaction = true emoji = [ "https://unpkg.com/@waline/emojis@1.0.1/tw-emoji", "https://unpkg.com/@waline/emojis@1.0.1/weibo" ]Override the template to display full URLs (easier to manage in the admin panel):
During deployment, you may notice that Waline stores comments using only the relative path (e.g.,
/p/post-name) instead of the full URL (https://yourdomain.com/p/post-name), making it very hard to identify which post a comment belongs to.To fix this, create the file:
layouts/partials/comments/provider/waline.htmlto override the theme’s default.File content:
| |
- Using
.Permalinkwill automatically include the full URL (with domain), so the Waline admin panel displays comments ashttps://yourblog.com/p/post-name/instead of a relative path β making them much easier to identify.
Step 4: Writing New Posts and Updating Your Blog
Once the scaffolding is set up, writing new posts is incredibly simple:
Create a new post: Open a terminal and run:
hugo new content post/your-post-title/index.mdThis creates a new folder inside
content/post/along with anindex.mdfile β this is where you’ll write your post content.Write your content: Open the newly created
index.md. You’ll see a section at the top (between+++) called the Front Matter β this is where metadata like title, date, description, and cover image goes. Everything below is your post content, written in standard Markdown.Preview locally: Run
hugo serverto see how your post looks before publishing.Publish (This is all it takes): When you’re happy with your post, run these 3 basic Git commands:
git add . git commit -m "Add new post: Your Post Title" git push origin mainAs soon as you push, GitHub Actions will handle everything else. Within about a minute, your new post will appear live on your blog!
Conclusion
- Total cost: $0 (the free tiers of GitHub Pages, Vercel, and Neon are more than sufficient for a personal blog).
- Advantages: A full-featured comment system with anonymous support, instant display, emoji, and reactions.
- Automation: Once the setup is done, your only job is to write in Markdown and push to GitHub. GitHub Actions takes care of building and deploying β your post goes live automatically.
- Drawback: If you experience a sudden traffic spike, you may need to upgrade your Neon/Vercel plan β but this is extremely rare for a personal blog.
In just a few simple steps and at zero cost, you have a sleek, professional blog to write on freely. Now it’s just a matter of making time to publish! Thanks for reading, and see you in the next post. If you run into any issues or have questions, feel free to leave a comment below!
References
Hugo Theme Stack Starter Template (official repo to clone and get started quickly):
https://github.com/CaiJimmy/hugo-theme-stack-starterHugo Theme Stack Official Documentation (comments config, Waline, and general customization):
https://stack.jimmycai.com/
Comments section: https://stack.jimmycai.com/config/commentsHugo Official Guide: Host and Deploy on GitHub Pages (deployment with GitHub Actions):
https://gohugo.io/host-and-deploy/host-on-github-pages/Waline Official Documentation (Vercel deployment, client config, ecosystem):
https://waline.js.org/en/
Deploy on Vercel: https://waline.js.org/en/guide/deploy/vercel.html
Client config (path, lang, reaction): https://waline.js.org/en/reference/client/props.htmlNeon Docs: Integrate with Vercel (connecting Neon Postgres with Vercel, env vars, branching):
https://neon.com/docs/guides/vercel-overviewSource code of this blog (for a real-world reference):
https://github.com/pngocthach/pngocthach.github.io