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
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
- Accessible design by default - color contrast, encouraging alt-text for visual elements, decoration for links.
- No unnecessary JavaScript or external resources like web fonts.
- No trackers
- Support a responsive design for mobile clients
- Constrain scripts to only those pages where they are needed by providing post-level configuration flags. For instance, there is a CSS file that is only used on pages with syntax highlighting, so that CSS file is only loaded on pages that actually use syntax highlighting.
- Support comments
- Good image and image gallery support.
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
- If you haven’t already, install Hugo.
- 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:~$
- 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$
- 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
- 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
- Make sure you can load web content from the web server. It should look like this:
- 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
- The Tinyblog, Tinycomments, and Tinyimages modules are separate; if you don’t want to use the comments system or image gallery, then simply don’t list those modules in your Hugo site config file.
- There are several basic elements that can be customized with config file settings, without having to dig around in the theme HTML and CSS templates:
Setting | Description | Default Value |
---|---|---|
author | Your name. This will be included in the footer. | None. |
licenseText | A description of your site license. This will render below the copyright line, if it is specified, in the footer. | None. |
licenseUrl | A URL for the license terms and conditions for your site. Also optional. | None. |
accentColor | Foreground color for borders and link text. Can be a color name or a hex color (e.g., #ff0000) | grey |
textColor | Foreground color for text. | black |
backgroundColor | Site background color. | #fefbea |
navbarBackgroundColor | Navigation bar background color | #ffffea |
navbarBorderTop | Top border thickness for the navigation bar. | 2px |
navbarBorderBottom | Bottom border thickness for the navigation bar. | 1px |
navbarIconSize | Icon size (width and height) for navigation bar images | 16px |
itemsPerPage | How many items to render on a page before paginating | 5 |
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"
...
- In the example configuration, there is a commented-out [[menu.icon]] entry. As the name suggests, this is for a navigation bar entry that uses an image instead of text. By default, these images are scaled to 16x16px, regardless of the image size, although you can change that with the navbarIconSize configuration setting. Another thing to note is the icon entries are right-justified in a separate group than the text navigation bar entries. The icon parameter specifies the image URL, the url parameter is the link target, and name, if specified will be used as the image alt text.
[[menu.icon]]
url = "/contact.html"
name = "contact"
[menu.icon.params]
icon = "/images/envelope.svg"
weight = 1
- By default, the theme uses the Solarized Light highlighting theme. If you want to use a different theme, check out the options here and then generate new CSS in your site directory in static/css/highlight.css:
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:
Setting | Description | Notes |
---|---|---|
title | A string argument containg the post title. | This should always be present, and is used in an opening header and tag. |
date | The original date of the post. This will be included in the post heading, but is optional. | |
lastmod | The date the post was last updated. This is optional, but if specified will be in the heading below the publish date. | |
draft | A 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. | |
url | An optional parameter that overrides the default URL Hugo will pick for the generated content. | |
tags | An optional array of tags. Hugo will use these to generate cross-links for related posts. | The array format looks like this: [“hugo”, “theme”, “minimal”] |
quote | An 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. | |
highlight | A boolean flag that is used to include the syntax highlighting CSS, if that is in use on a particular post | Defaults to false. |
description | An 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
Integrate chat support.Mostly done.- Better inline image/gallery support for posts.
License
Tinyblog is released under the MIT License