How to Create a Website with Hugo Academic Theme: Blog Setup

Getting your blog setup right.

Academic logo

Academic is one of the most popular Hugo themes for good reason. It’s flexible, clean, and easy to use and set up. It supports many widgets and allows you to display a wide range of content types, including biographies, accomplishments, experiences, projects, posts, talks, and publications (it is called Academic after all). However, while it’s able to handle all of them adequately, it does lack some desirable features and characteristics that a dedicated blog theme might provide. This post outlines the changes I made, and how, to improve the theme’s ability to function as a blog.

Rename section from “post” to “blog”

One thing that may have bugged you, I know it did me, is that everything is called “post” instead of “blog”, especially for the URL. I wanted it to be eliaszwang.com/blog instead of eliaszwang.com/post. I know it may seem like a small detail, but I cared enough to figure out how to change it. And now I’ll show you how too.

Website repo changes

Starting off with the easy changes, you’ll need to change the name in the menus. So in config/_default/menus.toml replace the two lines with,

name = "Blog"
url = "#blog"

If you want the menu to take you directly to the section page for your posts you can use url = "/blog" instead. Next, rename the post subdirectory in the content folder to blog and change the title in the front matter of content/blog/_index.md to “Blog”, or whatever you want to name your blog. Also rename content/home/posts.md to content/home/blog.md. In that file you’ll also need to change the page_type from “post” to “blog”. Some important notes:

  1. The name of the *.md file in content/home determines the HTML id attribute on the homepage, i.e. the anchor link used in the menu. See layouts/partials/widget_page.html in the theme repo.
  2. The page_type determines the folder name in the content directory where content (e.g. single posts) is pulled from. See layouts/partials/widgets/pages.html.

Subdomain redirect

At this stage, you can also set up subdomain redirects through Netlify to make your blog accessible from a subdomain, e.g. blog.domain.com. Just add the following lines to the netlify.toml file, replacing domain.com with your own domain:

[[redirects]]
  from = "https://blog.domain.com"
  to = "/blog"
  status = 200
  force = true
  
[[redirects]]
  from = "https://blog.domain.com/blog/*"
  to = "/blog/:splat"
  status = 200
  force = true

[[redirects]]
  from = "https://blog.domain.com/css/*"
  to = "/css/:splat"
  status = 200
  force = true

The last redirect rule for the css subdirectory ensures that the pages on the new subdomain will be formatted correctly without any addtional changes. The final thing to do is add the subdomain as a domain alias in Netlify under “Domain settings>Custom domains”. To fully understand how these redirect rules work take a look at the documentation on general redirects, proxy redirects, and splats.

Summary of changes in the website repo:

  • In config/_default/menus.toml change name to “Blog” and url to “#blog” or “/blog”
  • Rename content/post to content/blog, and change title in content/blog/_index.md to “Blog”
  • Rename content/home/posts.md to content/home/blog.md, and change page_type to “blog”
  • Change redirects accordingly in netlify.toml

Theme repo changes

This part is pretty short. Start by renaming two files: layouts/post/single.html to layouts/blog/single.htmland layouts/section/post.html to layouts/section/blog.html. This mostly just reflects the renaming that you did earlier in the website repo. Finally, there are a couple of changes in the layout files. In layouts/partials/widgets/pages.html (i.e. the pages widget) in the two lines where $items_type and "post" appear change “post” to blog. The new lines should look something like,

...
{{ $items_type := $st.Params.content.page_type | default "blog" }}
...
{{ if eq $items_type "blog" }}
...

Also in layouts/partials/page_metadata.html change the $page.Type check (near the end of the file) from “post to “blog”,

...
{{ if and (eq $page.Type "blog") (not (or (eq site.Params.reading_time false) (eq $page.Params.reading_time false))) }}
...

This will ensure that the estimated reading time for posts continues to be displayed, if you have it enabled in params.toml. For some more information about content types in Hugo take a look here.

Summary of changes in the theme repo:

  • Rename layouts/post/single.html to layouts/blog/single.html
  • Rename layouts/section/post.html to layouts/section/blog.html
  • In layouts/partials/widgets/pages.html change page_type/$items_type processing from “post” to “blog”
  • In layouts/partials/page_metadata.html change $page.Type check from “post to “blog”

Change subdirectory to submodule

Another useful thing to do is setting up your content/blog subdirectory into a git submodule. The benefit of doing this is that you can still use git for version control of your posts while keeping them in a private repo, even if your website repo is public. If you’re not familar with git submodules, check out my other post that explains more.

Splitting a subdirectory into a new repo

In case you’ve already added some posts and want to keep the git history, it’s pretty easy to do with just a few git commands. Just follow the steps outlined in the GitHub docs here. Once you have this new repo set up with just your blog posts it’s time to add it as a submodule to the original repo. First delete the original content/blog folder, then replace it with a submodule by running the following command in the root directory: git submodule add https://github.com/USERNAME/REPOSITORY-NAME.git content/blog (this assumes you renamed post to blog, if not use content/post as the path). Note: If you are planning to keep the blog repo private you’ll need to use ssh instead of https: git submodule add git@github.com:USERNAME/REPOSITORY-NAME.git content/blog and follow the additional steps in “Configure Netlify for private submodules”. After adding the submodule run git submodule update --init to finish the setup.

Configure Netlify for private submodules

Netlify provides nice documentation for setting up deploy keys when using private repos here. In short, you’ll first need to go to the Netlify site and generate a public key by going to Settings > Build & deploy > Continuous deployment > Deploy key, and select Generate public key. Copy this public key. Next you’ll go to the GitHub page for you blog repo and go to Settings > Deploy keys, and select Add deploy key and paste the public key you copied from Netlify (no need to give it write access). This should now give Netlify read access to the private repo and will allow it to build your site.

Elias Z. Wang
Elias Z. Wang
AI Researcher | PhD Candidate