Okay, you’ve tried hugo. It’s nice, it’s fast; it’s what the cool kids use. You shuffle from theme to theme and found nothing you like for your beloved blog.
What do you do?
That’s where I was in a month ago, and I created my own hugo theme from scratch. In this post, I’ll outline everything I did.
Prerequisite
Here’s what you need to know before proceeding.
- HTML and templating engine (e.g., Jinja, handlebars, liquid, etc)
- little bit of hugo
- terminal (
cd
,rm
, etc)
Alright, let’s dive straight to it.
Create a new hugo site for the “shell”
This is the one confusion that has wasted hours of my life.
The theme you create must live inside a hugo site. Think of a snail—the theme is the slimy part, and the thing for testing your theme is the shell part.
This is how it looks like in “trees.”
.
└── site (shell of snail)
├── blahblahblah
├── content
└── themes
└── your-theme (the slimy part)
Time to create
In the directory of your choice, run hugo new site your-site-name
The directory will look like this
.
├── archetypes
│ └── default.md
├── config.toml
├── content
├── data
├── layouts
├── static
└── themes
Notice the themes
folder? Yeah, those are the folders we’re going to mess with.
What you have to do now is to create a new theme in that folder. You can do that with hugo new theme your-theme-name
, but for me, that’s too barebones. Here’s what I did to get up and running ASAP.
- cd to
themes
git clone https://github.com/vinliao/hugo-starter.git
-
rm -rf hugo-starter/.git
to remove git (so you can point to your own git remote) -
mv hugo-starter your-new-theme-name
to rename -
cd ../..
and in config.toml, addthemes = "your-new-theme-name"
Now it looks—more or less—like this.
.
├── archetypes
│ └── default.md
├── config.toml
├── content
├── data
├── layouts
├── resources
│ └── _gen
│ ├── assets
│ └── images
├── static
└── themes
└── your-new-theme-name
├── archetypes
│ └── default.md
├── exampleSite
│ └── config.toml
├── layouts
│ ├── 404.html
│ ├── _default
│ │ ├── list.html
│ │ └── single.html
│ ├── index.html
│ └── partials
│ ├── footer.html
│ ├── header.html
│ └── nav.html
├── README.md
└── static
└── css
└── style.css
Now cd
to the root of this site—read: the “shell” of the snail—and run hugo serve -D
. (The -D arg is for showing drafts).
Boom. It’s working... but it’s empty. To fill the emptiness, you can use the hugo new your-post-name.md
command.
Try it out—run hugo new about.md
, then hugo serve -D
, and go to localhost:1313/about
.
Theme details
I won’t get into the nitty gritty, but I’ll just explain the very basics of hugo templating engine—ELI5 fashion.
If you go to your theme folder—the slimy part of the snail—here’s what you’ll see.
.
├── archetypes
│ └── default.md
├── exampleSite
│ └── config.toml
├── layouts
│ ├── 404.html
│ ├── _default
│ │ ├── list.html
│ │ └── single.html
│ ├── index.html
│ └── partials
│ ├── footer.html
│ ├── header.html
│ └── nav.html
├── README.md
└── static
└── css
└── style.css
The most important folder is the layouts folder. At this stage, you can pretty much ignore everything else. Let’s zoom in there, shall we?
.
├── 404.html
├── _default
│ ├── list.html
│ └── single.html
├── index.html
└── partials
├── footer.html
├── header.html
└── nav.html
How does all these relate to each other?
-
404.html
is self-explanatory -
nav.html
,header.html
, andfooter.html
is also self-explanatory -
header.html
containsnav.html
-
index.html
containsheader.html
andfooter.html
. This is the thing that gets “served” when user visitsyourwebsite.com
-
list.html
containsheader.html
. This is the thing that gets served when user viewsyourwebsite.com/posts
-
single.html
serves individual post
(Another way to see this: list.html
is like the list of things that gets shown to you when you first open Hacker News; single.html
is for HN comments.)
Here’s something that caught me offguard about all these files: the header.html
and footer.html
are, in the end, combined into one file. If you look at header.html
, you notice that there’s an opening tag for <main>, and <body>
, but no closing tag. Ding, ding, ding—the closing tag is on footer.html
.
This structure is not a straitjacket rule. The theme I created (https://github.com/vinliao/mita) doesn’t adhere to this structure. In my theme, I want the list of post to show when user visits vinliao.com
instead of having to go to vinliao.com/posts
. I ended up changing the index.html
to show lists of post instead.
Now that you understand, you can do whatever you want with your theme.
Git
If you want to share this theme, share the slimy part, not the whole snail.
This means you must git init
in the your-theme-name
folder.
Conclusion
This is not an in-depth post in any way, but at least, you can now fiddle with your theme.
Happy hacking, people of the internet!
Top comments (1)