Tinyblog Theme for Hugo

Posted: Oct 30, 2023

Tags: hugo theme minimal
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupéry

Tinyblog is a hyper minimalist theme for Hugo. You can download it here. If you want to see what it looks like, you’re looking at it. This blog uses Tinyblog with the default theme settings.

Table of Contents

  1. Overview
  2. Design Goals
  3. A Note on Accessibility
  4. Installation
    1. Customization
    2. Front Matter
    3. Deeper Customization
  5. Todo
  6. License

Overview

I really like the Hugo site generator. It’s fast, and doesn’t have a bunch of bloated server-side dependencies. It also supports themes, giving you complete control over the generated content. I was using the Minimal theme by Calin Tataru, and while I really like the style (which I’ve more or less kept for this theme,) I found it was over kill for my purposes: it uses jQuery, Bootstrap, web fonts, and has optional integrations for a bunch of cloud services. I wanted to see how small of a theme I could make without compromising on the features I wanted. Tinyblog is the result.

What I started out with was something that generated around 25 separate assets totaling around 720k (compressed) in size for a page where the main content was less than 40k.

This page, as generated by this theme today, requires 75k (compressed) to load using 10 assets:

Pages with fewer images and less complicated markup (the syntax highlighting in particular is verbose) are even smaller. For instance, the home page of this site is 6.5k (compressed,) although granted, it only has two small icon-like images and a bit of text.

Design Goals

A note on accessibility

I tried – to the best of my ability – to encourage an accessible design with the defaults for this theme. Alas, I am not an expert in such matters. If you are an expert, or if you personally find some aspect of this design to hinder accessibility, please let me know!. I’ll do my best to fix it.

Installation

  1. If you haven’t already, install Hugo.
  2. Create an empty site:
marcusb@dom:~$ hugo new site testsite
Congratulations! Your new Hugo site was created in /home/marcusb/testsite.

Just a few more steps...

1. Change the current directory to /home/marcusb/testsite.
2. Create or install a theme:
   - Create a new theme with the command "hugo new theme <THEMENAME>"
   - Install a theme from https://themes.gohugo.io/
3. Edit hugo.toml, setting the "theme" property to the theme name.
4. Create new content with the command "hugo new content <SECTIONNAME>/<FILENAME>.<FORMAT>".
5. Start the embedded web server with the command "hugo server --buildDrafts".

See documentation at https://gohugo.io/.
marcusb@dom:~$
  1. Initialize the Hugo module system:
marcusb@dom:~$ cd testsite
marcusb@dom:testsite$ hugo mod init github.com/marcus0x62/testsite
go: creating new go.mod: module github.com/marcus0x62/testsite
go: to add module requirements and sums:
        go mod tidy
marcusb@dom:testsite$
  1. Edit the ‘hugo.toml’ file in your site directory and add the Tinyblog module(s) or just replace it with this file:
baseURL = 'https://example.com/'
languageCode = 'en-us'
title = 'Tinyblog Example Site'
markup.highlight.noClasses=false

[module]
[[module.imports]]
        path = 'github.com/marcus0x62/tinyblog'
[[module.imports]]
        path = 'github.com/marcus0x62/tinycomments'
[[module.imports]]
        path = 'github.com/marcus0x62/tinyimages'

[params]
    author = "Marcus Butler"
    licenseText = "Tinyblog is licensed under the MIT License"
    licenseLink = "https://marcusb.org/hacks/MIT-LICENSE.txt"
    #accentColor = "grey"
    #textColor = "black"
    #backgroundColor = "#fefbea"
    #navbarBackgroundColor = "#ffffea"
    #navbarBorderTop = "2px"
    #navbarBorderBottom = "1px"
    #navbarIconSize = "16px"
    #itemsPerPage = "5"

[[menu.main]]
    url = "/"
    name = "Home"
    weight = 1

[[menu.main]]
    url = "/posts/"
    name = "Posts"
    weight = 2

[[menu.main]]
    url = "/projects/"
    name = "Projects"
    weight = 3

#[[menu.icon]]
#    url = "/contact.html"
#    name = "contact"
#    [menu.icon.params]
#        icon = "/images/envelope.svg"
#    weight = 1
  1. Make sure the module imports work and the site renders:
marcusb@dom:testsite$ hugo server -D
go: no module dependencies to download
go: added github.com/marcus0x62/tinyblog v0.0.0-20240117174831-855475c7b1db
go: added github.com/marcus0x62/tinycomments v0.0.0-20240117164733-0a3dec7308ef
go: added github.com/marcus0x62/tinyimages v0.0.0-20240117164552-29761a007428
hugo: collected modules in 822 ms
Watching for changes in /home/marcusb/code/testsite/{archetypes,assets,content,data,i18n,layouts,static}
Watching for config changes in /home/marcusb/code/testsite/hugo.toml, /home/marcusb/code/testsite/go.mod
Start building sites …
hugo v0.120.4+extended linux/amd64 BuildDate=unknown


                   | EN
-------------------+-----
  Pages            |  7
  Paginator pages  |  0
  Non-page files   |  0
  Static files     |  5
  Processed images |  0
  Aliases          |  3
  Sitemaps         |  1
  Cleaned          |  0

