Featured image of post From Zero to Hero: Building Your Personal Website with Hugo

From Zero to Hero: Building Your Personal Website with Hugo

一起来用世界上最快的网站构建框架搭建个人博客站点吧!

This article will introduce the method of setting up Hugo locally and deploying it via GitHub Pages and Vercel. The approach described below is the one I used to deploy this very site, which can serve as a useful reference. If you encounter errors or other difficulties during the deployment process, you can search online or leave a comment—I will provide assistance to the best of my ability when I see it.


Prerequisites for Deploying Hugo:

  1. Install Git: Git is used for version control and code management. Git comes pre-installed on Linux and macOS systems, while Windows users need to install it manually. Download it from: https://git-scm.com/. During installation, no additional options are required—just keep clicking “Next.”
  2. Have a GitHub account: This is for hosting your code files. Register at: https://github.com/login.
  3. Use a suitable text editor: Recommended options include Visual Studio Code, Sublime Text, or any editor of your choice.
  4. Ensure a stable internet connection: To avoid errors while downloading files or uploading them to GitHub, it is advisable to use a reliable network environment.

If you’ve completed these preparations, congratulations! You’re ready to proceed to the next step.

Download and Install Hugo

On Hugo’s Release page, locate the latest version of Hugo and download the appropriate package for your system. Download
Alternatively, you can follow the installation instructions on Hugo’s official website.

Create a Site

Place the downloaded files in an empty folder. In the address bar of the folder, type cmd to open the command line. Then, enter the command hugo new site your-site-name to create the site. Create Site
Create Site

Next, enter cd your-site-name to navigate into the directory. Copy hugo.exe into this folder to avoid configuring environment variables. #

Run the command hugo server in the current directory to start the local site (press Ctrl + C to stop the service). The address is usually localhost:1313. If the page displays “Page not found,” it means all previous configurations were correct.

Configuring the Theme

Hugo does not come with a default theme, so you need to download one from the official website. The theme I use is Stack, created by Jimmy Cai. The following steps will use this theme as an example.

After downloading the theme, extract it into the themes folder. Then, copy the content folder and hugo.yaml from the exampleSite folder to the main directory. Delete the original hugo.toml and Content/post/rich-content to avoid compatibility issues. (The name “春树暮云” in the image is the title of this blog.)
Configuring Theme 1
Configuring Theme 2

Modify the theme option in hugo.yaml to match the name of the theme folder.
Modifying hugo.yaml

Run hugo server again in the command line. If you see a style similar to the image below, it means the previous steps were successful.
#
#

Enter the relevant configurations in config.yaml. The explanations for each configuration item are as follows, for reference:

  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
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
baseurl: https://example.com  # The base URL of the website. Replace it with your own domain.  
languageCode: en-us  # The default language code of the website. "zh-cn" refers to Simplified Chinese.  
themehugo-theme-stack # The Hugo theme used here is the Stack theme.  
paginate: 3 # The number of items displayed per page, typically used for pagination settings.  
title: Example Site # The title of the website, displayed in the browser tab.  
copyright: Example Person # The copyright information of the website, usually displayed at the bottom of the page.  

# Theme i18n support  
# Available values: ar, bn, ca, de, el, en, es, fr, hu, id, it, ja, ko, nl, pt-br, th, uk, zh-cn, zh-hk, zh-tw  
DefaultContentLanguage: en # Sets the default content language for the website. See available options in the comment above.  

# Set hasCJKLanguage to true if DefaultContentLanguage is in [zh-cn ja ko]  
# This will make .Summary and .WordCount behave correctly for CJK languages.  
hasCJKLanguage: false # If the default language is Chinese, Japanese, or Korean, set this to true to ensure proper summary and word count behavior.  

