DEV Community

Vincent Liao
Vincent Liao

Posted on • Edited on

Create Your Own Hugo Theme From Scratch—With Snails

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

  1. cd to themes
  2. git clone https://github.com/vinliao/hugo-starter.git
  3. rm -rf hugo-starter/.git to remove git (so you can point to your own git remote)
  4. mv hugo-starter your-new-theme-name to rename
  5. cd ../.. and in config.toml, add themes = "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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

How does all these relate to each other?

  • 404.html is self-explanatory
  • nav.html, header.html, and footer.html is also self-explanatory
  • header.html contains nav.html
  • index.html contains header.html and footer.html. This is the thing that gets “served” when user visits yourwebsite.com
  • list.html contains header.html. This is the thing that gets served when user views yourwebsite.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)

Collapse
 
Sloan, the sloth mascot
Comment deleted