Build a Personal Website with Hugo
In this post, I will show you how to build a personal website with Hugo and configure the theme DoIt.
Quick Start
Install Hugo
In macOS, you can use Homebrew to install Hugo.
brew install hugo
Then add the theme DoIt as a submodule of the hugo project.
-
Create a new hugo project:
hugo new site my_website cd my_website
-
Initialize your project directory as a git repository, and add the theme repository as a submodule of your website directory:
git init git submodule add https://github.com/HEIGE-PCloud/DoIt.git themes/DoIt
-
Initialize the project:
git submodule update --init --recursive
, and finish the installation. -
Update the submodule:
git submodule update --remote --merge
. -
Create your first post!
hugo new posts/hello-world.md
. -
Preview your website:
hugo server --disableFastRender -D
.
.
├── archetypes # markdown templates
├── assets # assets used to generate the website
├── content # website content, mainly posts
├── data # data files used to generate the website
├── public # static files generated by hugo, mainly publish this
├── resources # resources generated by hugo, not sure what it is
├── static # static files, e.g. images, thumbnails, etc.
├── themes # hugo themes
└── hugo.toml # configuration file
-
hugo.toml
: The configuration of Hugo, including the configuration of the theme. See here for details. -
content
: Save the content of the website, such as posts.. └── content └── about | └── index.md // <- <https://example.com/about/> ├── posts | ├── firstpost.md // <- <https://example.com/posts/firstpost/> | ├── happy | | └── ness.md // <- <https://example.com/posts/happy/ness/> | └── secondpost.md // <- <https://example.com/posts/secondpost/> └── quote ├── first.md // <- <https://example.com/quote/first/> └── second.md // <- <https://example.com/quote/second/>
-
archetypes
: Save the markdown templates of the posts, usually including the front matter of the posts. -
static
: Save the static files used in the posts, these files will be copied to thepublic
folder when generating the website. -
public
: The static HTML, CSS, JS, etc. generated by thehugo
command. This folder is mainly published on the server.
Deploy
We can create two repositories on GitHub to deploy the website.
- Repository 1: A repository used to host the source files of the website project, set the permission to Private. We will spend most of our time on this repository.
- Repository 2: A repository used to host the static files generated by the website, set the permission to Public. The name of this repository should be
{{your_github_username}}.github.io
. For example, my GitHub username isfakephysicist
, then the name of the repository I need to create isfakephysicist.github.io
. In the settings of this repository, enable GitHub Pages, setBranch
tomain
, and set the static file location to/(root)
. We will directly push the contents of thepublic
folder generated by thehugo
command to the/
directory of themain
branch.
Create these two repositories on GitHub, and then follow the steps below to deploy the website.
-
In the
my_website
directory, executegit submodule update --init --recursive
to update the submodules to the latest state. -
In
hugo.toml
, setbaseurl = https://fakephysicist.github.io/
. -
Set the
fakephysicist.github.io
repository as a submodule and set it in thepublic
folder.git submodule add -f -b main <https://github.com/fakephysicist/fakephysicist.github.io.git> public
-
Generate the website, and push the generated website to repository 2.
hugo cd public git add . git commit -m "Build website" git push origin main cd ..
-
Add, commit and push repository 1.
git add . git commit -m "Publish website" git push -u origin master
Next time you want to update the website, just execute the following script deploy.sh
.
#!/bin/bash
set -e
# Optional: Custom commit message
commit_msg=${1:-"Update site"}
# Step 1: Ensure you're in the root of the Git repo
if [ ! -d ".git" ]; then
echo "❌ You must run this script from the root of the Git repository."
exit 1
fi
# Step 2: Update the submodule if it's not initialized
if [ ! -d "public/.git" ]; then
echo "➡️ Initializing submodule..."
git submodule update --init --recursive
fi
# Step 3: Pull latest from GitHub Pages branch (optional, but safe)
echo "🔄 Updating submodule content..."
cd public
git checkout main
git pull origin main
cd ..
# Step 4: Generate the site into public/
echo "🏗 Running Hugo to build the site..."
hugo
# Step 5: Commit & push changes in public submodule
cd public
git add .
if git diff --cached --quiet; then
echo "✅ No changes in public to commit."
else
git commit -m "$commit_msg"
git push origin main
echo "✅ Pushed updates to GitHub Pages repo."
fi
cd ..
# Step 6: Commit & push changes in main repo (content, config, etc.)
git add .
if git diff --cached --quiet; then
echo "✅ No changes in main repo to commit."
else
git commit -m "$commit_msg"
git push origin main
echo "✅ Pushed changes to main repository."
fi
echo "🚀 Deployment complete!"
If this script is saved in the root directory of the project, you can run it with the following command:
bash deploy.sh "<your commit message>"
Get current timestamp
date +'%Y-%m-%dT%H:%M:%S%z' | sed 's/\(..\)$/:\1/'
One can use the above command to get the current timestamp in the format of 2024-08-04T14:20:29-07:00
.
This timestamp can be used in the front matter of the posts.
date: 2021-01-01T02:43:06-05:00
lastmod: 2024-08-04T14:20:29-07:00