languages:  
    en:  
        languageName: English # English language configuration  
        title: Example Site # English site title  
        weight: 1 # Language weight; lower values appear first in sorting  
        params:  
            description: Example description # English site description  
    zh-cn:  
        languageName: 中文 # Chinese language configuration  
        title: 演示站点 # Chinese site title  
        weight: 2 # Chinese site language weight  
        params:  
            description: 演示说明 # Chinese site description  
    ar:  
        languageName: عربي # Arabic language configuration  
        languag```markdown
direction: rtl  # Text direction, right-to-left
        title: Demo Site  # Arabic site title
        weight: 3  # Arabic site language weight
        params:
            description: Demo Description  # Arabic site description

services:
    # Change it to your Disqus shortname before using
    disqus:
        shortname: "hugo-theme-stack"  # Disqus comment system shortname; replace with your own Disqus shortname.
    # GA Tracking ID
    googleAnalytics:
        id:  # Google Analytics tracking ID for website traffic statistics.

permalinks:
    post: /p/:slug/  # Permanent link format for blog posts, using the post's slug as the path.
    page: /:slug/  # Permanent link format for pages.

params:
    mainSections:
        - post  # Main content section, displaying article content.
    featuredImageField: image  # Name of the featured image field.
    rssFullContent: true  # Whether the RSS feed includes full content.
    favicon: # e.g.: favicon placed in `static/favicon.ico` of your site folder, then set this field to `/favicon.ico` (`/` is necessary)
        # Path to the website's favicon, e.g., `/favicon.ico`.

    footer:
        since: 2020  # Year the website was created, typically displayed in the footer.
        customText:  # Custom footer text.

    dateFormat:
        published: Jan 02, 2006  # Published date format.
        lastUpdated: J  # Last updated date format (incomplete in original).
```an 02, 2006 15:04 MST  # Last updated date format.

    sidebar:
        emoji: 🍥  # Emoji displayed next to the sidebar title.
        subtitle: Lorem ipsum dolor sit amet, consectetur adipiscing elit.  # Subtitle of the sidebar.
        avatar:
            enabled: true  # Whether to enable avatar display.
            local: true  # Whether to use a local avatar.
            src: img/avatar.png  # Path to the avatar image.

    article:
        math: false  # Whether to support math formula rendering.
        toc: true  # Whether to display the table of contents.
        readingTime: true  # Whether to show estimated reading time.
        license:
            enabled: true  # Whether to enable article copyright information.
            default: Licensed under CC BY-NC-SA 4.0  # Default license agreement.

    comments:
        enabled: true  # Whether to enable the comment feature.
        provider: disqus  # Selected comment provider, default is Disqus.

        disqusjs:
            shortname:  # DisqusJS shortname.
            apiUrl:  # DisqusJS API URL.
            apiKey:  # DisqusJS API Key.
            admin:  # DisqusJS admin username.
            adminLabel:  # DisqusJS admin label.

        utterances:
            repo:  # GitHub repository address for Utterances comment system.
            issueTerm: pathname  # Utterances comment system issue term.The issue association method uses the page path.  
            label:  # Label for the Utterances comment system.  

        beaudar:  
            repo:  # GitHub repository address for the Beaudar comment system.  
            issueTerm: pathname  # Issue association method for the Beaudar comment system.  
            label:  # Label for the Beaudar comment system.  
            theme:  # Theme for the Beaudar comment system.  

        remark42:  
            host:  # Host address for Remark42.  
            site:  # Site identifier for Remark42.  
            locale:  # Language setting for Remark42.  

        vssue:  
            platform:  # Platform used by Vssue (e.g., GitHub).  
            owner:  # Owner of the Vssue comment repository.  
            repo:  # GitHub repository address for Vssue comments.  
            clientId:  # OAuth app Client ID for Vssue.  
            clientSecret:  # OAuth app Client Secret for Vssue.  
            autoCreateIssue: false  # Whether to automatically create a comment issue.  

        waline:  
            serverURL:  # Server URL for the Waline comment system.  
            lang:  # Language setting for Waline.  
            pageview:  # Whether to enable page view statistics.  
            emoji:  # Emoji package address for Waline.  
                - https://unpkg.com/@waline/emojis@1.0.1/weibo  
            requiredMeta:  
                - name  # Required metadata when commenting.Fields to be filled in:  
- username  # Field required for comments, username.  
- email  # Field required for comments, email address.  
- url  # Field required for comments, website URL.  

locale:  
- admin: Admin  # Administrator name for the Waline comment system.  
- placeholder:  # Placeholder text for the Waline comment box.  

twikoo:  
- envId:  # Environment ID for the Twikoo comment system.  
- region:  # Deployment region for the Twikoo comment system.  
- path:  # Path for the Twikoo comment system.  
- lang:  # Language setting for the Twikoo comment system.  

