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.

Install Hugo

In macOS, you can use Homebrew to install Hugo.

1
brew install hugo

Then add the theme DoIt as a submodule of the hugo project.

  1. Create a new hugo project:

    1
    2
    
    hugo new site my_website
    cd my_website
    
  2. Initialize your project directory as a git repository, and add the theme repository as a submodule of your website directory:

    1
    2
    
    git init
    git submodule add https://github.com/HEIGE-PCloud/DoIt.git themes/DoIt
    
  3. Initialize the project: git submodule update --init --recursive, and finish the installation.

  4. Update the submodule: git submodule update --remote --merge.

  5. Create your first post! hugo new posts/hello-world.md.

  6. Preview your website: hugo server --disableFastRender -D.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.
├── 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.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    .
    └── 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 the public folder when generating the website.

  • public: The static HTML, CSS, JS, etc. generated by the hugo command. This folder is mainly published on the server.

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 is fakephysicist, then the name of the repository I need to create is fakephysicist.github.io. In the settings of this repository, enable GitHub Pages, set Branch to main, and set the static file location to /(root). We will directly push the contents of the public folder generated by the hugo command to the / directory of the main branch.

Create these two repositories on GitHub, and then follow the steps below to deploy the website.

  1. In the my_website directory, execute git submodule update --init --recursive to update the submodules to the latest state.

  2. In hugo.toml, set baseurl = https://fakephysicist.github.io/.

  3. Set the fakephysicist.github.io repository as a submodule and set it in the public folder.

    1
    
    git submodule add -f -b main <https://github.com/fakephysicist/fakephysicist.github.io.git> public
    
  4. Make sure the public folder is deleted. Make fakephysicist.github.io repository as a submodule, and set it in the public folder.

    1
    
    git submodule add -f -b main https://github.com/fakephysicist/fakephysicist.github.io.git public
    
  5. Generate the website, and push the generated website to repository 2.

    1
    2
    3
    4
    5
    6
    7
    
    hugo
    cd public
    git add .
    git commit -m "Build website"
    git push origin main
    cd ..
    rm -rf public
    
  6. Add, commit and push repository 1.

    1
    2
    3
    
    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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/bash

# Ensure we exit on any error
set -e

# Function to check current directory is the root of the repository
check_root_dir() {
    if [ ! -d ".git" ]; then
        echo "Error: The script needs to be run from the root of the repository."
        exit 1
    fi
}

# Step 1: Update submodules
check_root_dir
git submodule update --init --recursive

# Step 2: Ensure public folder is deleted and add the submodule repository
if [ -d "public" ]; then
    rm -rf public
fi
git submodule add -f -b main git@github.com:fakephysicist/fakephysicist.github.io.git public


# Step 3: Generate the website and push it to the submodule repository
hugo
cd public
git add .
git commit -m "Build website"
git push origin main
cd ..
rm -rf public

# Step 4: Add, commit and push the main repository
git add .
git commit -m "Update website"
git push -u origin master

echo "Deployment completed successfully!"
1
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.

1
2
date: 2021-01-01T02:43:06-05:00
lastmod: 2024-08-04T14:20:29-07:00