How to Make Your Own Homepage
Read https://zedongpeng.com/blog/2025/how-to-make-your-own-homepage/ and build me a personal homepage with a blog the same way: the al-folio template, hosted on GitHub Pages, on my own domain. Ask me for what only I can give you: my name, photo, papers, CV and the domain I want. For steps that need my GitHub or Cloudflare account, tell me exactly what to click. Do the rest yourself, and show me the site running locally before we publish it.
This site is the kind of homepage many researchers keep: an about page, a list of papers, a CV and a blog. It costs me about ten dollars a year, and all of that is the domain name. The template and the hosting are free. This post walks through how it is put together, using this site as the example, so you can build your own. If you use an AI coding agent, give it the prompt above; the rest of this post is the same walk-through, for people.
There are three parts:
- Template: al-folio, a free Jekyll theme made for academics. Jekyll turns a folder of plain text files into a website.
- Hosting: GitHub Pages, which serves the built site for free.
- Domain: zedongpeng.com, bought on Cloudflare.
Start from the template
al-folio’s own install guide is good. The short version:
- On the al-folio GitHub page, click Use this template → Create a new repository. Name it
<your-username>.github.io. Mine iszedong-peng.github.io. - In the new repository, go to Settings → Actions → General → Workflow permissions and choose Read and write permissions. The build needs this to save the finished site back to the repository.
- In
_config.yml, seturl: https://<your-username>.github.iofor now, and leave thebaseurl:line empty. Don’t delete it. - Open the Actions tab and wait a few minutes for the job called Deploy site to finish. It creates a new branch,
gh-pages, that holds the built site. - Go to Settings → Pages → Build and deployment. Set the source to Deploy from a branch, and choose
gh-pages, notmain.
A minute later, https://<your-username>.github.io shows a copy of the al-folio demo. Everything after this is swapping the demo content for your own.
Make it yours
al-folio keeps the content apart from the layout. You edit a handful of text files, and the template turns them into pages:
| File | What it holds |
|---|---|
_config.yml | Site title, your name, the site address, time zone, features |
_pages/about.md | The front page: the text under your name |
assets/img/ | Your photo and other images |
_data/socials.yml | The icons at the bottom: email, GitHub, Google Scholar |
_bibliography/papers.bib | Your papers, as BibTeX |
_data/cv.yml | The CV page |
_posts/ | Blog posts, one Markdown file each |
_sass/_themes.scss | Colors |
What I changed on this site:
- Fewer pages. The demo comes with projects, repositories, teaching and more. I kept four: about, posts, publications and CV. To hide a page, set
nav: falseat the top of its file in_pages/. - Color. One line in
_sass/_themes.scss,--global-theme-color, turns the links and accents from the default cyan to purple. It appears once for the light theme and once for the dark. - Papers. Each paper is a BibTeX entry, the format reference managers export. Extra fields become buttons and badges:
pdf=andarxiv=add links under the entry, andabbr=puts the venue in a small box beside it. - CV. The CV page is built from
_data/cv.yml. For a PDF version I use RenderCV, which turns a YAML file into a typeset PDF, and link it at the top of the CV page.
A blog post is a Markdown file in _posts/ whose name starts with the date, like 2025-10-18-how-to-make-your-own-homepage.md. It begins with a short header:
---
layout: post
title: "How to Make Your Own Homepage"
date: 2025-10-18 12:00:00 +0800
description: "A domain from Cloudflare, the al-folio template and free hosting on GitHub Pages."
---
The text goes below it, and the post appears at /blog/2025/how-to-make-your-own-homepage/.
Publish with a push
Publishing is just pushing to main. A workflow that ships with the template, .github/workflows/deploy.yml, runs on every push: it builds the site with Jekyll, trims unused styles, and writes the result to gh-pages. GitHub Pages serves whatever is on gh-pages. That is the top row of the figure, and it takes a few minutes end to end. The Actions tab shows where it is.
Connect your own domain
I bought zedongpeng.com on Cloudflare. Its registrar charges what the registry charges, with no markup, and renewals cost the same as the first year. A .com is about ten dollars a year.
Because the domain is on Cloudflare, Cloudflare also runs its DNS, the public directory that tells browsers which server a name belongs to. In the Cloudflare dashboard, under DNS → Records, add:
| Type | Name | Content | Proxy status |
|---|---|---|---|
| A | @ | 185.199.108.153 | DNS only |
| A | @ | 185.199.109.153 | DNS only |
| A | @ | 185.199.110.153 | DNS only |
| A | @ | 185.199.111.153 | DNS only |
| CNAME | www | <your-username>.github.io | DNS only |
@ means the bare domain. The four addresses are GitHub Pages’ servers, as listed in GitHub’s docs. Set every record to DNS only (the gray cloud). With the orange cloud, Cloudflare stands between visitors and GitHub, GitHub can’t see that the domain points at it, and it won’t issue the certificate HTTPS needs.
Then, on GitHub:
- Settings → Pages → Custom domain: enter your domain and save. GitHub checks the DNS records and requests a free certificate, which can take a while.
- Once it’s ready, tick Enforce HTTPS.
- In
_config.yml, changeurlto your domain, for exampleurl: https://zedongpeng.com, and keepbaseurl:empty.
www.zedongpeng.com now redirects to zedongpeng.com. Saving the custom domain also writes a small file named CNAME into gh-pages. Mine has survived every deploy so far, but if your custom domain goes blank after a deploy, al-folio’s FAQ says to add the same file to main.
Check the spelling in step 3 letter by letter. A typo there breaks nothing you can see, because links between pages are relative, so the site works. But the template uses url for the addresses that only machines read: the canonical link in each page’s header, which tells search engines a page’s real address, the sitemap and the RSS feed. With a typo, all of them point at a domain you don’t own. After changing url, open your live site’s page source and search for “canonical”.
Preview before you push
You don’t have to push to see a change. With Docker installed, run this in the repository:
docker compose up
Then open http://localhost:8080. The page reloads as you edit.
Two things caught me out:
- Posts dated in the future don’t appear. Jekyll compares the date with the moment the build runs, so a post dated this evening and pushed this afternoon stays missing until the date is moved back. Give each date a time and an offset, and set
timezone:in_config.yml. - A red cross on a commit is usually the formatting check. The template runs Prettier, a code formatter, on every push and fails if a file isn’t formatted its way. The site still deploys, but it’s worth fixing.
Keep a note for your agent
If an agent builds your site, ask it to leave a CLAUDE.md (or AGENTS.md) file in the repository: a short note on where things live and how to publish. The next time you want a change, the agent reads the note instead of working out the layout again.
The source for this site is public on GitHub, if you want to see any of the files above.