cactus:  
- defaultHomeserverUrl: "https://matrix.cactus.chat:8448"  # Default homeserver URL for Cactus.Chat.  
- serverName: "cactus.chat"  # Server name for Cactus.Chat.  
- siteName: "" # You must insert a unique identifier here matching the one you registered (See https://cactus.chat/docs/getting-started/quick-start/#register-your-site)  
# Site name for Cactus.Chat, must match the registered identifier.  

giscus:  
- repo:  # GitHub repository address for the Giscus comment system.  
- repoID:  # Unique identifier for the Giscus repository.  
- category:  # Category name for Giscus.  
- categoryID:  # Unique identifier for the Giscus category.  
- mapping:# Giscus Issue Association Method  
            lightTheme:  # Giscus light theme settings  
            darkTheme:  # Giscus dark theme settings  
            reactionsEnabled: 1  # Whether to enable Giscus reactions  
            emitMetadata: 0  # Whether to enable Giscus metadata emission  

        gitalk:  
            owner:  # Repository owner for Gitalk comment system  
            admin:  # Administrator username for Gitalk comment system  
            repo:  # GitHub repository address for Gitalk comments  
            clientID:  # OAuth application Client ID for Gitalk  
            clientSecret:  # OAuth application Client Secret for Gitalk  

        cusdis:  
            host:  # Host address for Cusdis comment system  
            id:  # Site identifier for Cusdis  

    widgets:  
        homepage:  
            - type: search  # Homepage widget: search functionality  
            - type: archives  # Homepage widget: article archives  
              params:  
                  limit: 5  # Number of archived articles to display  
            - type: categories  # Homepage widget: article categories  
              params:  
                  limit: 10  # Number of categories to display  
            - type: tag-cloud  # Homepage widget: tag cloud  
              params:  
                  limit: 10  # Number of tags to display  
        page:  
            - type: toc  #The widget on the page displays the table of contents for the article.

    opengraph:
        twitter:
            # Your Twitter username
            site:  # Your Twitter username, which will be used in OpenGraph metadata.
            # Available values: summary, summary_large_image
            card: summary_large_image  # Type of Twitter card. Options include `summary` or `summary_large_image`, with the latter displaying a large image.

    defaultImage:
        opengraph:
            enabled: false  # Whether to enable a default OpenGraph image for pages without a featured image.
            local: false  # Whether to use a local image as the OpenGraph image.
            src:  # Path to the default OpenGraph image.

    colorScheme:
        # Display toggle
        toggle: true  # Whether to show the color mode toggle button on the page.

        # Available values: auto, light, dark
        default: auto  # Default color mode. Options include auto-switching (auto), or fixed to light (light) or dark (dark).

    imageProcessing:
        cover:
            enabled: true  # Whether to enable automatic processing for cover images, such as cropping and scaling.
        content:
            enabled: true  # Whether to enable automatic processing for content images.

### Custom menu
### See https://stack.jimmycai.com/config/menu
### To remove about, archive, and search page menu items, remove the `menu` field fromtheir FrontMatter  
menu:  
    main: []  # Custom configuration for the main menu, where navigation links can be added.  

    social:  
        - identifier: GitHub  # Identifier for the social link, typically used to specify the icon.  
          name: GitHub  # Display name of the link.  
          url: https://GitHub.com/CaiJimmy/hugo-theme-stack  # Link to the GitHub profile.  
          params:  
              icon: brand-GitHub  # Social icon used, in this case, the GitHub icon.  

        - identifier: twitter  # Another social link configuration, here for Twitter.  
          name: Twitter  # Display name for the Twitter link.  
          url: https://twitter.com  # Link to Twitter.  
          params:  
              icon: brand-twitter  # Social icon used, in this case, the Twitter icon.  

related:  
    includeNewer: true  # Whether to include newer articles in related posts.  
    threshold: 60  # Similarity threshold for matching related articles, ranging from 0 to 100.  
    toLower: false  # Whether to convert tags and categories to lowercase.  
    indices:  
        - name: tags  # Use tags as the basis for matching related articles.  
          weight: 100  # Weight value for tag matching.  
        - name: categories  # Use categories as the basis for matching related articles.  
          weight: 200  # Weight value for category matching.  