Built in 1 ms
Environment: "development"
Serving pages from memory
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop
  1. Make sure you can load web content from the web server. It should look like this:

  1. From there, add your content and deploy to your cloud provider of choice. If you aren’t familiar with Hugo, I recommend the Hugo Quick Start guide.

Customization

SettingDescriptionDefault Value
authorYour name. This will be included in the footer.None.
licenseTextA description of your site license. This will render below the copyright line, if it is specified, in the footer.None.
licenseUrlA URL for the license terms and conditions for your site. Also optional.None.
accentColorForeground color for borders and link text. Can be a color name or a hex color (e.g., #ff0000)grey
textColorForeground color for text.black
backgroundColorSite background color.#fefbea
navbarBackgroundColorNavigation bar background color#ffffea
navbarBorderTopTop border thickness for the navigation bar.2px
navbarBorderBottomBottom border thickness for the navigation bar.1px
navbarIconSizeIcon size (width and height) for navigation bar images16px
itemsPerPageHow many items to render on a page before paginating5

Any settings you want to customize should be placed in the [params] block in the site config file. If you use the example config file as your base, these are already there, commented out. If not, the syntax looks like this:

[params]
        accentColor = "fuschia"
        backgroundColor = "white"
        ...
[[menu.icon]]
    url = "/contact.html"
    name = "contact"
    [menu.icon.params]
        icon = "/images/envelope.svg"
    weight = 1
marcusb@dom:testsite$ mkdir static/css
marcusb@dom:testsite$ hugo gen chromastyles --style solarized-dark > static/css/highlight.css

For any post that uses syntax highlighting, be sure to set the highlight flag to true in the content front matter:

---
title: "Tinyblog Theme for Hugo"
date: 2023-10-30
draft: false
url: /hacks/tinyblog.html
tags: ["hugo", "theme", "minimal"]
quote: "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupéry"
highlight: true
---

You can read more about how Hugo syntax highlighting works in markdown here.

Front Matter

Front matter is metadata or configuration that is placed in a Hugo content item, like a post. Tinyblog uses the following front matter elements:

SettingDescriptionNotes
titleA string argument containg the post title.This should always be present, and is used in an opening header and tag.
dateThe original date of the post. This will be included in the post heading, but is optional.
lastmodThe date the post was last updated. This is optional, but if specified will be in the heading below the publish date.
draftA boolean which indicates if the post is a draft or final. By default, drafts aren’t included in the Hugo build process, unless you specify the ‘-D’ flag to Hugo.
urlAn optional parameter that overrides the default URL Hugo will pick for the generated content.
tagsAn optional array of tags. Hugo will use these to generate cross-links for related posts.The array format looks like this: [“hugo”, “theme”, “minimal”]
quoteAn optional string argument, that will be placed on the right side of the post heading (or below the tags on a small enough viewport." I use it to include quotations in some of my posts.
highlightA boolean flag that is used to include the syntax highlighting CSS, if that is in use on a particular postDefaults to false.
descriptionAn optional string argument that is used to generate the tag.

Deeper customization

If you want to use the theme but do more customization than the settings above allow for, you’ll need to add the Tinyblog theme as a submodule in your project:

marcusb@dom:~testsite$ git submodule add https://github.com/marcus0x62/tinyblog themes/tinyblog
Cloning into '/home/marcusb/testsite/themes/tinyblog'...
remote: Enumerating objects: 135, done.
remote: Counting objects: 100% (135/135), done.
remote: Compressing objects: 100% (86/86), done.
remote: Total 135 (delta 56), reused 114 (delta 38), pack-reused 0
Receiving objects: 100% (135/135), 28.28 KiB | 1.13 MiB/s, done.
Resolving deltas: 100% (56/56), done.
marcusb@dom:testsite$

Then add a ’theme’ configuration setting in your config file:

baseURL = 'https://example.com/'
languageCode = 'en-us'
title = 'My New Hugo Site'
markup.highlight.noClasses=false
theme = 'tinyblog'

The difference between this and the previous method is the theme source is replicated in your site directory under themes/tinyblog, and you can edit it to suit your purposes.

You can add Tinycomments and Tinyimages in the same way:

marcusb@dom:testsite$ git submodule add https://github.com/marcus0x62/tinycomments themes/tinycomments
Cloning into '/home/marcusb/testsite/themes/tinycomments'...
remote: Enumerating objects: 44, done.
remote: Counting objects: 100% (44/44), done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 44 (delta 10), reused 39 (delta 8), pack-reused 0
Receiving objects: 100% (44/44), 28.65 KiB | 946.00 KiB/s, done.
Resolving deltas: 100% (10/10), done.
marcusb@dom:testsite$ git submodule add https://github.com/marcus0x62/tinyimages themes/tinyimages                   √
Cloning into '/home/marcusb/testsite/themes/tinyimages'...
remote: Enumerating objects: 19, done.
remote: Counting objects: 100% (19/19), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 19 (delta 1), reused 16 (delta 1), pack-reused 0
Receiving objects: 100% (19/19), 5.47 KiB | 5.47 MiB/s, done.
Resolving deltas: 100% (1/1), done.
marcusb@dom:testsite$                                                                                                √

Then change your theme line to be:

theme = ['tinyblog', 'tinycomments', 'tinyimages']

Todo

License

Tinyblog is released under the MIT License