Grizzly Hugo Theme

Today’s websites are bloated, slow, and full of scripts, ads, and trackers. This practice has become so commonplace that we’ve lost all sense of perspective, to the point that now we think multi-megabyte webpages are normal.

Grizzly is based on Bear Cub and keeps its focus on speed, privacy, and accessibility. It is multilingual, search-engine friendly, and responsive.

View source here: https://github.com/brycekwon/hugo-grizzly/
View example(s) here: https://demo.brycekwon.com/hugo-grizzly/

Requirements

Grizzly requires the extended edition of Hugo, version 0.163.0 or newer. The extended build is needed for the WebP image processing and CSS bundling the theme performs while rendering.

hugo version

Git is recommended for installing the theme as a submodule to keep up with updates and releases. However, an archive of the repository will work as well.

Building

The repository carries an example site under examples/. Two scripts in tools/ build and serve it against the theme:

./tools/build              # build the example site (development)
./tools/build --serve      # serve it locally with live reload
./tools/build --env production
./tools/clean              # remove generated output (public/, resources/)

./tools/build takes --env development (the default) or --env production. The two differ only in base URL and whether draft, future, and expired content are built. Add --serve to either for a live-reloading preview.

For your own site the usual Hugo commands apply once the theme is installed:

hugo server      # preview with live reload
hugo             # build into public/

Usage

Follow Hugo’s quick start guide to create an empty website. Then drop Grizzly into the themes/ directory and append the following line to the site configuration file:

echo 'theme = "hugo-grizzly" >> config/_default/hugo.toml'

From there you can use the following commands to create pages:

hugo new content --kind posts somewhere/odd-path.md
hugo new content --kind projects somewhere/odd-path.md

Options

OptionEffect
css.disableSyntaxHighlightsSkip the highlight stylesheet even on code pages
js.disableJSShip a script-free site (drops the theme toggle)
rss.limitItems included in each RSS feed
ui.hideRSSIconHide the RSS icon in the header
ui.hideThemeToggleHide the light/dark toggle button
posts.groupBy“year” groups the post list by year, empty is flat
posts.pagerSizePosts per page, 0 disables pagination

Content

The archetypes populate a standard set of front matter fields. Posts carry type = "posts" and an optional author. Projects carry a weight that orders the project list. Any trailing field can be left at its default.

FieldPurpose
titlePage title
summaryBlurb shown in list pages and feeds
descriptionMeta description for SEO and Open Graph
tagsList of tags that fill the tags taxonomy
datePublish date
lastmodLast-modified date, shown when newer than date
slugURL segment for the page
aliasesOld paths to redirect from
authorOptional byline on a post
weightOrders entries in the project list
draftExclude from production builds when true
extra_cssExtra stylesheets to load on this page
extra_jsExtra scripts to load on this page

Shortcodes

Two shortcodes cover the common rich-content cases. Math is written with latex and rendered to MathML at build time, so no script or font is downloaded:

Inline: {{< latex >}}\sqrt{a^2 + b^2}{{< /latex >}}
Block:  {{< latex display="true" >}} \varphi = 1 + \frac{1}{1+\cdots} {{< /latex >}}

YouTube videos use a privacy-friendly, lazy-loaded embed. id is required, and title, caption, rel, modest, and start are optional:

{{< youtube id="VIDEO_ID" caption="A caption" >}}

Admonitions are written as GitHub-style alerts. The supported types are NOTE, TIP, IMPORTANT, WARNING, and CAUTION, plus a custom callout with your own label:

> [!NOTE]
> Useful information worth knowing.

> [!CALLOUT] Custom title
> Body text goes here.

Markdown is handled with a light touch elsewhere too: external links open in a new tab, content images are converted to WebP with a responsive srcset and lazy-loaded (alt text is required), and fenced code blocks are highlighted.

Languages

Grizzly is multilingual. Define each language under [languages] in hugo.toml with a title, locale, direction, and date formats:

[languages.en]
 title = "Grizzly"
 locale = "en-US"
 [languages.en.params.formats.date]
   long = "January 02, 2006"
   short = "Jan 02, 2006"

Theme strings (the 404 page, tag label, post metadata, admonition labels, and pagination) live in i18n/en.toml and i18n/ja.toml. Add a file per language to translate them. Tag display names can be localized with matching keys in your site’s own i18n files. On a translated page the header shows a language switcher automatically.

For more information, please see the examples/ directory.

License

This project is licensed under the MIT License.