markup:  
    goldmark:  
        renderer:  
            ## Set to true if you have HTML content inside Markdown  
            unsafe: true  # If MarkdoThe `wn` contains HTML content, set to `true` to allow rendering this HTML.

    tableOfContents:
        endLevel: 4  # The maximum heading level for table of contents generation.
        ordered: true  # Whether to use ordered lists for table of contents items.
        startLevel: 2  # The starting heading level for table of contents generation.

    highlight:
        noClasses: false  # Whether to disable CSS class names for syntax highlighting.
        codeFences: true  # Whether to enable syntax highlighting for code blocks.
        guessSyntax: true  # Whether to automatically guess the language for syntax highlighting in code blocks.
        lineNoStart: 1  # The starting value for line numbers in code blocks.
        lineNos: true  # Whether to display line numbers in code blocks.
        lineNumbersInTable: true  # Whether to display line numbers in a table format.
        tabWidth: 4  # The width of tabs in code blocks (in spaces).

For more configuration options, refer to the official website, such as website font settings, custom headers or footers, etc.

Writing Articles

Create a new folder under your-site-name/content/post, then create an index.md file within that folder to represent a new article.

You can also create a new article by opening the your-site-name page and using the command line with the following command:
hugo new content post/new-article-title/index.md
#

Afterward, use VS Code or another editor to write the article in Markdown.

At the top of every article generated using the Hugo command, there is a section enclosed by +++ or ---. This is officially called “Front Matter,” which specifies various attributes of the article. Below is a snippet of Front Matter extracted from an example article in the Stack theme, along with annotations:

 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
+++
author = "Hugo Authors"  # Author name, used forTitle: Markdown Syntax Guide  
Date: 2019-03-11  
Description: Sample article showcasing basic Markdown syntax and formatting for HTML elements.  
Tags: ["markdown", "css", "html", "themes"]  
Categories: ["themes", "syntax"]  
Series: ["Themes Guide"]  
Aliases: ["migrate-from-jekyl"]  
Image: "pawel-czerwinski-8uZPynIu-rQ-unsplash.jpg"  

Hugo comes with an auto-generated Front Matter template, but in reality, Hugo supports far more Front Matter fields than the default template provides. Below are some commonly used fields and their purposes. You can either mimic the original template for writing or edit the `default.md` file in the `archetypes` folder to customize a new Front Matter template. When using the `hugo new` command to create a new article, Hugo will automatically generate Front Matter based on the template in the `archetypes` directory.  

#### Common Front Matter Fields Explained  
- `title`: Article title. The auto-generated title matches the filename.  
- `date`: Article creation date. The default date is the file creation date.  
- `lastmod`: Last modification date of the article.  
- `description`: Brief description of the article, used for summaries or SEO optimization.### Front Matter in Hugo Blog Posts

When writing a blog post in Hugo, the content is typically divided into two parts: **Front Matter** and the **main body**. Front Matter is written in YAML, TOML, or JSON format and is placed at the beginning of the file, enclosed between `---` (for YAML) or `+++` (for TOML). The main body is written in Markdown.  

For example, here’s a simple Front Matter example in YAML format:  

