Midori is a clean Hugo theme with a left navigation rail, optional table of contents, mobile app bar and drawer navigation, multilingual UI strings, and a lightweight reading-focused layout.
- Clean three-column layout on desktop: navigation, content, TOC
- Mobile app bar with drawer-style navigation
- TOC rendered only when the current page has real heading links
- Back-to-top button
- Hugo i18n support for built-in UI text
- Language switcher that only appears when the current page has a translated counterpart
- Optional homepage page listing
- Hugo
>= 0.146.0
Add the theme to your site:
git submodule add https://github.com/Saiba-Midori-Projects/gohugo-theme-midori.git themes/midoriThen enable it in your site config:
theme = "midori"If you clone the theme into a different folder name, theme must match that folder name.
Example site config:
baseURL = "https://example.org/"
defaultContentLanguage = "zh-CN"
defaultContentLanguageInSubdir = false
theme = "midori"
[languages]
[languages.zh-CN]
languageCode = "zh-CN"
languageName = "简体中文"
title = "My Site"
weight = 1
[languages.en]
languageCode = "en-US"
languageName = "English"
title = "My Site"
weight = 2
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
[markup.tableOfContents]
startLevel = 1
endLevel = 3
[params]
themeName = "Midori"
version = "0.1.1"
homeListPages = false
# homeListSections = ["posts"]The theme currently reads these custom parameters from params:
[params]
themeName = "Midori"
version = "0.1.1"
favicon = "/favicon.ico"
backgroundImage = "images/default_bg.png"
footerHTML = "<span>Copyright © 2026 <a href='https://example.org'>Your Site</a></span>"
homeListPages = false
# homeListSections = ["posts"]
[params.author]
name = "Your Name"
email = "you@example.com"params.backgroundImage: page background image, used by the main layout. Relative static paths such asimages/bg.pngwork well.params.favicon: favicon URL. If omitted, the theme falls back to/favicon.ico.params.footerHTML: custom footer HTML. When set, it replaces the default copyright line.params.author.name: author name shown in the footer copyright area.params.author.email: author email used for the footer mail link.params.themeName: theme name shown in the browser console badge.params.version: theme version shown in the browser console badge.params.homeListPages: enables homepage page listing mode.params.homeListSections: limits homepage listing to specific sections whenhomeListPages = true.
Example:
[params]
footerHTML = """
<span>Copyright © 2026 <a href="https://example.org">Your Site</a></span>
<span style="margin-left: 0.5rem;">Powered by Hugo</span>
"""If footerHTML is not set, the theme falls back to the old author-and-email footer.
You can manage the left navigation in either of these ways.
Use menus.main in site config:
[menus]
[[menus.main]]
identifier = "menu.home"
name = "Home"
pageRef = "/"
weight = 10
[[menus.main]]
identifier = "menu.about"
name = "About"
pageRef = "/about"
weight = 20Or define menu membership in page front matter:
+++
title = "About"
[menus]
[menus.main]
weight = 20
+++If a menu entry has an identifier, the theme will try to translate it through Hugo i18n.
Built-in UI text is translated through Hugo i18n. The theme already includes:
i18n/zh-CN.tomli18n/en.toml
The language switcher is shown only when:
- the current regular page has a translated version
- or the home page has actual translated home content files such as
content/_index.en.md
For example:
content/_index.md
content/_index.en.md
content/about.md
content/about.en.md
If about.en.md does not exist, the switcher will be hidden on /about/.
- TOC is shown only when Hugo generates actual heading links for the page
- the mobile TOC toggle is also hidden when there is no real TOC
- you can disable TOC per page with front matter
- TOC levels follow your Hugo config, for example:
[markup.tableOfContents]
startLevel = 1
endLevel = 3Per-page example:
+++
title = "Home"
toc = false
+++When toc = false, the theme will hide both the TOC card and the mobile TOC toggle for that page.
By default, the home page renders only its own content.
To turn the home page into a blog-like list:
[params]
homeListPages = trueTo limit the list to specific sections:
[params]
homeListPages = true
homeListSections = ["posts"]This repository keeps demo content in exampleSite/content.
For local theme development, run this from the theme repository root:
hugo server -DThe root hugo.toml already points contentDir to exampleSite/content, so you do not need a long --source command for normal development.
Generated demo output is ignored via:
exampleSite/public/exampleSite/.hugo_build.lock
assets/ CSS and JavaScript
exampleSite/ Demo content and demo site config
i18n/ UI translations
layouts/ Theme templates and partials
static/ Static assets
