Introduction
Can you believe it? Except for the domain name, the setup of my personal website is completely free! After all, this is just a site where I plan to post casual articles, so I'll save money wherever I can. Let me explain how I built this website.
Framework Selection
Since I wanted it to be free, I couldn't choose an SSR (Server-Side Rendering) framework like WordPress, as deploying it to a host would cost money. Although some cloud platforms offer free tiers, increased traffic would inevitably incur costs. Therefore, choosing an SSG (Static Site Generation) framework and deploying it on a platform offering free static site hosting is more sensible.
My previous website used the Gatsby framework, for a simple reason: I am very familiar with React, so I thought customization would be easier. However, I later realized I didn't have time to maintain a bunch of Typescript and Javascript, which made me reluctant to update my website. This time, I choose Hugo. Maintaining a small amount of Go Template is easier, and I am familiar with Golang, too.
Theme Selection
Hugo's official website offers many themes to choose from. This time, I chose the hugo-PaperMod theme. Themes usually provide download steps, just follow them.
hugo new site personal-website --format yaml
cd personal-website
git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
git submodule update --init --recursive
Configuration
You'll have to follow the documentation provided by different themes to configure them to your liking. So in the following I only discuss some challenging configurations.
Multilingual
The theme I chose supports multiple languages, but some parts are not well translated. You'll need to look at the source code and find a solution, or search the issues to see if anyone has provided solutions. Luckily, I found some solutions:
Last Modified Time
Similarly, search the issues for solutions:
Chinese Fonts
Themes usually don't specifically set Chinese fonts, so Chinese characters look ugly. I often use web fonts to solve this, which is more convenient. Here, I use Google's Noto Sans Traditional Chinese font.
First, copy the font's embed code by clicking "Get fonts"
Then click "Get embed code"
Then click "copy code"
Next, find where to insert HTML tags in the theme's source code. After searching, I found this file. Create a file called layouts/partials/extend_head.html
and write the copied content into it.
Then, find where the CSS controlling the fonts is located. After searching, I found this line: https://github.com/adityatelange/hugo-PaperMod/blob/9ea3bb0e1f3aa06ed7715e73b5fabb36323f7267/assets/css/core/reset.css#L27.
Create a file called assets/css/extended/custom-font.css
and write the following content:
body:lang(zh-tw) {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", "Noto Sans TC", sans-serif;
}
Note that this part is directly copied from the original code, adding the selector body:lang(zh-tw)
to override the font style for Traditional Chinese. Since my articles mix Chinese and English, to avoid changing the English font, "Noto Sans TC" should be placed before the fallback font, which is before sans-serif
.
Comment System
Since our site is a static site, we need to rely on external services to provide a comment system. The most famous one is Disqus. However, its free plan forces use to show a lot of ADs to the users, which I don't like. So I chose giscus, which uses GitHub Discussions as the storage place for comments. The only downside is that it doesn't allow users to log in and comment with Google or social media accounts like Disqus does, but since my articles are mostly technical, people reading them are likely to have a GitHub account, so it's not a big issue.
It's a bit tricky to support multilingual and light/dark mode switching for this comment system, so I had to write some Javascript. Here's what it roughly looks like (sensitive information has been replaced):
<div id="giscus-script" />
<script>
let lang = document.documentElement.lang;
let category = "English Comments";
let categoryId = "<your-category-id>";
if (lang === "zh-tw") {
lang = "zh-TW";
category = "Traditional Chinese Comments";
categoryId = "<your-category-id>";
}
let theme = localStorage.getItem("pref-theme");
if (theme !== "light" && theme !== "dark") {
theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? "dark" : "light";
}
const giscusAttributes = {
"src": "https://giscus.app/client.js",
"data-repo": "<your-repo>",
"data-repo-id": "<your-repo-id>",
"data-category": category,
"data-category-id": categoryId,
"data-mapping": "pathname",
"data-strict": "1",
"data-reactions-enabled": "1",
"data-emit-metadata": "0",
"data-input-position": "top",
"data-theme": theme,
"data-lang": lang,
"data-loading": "lazy",
"crossorigin": "anonymous",
"async": "",
};
const giscusScript = document.createElement("script");
Object.entries(giscusAttributes).forEach(([key, value]) =>
giscusScript.setAttribute(key, value)
);
document.getElementById("giscus-script").appendChild(giscusScript);
function setGiscusTheme(theme) {
if (giscusScript) {
giscusScript.remove();
const newGiscusScript = document.createElement("script");
Object.entries(giscusAttributes).forEach(([key, value]) =>
newGiscusScript.setAttribute(key, value)
);
newGiscusScript.setAttribute('data-theme', theme); // Set the new theme
document.getElementById("giscus-script").appendChild(newGiscusScript);
}
}
function handleStorageChange() {
const theme = localStorage.getItem('pref-theme');
setGiscusTheme(theme);
}
window.addEventListener("storage", (event) => {
if (event.key === 'pref-theme') {
handleStorageChange();
}
});
// Override the localStorage setItem method to detect changes in the same browsing context
const originalSetItem = localStorage.setItem;
localStorage.setItem = function(key, value) {
originalSetItem.apply(this, arguments);
if (key === 'pref-theme') {
handleStorageChange();
}
};
</script>
Deployment
There are many platforms for Static Site Hosting, including GitHub Pages, Netlify, Cloudflare Pages, etc. I chose Cloudflare Pages for a simple reason: its free plan has the fewest restrictions. It even has no bandwidth limit!
Deployment is straightforward. Follow the official documentation, connect to the GitHub repo, and choose hugo
as the build command.
CMS
It's inconvenient to have to sit in front of a computer and open a text editor to write a blog post every time. A common solution is to use a CMS (Content Management System). I used to use Decap CMS (formally Netlify CMS), but it wasn't very convenient for connecting to a GitHub repo, and it didn't generate a blank line between YAML frontmatter and the body, which sometimes caused issues. So this time, I used Tina CMS. Fortunately, Tina Cloud is free for up to two users.
Setting up Tina CMS is not difficult. Follow the official setup instructions, then go to Cloudflare Pages and change the build command to git fetch --unshallow && npx --yes tinacms build && [ "$CF_PAGES_BRANCH" = "main" ] && hugo --minify || hugo -b $CF_PAGES_URL --minify
and add the environment variables. It will look like this:
SEO
Favicon
A Favicon is a small icon on a webpage. Without setting it, it appears as a globe in Chrome, which doesn't look good.
Go to Favicon Generator, upload an image, download the files, unzip them, and copy all the files into the static
folder. Then refer to the theme documentation to see how to set the favicon.
OpenGraph
OpenGraph is used to set images and descriptions when your website is shared on social media. You can use https://www.opengraph.xyz/ to check how your website will look when shared on social media.
Google Search Console
Submitting your site to Google Search Console can speed up indexing. Remember to submit the sitemaps (both XML and RSS sitemaps) to speed up indexing furthermore.
LightHouse
LightHouse can be used to measure website performance and SEO. First, open the website in incognito mode to avoid interference from Chrome extensions. Then press Ctrl+Shift+J
to enter Chrome Dev Tools, and select the LightHouse tab.
Select Desktop and click "Analyze page load".
Results:
Note: Google Web Font Performance Tuning
When using Lighthouse, you might notice a performance issue related to Google Web Fonts. In this case, you can use the
preload
method to solve it:<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@100..900&display=swap" rel="preload" as="font" crossorigin="anonymous">
Page Analytics
To analyze website data, such as the number of visitors, the most commonly used tool is Google Analytics, which is beyond the scope of this article, so it is not detailed here.
Conclusion
Deploying a website requires attention to many details. This article only briefly covers many topics, as different frameworks and themes require different configurations. Although you can't directly replicate a website by reading this article, I hope it helps you notice these details when deploying your personal website.
Top comments (0)