```yaml
---
title: "My First Blog Post"
date: 2023-10-01T12:00:00+08:00
categories: ["Tech"]
tags: ["Hugo", "Blogging"]
draft: false
---

Common Front Matter Attributes

  • title: The title of the article.
  • date: The publication date of the article.
  • lastmod: The last modification date of the article.
  • categories: The categories under which the article falls.
  • tags: The tags associated with the article.
  • image: The cover image for the article.
  • draft: Whether the article is a draft. If set to true, Hugo will not compile the file, and the article will not appear on the site.
  • hidden: Whether the article is hidden. Unlike draft, a hidden article still exists but is not displayed on the site, though it can be accessed via its direct URL.

Not all Front Matter attributes need to be present in every article. As long as the default attributes are included, the article usually won’t encounter issues.

The methods for writing pages and editing categories and tags are largely similar, so they won’t be elaborated here.

Deploying the Blog

Once the blog content is written, the next step is deployment.

Hugo’s official documentation provides a deployment guide. Given the minimal size of static pages, I don’t recommend hosting them on a dedicated cloud server. Instead, platforms like Vercel, Cloudflare Pages, GitHub Pages, GitLab Pages, or Netlify are better choices. Due to space constraints, I’ll only cover deployment to GitHub Pages and Vercel.

Before deploying, I researched Hugo blogs hosted on various platforms and conducted speed tests. Ignoring differences between themes, the results were as follows:

Hosting Platform Fastest/Slowest Time in China Fastest/Slowest Time Overseas Average Time (China/Overseas)
GitHub Pages Inner Mongolia Unicom 0.304s / Hubei Wuhan Telecom 10.136s Frankfurt, Germany 0.018s / South Africa 2.978s 1.829s / 0.541s
Vercel Taiwan, China 0.355s (Mainland: Zhejiang Hangzhou Mobile 0.140s) / Heilongjiang Harbin Telecom 3.088s Ashburn, USA 0.050s / Los Angeles, USA 1.602s 0.865s / 0.526s
Cloudflare Pages Taiwan, China 0.147s (Mainland: Shanghai Mobile 0.436s) / Guizhou Guiyang Mobile 11.199s Ashburn, USA 0.109s / Singapore 2.133s 1.400s / 0.429s

From the results, Vercel offers the best performance for users in mainland China, while Cloudflare Pages performs better overseas. GitHub Pages has the slowest average loading time in China. Therefore, if your audience is primarily in mainland China, Vercel is the recommended choice.

Therefore, I recommend deploying on GitHub Pages first, then using Vercel to deploy the source files and bind a custom domain.

As for why GitHub Pages instead of just any GitHub repository, it’s because most online methods, including the official documentation, are based on GitHub Pages.

However, GitHub Pages blocks Baidu from crawling web pages, which is not SEO-friendly. So it’s advisable to also deploy the GitHub repository to Vercel.

Deploy to GitHub Pages

Create a new GitHub repository named yourusername.GitHub.io and set the visibility to public.

Go to Settings > Pages > Branch, select the main branch, and save.

In your local blog folder, run the hugo command. This will generate a public folder, which contains all the static resources of your blog and will be uploaded to the GitHub repository.
#

Next, run the following commands to push the repository to GitHub Pages (if it’s your first upload, it’s recommended to enter your account credentials beforehand to avoid confusion later—see below for how):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
cd public/  # Enter the public folder  

git init  # Initialize the current folder (i.e., the public folder) as a local git repository  

git remote add origin git@GitHub.com:username/username.GitHub.io  
# Link to the remote repository.  
# The remote repository address (git@GitHub.com:username/username.GitHub.io)  
# You can also go to the GitHub repository -> Code -> SSH to copy the remote repository address  

git add .  # Add all files in the current folder to the staging area  

git commit -m "My first commit"  # Commit the changes with a message  

git push -u origin main  # Push to the remote repository (main branch)  

If this is your first time using Git, you may need to configure your username and email:

1
2
git config --global user.name "Your Name"  
git config --global user.email "youremail@example.com"  

After completing these steps, wait a few minutes, and your blog should be accessible at https://yourusername.GitHub.io.

Deploy to Vercel

To improve SEO and avoid GitHub Pages’ restrictions, you can deploy the same repository to Vercel.

  1. Sign in to Vercel with your GitHub account.
  2. Click New Project, select your username.GitHub.io repository, and follow the prompts to deploy.
  3. During deployment, Vercel will ask you to configure a domain. If you have a custom domain, enter it here.

Once deployed, your blog will be accessible via both https://yourusername.GitHub.io and your custom domain (if configured).

This approach combines the reliability of GitHub Pages with the flexibility and SEO benefits of Vercel.```markdown commit" # Commit relevant files to the local repository

git push origin main # Push the relevant files to the main branch of the remote repository

1
2
3
4
5
6

Before pushing code for the first time, you need to perform the following configuration. Afterward, Git will automatically request to associate with your GitHub account.

