Getting Started with Mono
This guide walks through installing Mono and setting up a site.
Initial Setup
Install Hugo
Hugo is a fast static site generator. Follow the official Hugo installation guide. After installation, verify it works:
hugo versionFor full functionality, we recommend Hugo v0.139 or later as we tested Mono with this version.
Create a New Site
Create a new Hugo site:
hugo new site my-site
cd my-siteThis creates a directory with Hugo’s default structure:
my-site/
├── archetypes/ # Templates for new content
├── content/ # Pages and posts
├── data/ # Data files (TOML, YAML, JSON)
├── layouts/ # Custom templates (optional)
├── static/ # Static files (images, etc.)
├── themes/ # Installed themes
└── hugo.toml # Site configurationInstall Mono
Themes go in the themes/ directory. Choose one of these methods:
Git Submodule (Recommended)
Keeps theme files separate from the repository and makes updates easy.
git init
git submodule add https://github.com/yassouali/mono.git themes/monoTo update the theme later:
git submodule update --remote --mergeWhen cloning the site on a new machine, run git submodule update --init --recursive to fetch the theme.
Git Clone
Downloads the theme directly into the project.
git clone https://github.com/yassouali/mono.git themes/mono --depth=1To update the theme later:
cd themes/mono
git pull
cd ../..Hugo Module
Uses Go modules instead of storing theme files locally. Requires Go.
hugo mod init github.com/yourusername/my-siteThen add to hugo.toml:
[module]
[[module.imports]]
path = "github.com/yassouali/mono"To update the theme later:
hugo mod get -uConfigure and Run
Add the theme to hugo.toml:
theme = "mono"Start the development server:
hugo server --noHTTPCache -DOpen http://localhost:1313 to see the site. The server watches for changes and reloads automatically.
Using the Example Site
The site will be empty at this point. The easiest way to get started is to use the included example site.
cp themes/mono/exampleSite/hugo.toml .
cp -r themes/mono/exampleSite/content .
cp -r themes/mono/exampleSite/data .
cp -r themes/mono/exampleSite/static .
cp -r themes/mono/exampleSite/assets .After running hugo server --noHTTPCache -D, the example website can then be viewed locally at http://localhost:1313. In the command above, -D flag includes drafts, and --noHTTPCache disables browser caching to see the changes immediately.
Site Structure: By starting with the provided example website, we have a ready-to-use website with the following structure inside exampleSite/:
content/: Pages and posts: here we can edit the relevant blog posts and pages,posts/: Blog posts, each Markdown file represents a new blog post entry. The front matter at the top of each file contains metadata like title, date, tags, and description. The default archetype for new posts is defined inarchetypes/default.md,_index.md: The homepage content,about.md: An example for the about page,projects.md: An example for the projects page, the list of projects is sourced fromdata/projects.toml,
data/: Structured content, used mainly to list the projects that are rendered on the projects page,static/: Images and other static files,assets/: Custom CSS (processed by Hugo Pipes),hugo.toml: Main configuration file.
To configure the site, edit exampleSite/hugo.toml:
baseURL = "https://yourwebsite.com/"
title = "Your Name"
defaultContentLanguage = "en" # en, es, fr, de, zh, see i18n folder
[params]
author = "Your Name"
description = "Your site description"
# Social links (to appear in the footer)
[[params.social]]
name = "GitHub"
url = "https://github.com/yourusername"
icon = "github"
[[params.social]]
name = "Twitter"
url = "https://twitter.com/yourusername"
icon = "twitter"Mono includes translations for English, Spanish, French, German, and Chinese. To change the language, set defaultContentLanguage to the desired language code (en, es, fr, de, or zh).
Supported social icons: GitHub, Twitter, LinkedIn, Instagram, Mastodon, Bluesky, Threads, Google Scholar. For more details about theme configuration, see the Theme Configuration post.
Creating Content
New Blog Post
To write a new blog post, simply create a new Markdown file in content/posts/ or use Hugo’s new content command, which will automatically populate the new file with the front matter defined in archetypes/default.md:
hugo new posts/my-post.mdWe can then write our blog post in standard Markdown format. For the full functionality of Mono and all its available options, please refer to the Typography & Markdown post in this demo site.
After finishing the post, we can remove draft: true from the front matter to publish it.
New Page
To create a new page outside the standard blog posts, we can create a new markdown file directly in content/. For example, to create an About page:
hugo new about.mdPages created in content/ (and not in content/posts/) use the default single page layout (layouts/_default/single.html). We can specify a different layout in the front matter if needed:
---
title: "About"
layout: "about"
---To create a custom layout, we add an HTML file in layouts/_default/. For example, to create the “about” layout referenced above, we create layouts/_default/about.html:
{{ define "main" }}
<article class="about-page">
<h1>{{ .Title }}</h1>
{{ .Content }}
</article>
{{ end }}This template extends baseof.html (that contains the common structure, like <head>, <header>, and <footer>) and defines the “main” block. Hugo will automatically use this layout for any page with layout: "about" in its front matter.
Customization
How Mono Works
Understanding how Hugo themes work can help us customize Mono more effectively later on. The theme follows Hugo’s standard structure where templates in layouts/ determine how content is rendered.
Layouts
Layouts are HTML templates that define the structure of our pages. Mono includes the following key layouts in layouts/_default/:
baseof.html: The base template which wraps all pages. It includes ourhead.html,header.html, andfooter.htmlpartials, and defines a “main” block that other templates fill in,single.html: Template for individual pages (like the About page for example). For blog posts specifically, Hugo useslayouts/posts/single.htmlinstead, which adds features like Table of Contents and post navigation,list.html: Template for section index pages. Hugo automatically uses this when visiting a directory URL like/posts/, listing all content in that section.projects.html: Custom layout for the projects showcase. In Mono, and to make its customization simple, we use Hugo’s data templates feature to read project entries fromdata/projects.tomland render them as cards,search.html: Layout for the search page. It uses Fuse.js for fast client-side fuzzy searching across all posts.
Partials
Partials are reusable template fragments, included by baseof.html:
head.html: Meta tags, CSS bundles, and scripts,header.html: Navigation menu and theme toggle,footer.html: Social links and copyright.
To customize these, simply edit the files in layouts/partials/.
Shortcodes
Shortcodes are reusable content snippets we can use in our markdown files. Mono provides several custom shortcodes in layouts/shortcodes/:
note,info,warning: Styled callout boxes for highlighting content,details: Collapsible content sections,aside: Side notes and annotations,media: Embed YouTube, Vimeo, or other media,full-width-img: Images that break out of the content width.
Example usage:
{{< note >}}
This is an important note.
{{< /note >}}For examples of available shortcodes and other features, see the Mono Theme Features blog post.
Navigation Menu
The navigation menu is configured in hugo.toml. Each menu item has a name, URL, and weight:
[menu]
[[menu.main]]
name = "Home"
url = "/"
weight = 1
[[menu.main]]
name = "Blog"
url = "/posts/"
weight = 2
[[menu.main]]
name = "Projects"
url = "/projects/"
weight = 3The weight determines the order of menu items, lower values appear first. For each menu URL, we should point to existing content:
/points tocontent/_index.md(the homepage),/posts/points to thecontent/posts/section (Hugo automatically lists all posts using thelist.htmllayout),/projects/points tocontent/projects.md(a standalone page), and so on.
To add a new menu item, create the corresponding markdown file in content/ first, then add the menu entry in hugo.toml.
Custom CSS and JS
To add custom styles or scripts without modifying the theme files:
- CSS: Create
assets/css/custom.css(processed by Hugo) - JS: Create
static/js/custom.js(copied as-is)
Then add them to the config:
[params]
customCSS = ["css/custom.css"]
customJS = ["js/custom.js"]For example, to change the accent color, add this to custom.css:
:root {
--color-primary: #0088cc;
}See assets/css/style.css for all available CSS variables.