```bash
git config --global user.name "Your GitHub Username"
git config --global user.email "The email you used to register for GitHub"

I recommend enabling a global proxy when pushing to the repository, otherwise, GitHub may occasionally disconnect, which is very annoying!

An alternative to SSH is to download GitHub Desktop and upload your code through the client.

When pushing files, errors are common. I suggest carefully reading the error message to identify the cause. If you’re unsure, you can ask ChatGPT. Most of the errors I’ve encountered were resolved with GPT’s help—it patiently points out my mistakes and provides detailed solutions.

Once the upload is successful and the deployment is complete, you can visit https://{username}.GitHub.io/ to verify everything is correct before proceeding to the next step.

Deploy to Vercel and Bind a Domain

You need to own a domain name to deploy to Vercel. The subdomains assigned by Vercel are inaccessible in mainland China.

Go to the Vercel website and log in. It’s recommended to log in via GitHub for easier association with your GitHub repository.

Click “Add New” and then “Project.” Under “Import Git Repository,” find the repository you uploaded to GitHub. Click “Import.” Keep all options in “Configure Project” as default and click “Deploy.” Wait about ten seconds for the deployment to complete, and a celebratory page will appear.

Just like this: Welcome Page

Then, get straight to the point and click “Add Domain” on the right. Navigate to the “Domain” page. # Enter your domain in the search box, select the appropriate option, and click “Add.” Follow the instructions to add the required DNS records.After waiting for Vercel to verify and automatically configure the SSL certificate, the site will be accessible.

There’s a commonly overlooked point here: projects deployed on Vercel enforce HTTPS by default. If you also enforce HTTPS on Cloudflare or another platform, it will result in too many redirects when accessing the site, leading to the “ERR_TOO_MANY_REDIRECTS” error. My solution is to disable the relevant settings on Cloudflare. If a subdomain needs to enforce HTTPS, it can be achieved via the .htaccess file.

(Optional) GitHub Action for Auto-Deployment

Without auto-deployment, your blog will still function normally. However, every time you update the blog, you’ll need to do so on a computer with the environment already set up, manually compile Hugo, and push the Public folder to the GitHub repository. If you want to streamline the entire writing and publishing process, consider setting up auto-deployment.

Create a new repository on GitHub, preferably with “Private” permissions. This repository will be used to store Hugo’s source files, meaning all the folders and files under your blog’s root directory. As shown in the image below, I named my repository “Hugo.”
Create Repository

Go to your repository’s Settings/Developer Settings/Personal access tokens, then click “Generate new token (classic)” to create a token.
Create Token

Set the “Expiration” for the token (customizable) and make sure to select the “repo” and “workflow” options below.

Next, navigate to your repository’s Settings/Secrets and variables/Actions and save the generated token as a repository secret.
Environment Variables

Return to your local blog folder (e.g., your-blog-name), create a .github folder inside it, then a workflows folder within .github, and finally a deploy.yaml file inside workflows. Copy the following code into it:In the file:

 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
name: deploy

# Trigger GitHub Action when code is pushed to the main branch
on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
        - name: Checkout
          uses: actions/checkout@v4
          with:
              fetch-depth: 0

        - name: Setup Hugo
          uses: peaceiris/actions-hugo@v3
          with:
              hugo-version: "latest"
              extended: true

        - name: Build Web
          run: hugo -D

        - name: Deploy Web
          uses: peaceiris/actions-gh-pages@v4
          with:
              PERSONAL_TOKEN: ${{ secrets.YOUR_TOKEN_VARIABLE_NAME }}
              EXTERNAL_REPOSITORY: username/repository-name
              PUBLISH_BRANCH: main
              PUBLISH_DIR: ./public
              commit_message: auto deploy

Create a .gitignore file in the “your-blog-name” folder to exclude unnecessary files or folders from being committed. Add the following content:

1
2
3
4
public
resources
.hugo_build.lock
hugo.exe

Upload the Hugo source files to the repository:

1
2
3
4
5
6
7
git init
git add .
git commit -m "comment"
git branch -m main
git remote add origin git@github.com:username/repository-name.git
```Username/RepositoryName.git  
git -u push origin main  

After submitting, go to the “Actions” page to check the deployment status. The image below shows the status before I published this post.
Deployment Status

End

If everything goes smoothly, you can happily enjoy your personal blog! Of course, after deployment, you can further customize the theme, configure the comment section, and tackle a series of other intricate tasks. However, tinkering around isn’t meaningless—perhaps the very act of building a blog is the meaning itself.

Licensed under CC BY-NC-SA 4.0