Skip to content

Deploy docs site with Hugo and GitHub Actions#434

Merged
horgh merged 8 commits into
mainfrom
greg/stf-448
May 21, 2026
Merged

Deploy docs site with Hugo and GitHub Actions#434
horgh merged 8 commits into
mainfrom
greg/stf-448

Conversation

@oschwald
Copy link
Copy Markdown
Member

Summary

Migrates the docs site from Jekyll on gh-pages to a Hugo build deployed
via GitHub Actions. All CSS is now inlined in the layout template — no
external CDN dependencies.

  • Hugo site lives under docs/ on main and mounts the existing
    doc/libmaxminddb.md and doc/mmdblookup.md as content, keeping the
    source of truth in one place
  • A small pill nav at the top of each page lets readers move between the
    two docs
  • .github/workflows/pages.yml builds with mise run build-docs and
    deploys via the GitHub Actions Pages environment
  • dev-bin/release.sh no longer clones gh-pages or regenerates the
    index/mmdblookup Jekyll pages

Same design as MaxMind-DB PR #221: Charter serif body text, forest-green
accent on field-name headings, hover # anchor links.

Preview locally with mise run serve-docs.

For STF-448.

Post-merge steps

  1. Apply Terraform in mm_website to switch Pages source from
    gh-pages to GitHub Actions
  2. Verify the site at https://maxmind.github.io/libmaxminddb/ and
    https://maxmind.github.io/libmaxminddb/mmdblookup/
  3. Delete the legacy gh-pages branch

Test plan

  • mise run build-docs succeeds with no warnings
  • Both index.html and mmdblookup/index.html render with correct
    titles and working pill-nav
  • grep -r static-gh docs/ returns nothing
  • Build job passes in CI (deploy only runs on main)
  • After merge + Terraform apply, verify the live site renders correctly

🤖 Generated with Claude Code

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the project documentation from Jekyll to Hugo. It removes the manual documentation generation logic from the release script, adds Hugo configuration and layouts, and introduces mise tasks for building and serving the site. Review feedback focuses on refining the Hugo implementation, specifically restoring descriptive page titles lost during the migration, improving title tag logic, utilizing link titles in navigation, and pinning the Hugo version in the configuration for better build reproducibility.

Comment thread docs/hugo.toml
Comment on lines +5 to +6
[[cascade]]
layout = "default"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The migration to Hugo has resulted in the loss of descriptive page titles that were previously provided in the Jekyll front matter. Currently, Hugo defaults to using the filename (e.g., "mmdblookup") as the title. You can restore the descriptive titles (and optionally provide shorter link titles for the navigation) using Hugo's cascade feature in the configuration file.

Suggested change
[[cascade]]
layout = "default"
[[cascade]]
layout = "default"
[[cascade]]
[cascade._target]
path = "/_index.md"
title = "libmaxminddb - a library for working with MaxMind DB files"
linkTitle = "libmaxminddb"
[[cascade]]
[cascade._target]
path = "/mmdblookup.md"
title = "mmdblookup - a utility to look up an IP address in a MaxMind DB file"
linkTitle = "mmdblookup"

<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
{{- $title := or .Title .File.BaseFileName -}}
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ $title }} | {{ .Site.Title }}{{ end }}</title>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To support descriptive titles for the home page (set via configuration or front matter), the title tag should check for .Title before falling back to .Site.Title.

Suggested change
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ $title }} | {{ .Site.Title }}{{ end }}</title>
<title>{{ if .IsHome }}{{ or .Title .Site.Title }}{{ else }}{{ $title }} | {{ .Site.Title }}{{ end }}</title>

Comment thread docs/layouts/_default/default.html Outdated
Comment on lines +201 to +204
<a href="{{ .Site.Home.RelPermalink }}"{{ if .IsHome }} class="active"{{ end }}>{{ .Site.Title }}</a>
{{ range .Site.RegularPages }}
<a href="{{ .RelPermalink }}"{{ if eq $.RelPermalink .RelPermalink }} class="active"{{ end }}>{{ or .Title .File.BaseFileName }}</a>
{{ end }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using .LinkTitle in the navigation allows for shorter labels in the pill nav while maintaining descriptive titles for the browser tab. This works in conjunction with the cascade settings in hugo.toml.

Suggested change
<a href="{{ .Site.Home.RelPermalink }}"{{ if .IsHome }} class="active"{{ end }}>{{ .Site.Title }}</a>
{{ range .Site.RegularPages }}
<a href="{{ .RelPermalink }}"{{ if eq $.RelPermalink .RelPermalink }} class="active"{{ end }}>{{ or .Title .File.BaseFileName }}</a>
{{ end }}
<a href="{{ .Site.Home.RelPermalink }}"{{ if .IsHome }} class="active"{{ end }}>{{ or .Site.Home.LinkTitle .Site.Title }}</a>
{{ range .Site.RegularPages }}
<a href="{{ .RelPermalink }}"{{ if eq $.RelPermalink .RelPermalink }} class="active"{{ end }}>{{ or .LinkTitle .Title .File.BaseFileName }}</a>
{{ end }}

Comment thread mise.toml
]

[tools]
hugo = "latest"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It is recommended to pin the Hugo version to a specific version (e.g., the one currently in the lock file) to ensure build reproducibility across different environments and CI. Using latest can lead to unexpected build failures if a new version of Hugo introduces breaking changes.

Suggested change
hugo = "latest"
hugo = "0.161.1"

@oschwald
Copy link
Copy Markdown
Member Author

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the documentation site from Jekyll to Hugo, introducing a new Hugo configuration, base templates, and styling. The release.sh script was simplified by removing the manual documentation generation and deployment logic. Feedback suggests restoring the version information in the documentation which was lost during the migration and improving the home page title for better SEO and clarity.

Comment thread dev-bin/release.sh

git commit -m "Updated for $version" -a

read -r -e -p "Push to origin? (y/n) " should_push
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The migration to Hugo removes the logic that previously injected the library version into the documentation site. In the Jekyll setup, release.sh added a version field to the front matter. Since the new Hugo site mounts raw markdown files from ../doc/, this version information is no longer present in the rendered site. Consider passing the version as a Hugo parameter or environment variable during the build process in GitHub Actions and updating the template to display it.

<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
{{- $title := or .Title .File.BaseFileName -}}
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ $title }} | {{ .Site.Title }}{{ end }}</title>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The home page title is currently set to the site title ("libmaxminddb"), which is less descriptive than the previous Jekyll title ("libmaxminddb - a library for working with MaxMind DB files"). This can affect SEO and browser tab clarity. Consider using the more descriptive title for the home page.

Suggested change
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ $title }} | {{ .Site.Title }}{{ end }}</title>
<title>{{ if .IsHome }}libmaxminddb - a library for working with MaxMind DB files{{ else }}{{ $title }} | {{ .Site.Title }}{{ end }}</title>

oschwald and others added 3 commits May 18, 2026 23:24
Build with `mise run build-docs`, preview with `mise run serve-docs`.

The site mounts the existing `doc/libmaxminddb.md` and `doc/mmdblookup.md`
as Hugo content so the source of truth stays in one place. A small pill
nav lets readers move between the two pages.

CSS is inlined in the layout template — no external dependencies. Same
Charter serif + forest-green design as the MaxMind-DB spec site.

For STF-448.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Deploys the Hugo docs site on push to main. Uses the same mise-action
pattern as PR #221. All actions are SHA-pinned.

After merge, the Pages source needs to flip from "Deploy from a branch"
(gh-pages) to "GitHub Actions" — handled in the mm_website Terraform PR.
The legacy gh-pages branch can then be deleted.

For STF-448.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The release script no longer needs to clone the gh-pages branch and
regenerate Jekyll index/mmdblookup pages — the new Hugo workflow on
main owns the docs site, and the doc/*.md files are now mounted as
content directly. There is no versioned doc tree on gh-pages to
preserve for this repo.

For STF-448.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread docs/hugo.toml
@@ -0,0 +1,17 @@
title = "libmaxminddb"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From Claude. Not sure if it matters if it's right:

  - URL path break. Old Jekyll used permalink: /:title.html → mmdblookup.html. Hugo pretty URLs → /mmdblookup/. External links (forums, SO, blogs) to mmdblookup.html will 404.
  Fix: set permalinks in hugo.toml or add aliases frontmatter on each page.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 889b63c — added uglyURLs = true to hugo.toml. Old Jekyll served /mmdblookup.html via permalink: /:title.html; with uglyURLs Hugo emits the same .html suffix on non-home pages, so existing external links resolve unchanged.

(Claude, responding on behalf of @oschwald.)

Comment thread docs/hugo.toml Outdated
@@ -0,0 +1,17 @@
title = "libmaxminddb"
disableKinds = ["taxonomy"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same feedback as on geoipupdate PR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in b284fb1disableKinds = ["taxonomy", "term", "RSS"].

(Claude, responding on behalf of @oschwald.)

oschwald and others added 2 commits May 20, 2026 14:29
`disableKinds = ["taxonomy"]` only disables the taxonomy list page;
post-Hugo-0.73 individual term pages are a separate kind. The site
declares no taxonomies, so neither list nor term pages have content,
but the config now matches its stated intent. Disabling RSS also
suppresses an empty `index.xml` that nothing subscribes to.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hugo's built-in fallback renders an empty `<main></main>` for the
404 page. Provide a minimal "Page not found" body with a link back
to the site home, reusing the Charter/forest-green design tokens
from the main layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@oschwald
Copy link
Copy Markdown
Member Author

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the project's documentation system from a manual shell script process to a Hugo-based static site generator. The changes include removing legacy documentation generation from the release script, adding Hugo configuration and layouts, and updating the project's tool configuration to include Hugo and documentation-related tasks. A review comment identified a bug in the Hugo template logic where variable scoping prevented the correct assignment of page titles; a simplified approach using the 'or' function was suggested to resolve this.

Comment thread docs/layouts/_default/default.html Outdated
oschwald and others added 2 commits May 20, 2026 16:11
`.File` is nil on virtual pages (e.g., taxonomy listings before they
were disabled). Wrap with `with .File` so the title rendering is
null-safe even if future virtual pages get enabled.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The old Jekyll site used `permalink: /:title.html` and served pages
at `/mmdblookup.html`. Hugo's default pretty URLs would emit
`/mmdblookup/`, breaking existing external links to the old paths.
Set `uglyURLs = true` so Hugo writes `.html` suffixes for non-home
pages, matching the old behavior exactly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@oschwald
Copy link
Copy Markdown
Member Author

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the documentation generation process from a manual shell script in release.sh to a Hugo-based static site generator. It introduces a new docs directory containing Hugo configurations, layout templates, and CSS, while updating project tooling via mise to include Hugo tasks. Review feedback points out that uglyURLs should be disabled to maintain standard directory-style URL structures and suggests inlining the CSS to align with the PR's stated goals and optimize performance.

Comment thread docs/hugo.toml
@@ -0,0 +1,18 @@
title = "libmaxminddb"
uglyURLs = true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The uglyURLs = true setting causes Hugo to generate files like mmdblookup.html instead of the directory-style structure (mmdblookup/index.html) expected by the test plan and mentioned in the PR description. To maintain the desired URL structure and match the test plan, this should be set to false (which is the default).

Suggested change
uglyURLs = true
uglyURLs = false

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The uglyURLs = true setting is deliberate — the pre-migration Jekyll site served mmdblookup.html (the URL pattern documented in external references and search-engine indexed). Switching to Hugo's pretty-URL form (mmdblookup/) would 404 those existing links. This is preserving backward compatibility for libmaxminddb specifically.

(Claude, responding on behalf of @oschwald.)

Comment thread docs/layouts/_default/default.html Outdated
Comment on lines +8 to +9
{{- $css := resources.Get "css/main.css" -}}
<link rel="stylesheet" href="{{ $css.RelPermalink }}" />
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The PR description states that "All CSS is now inlined in the layout template", but the current implementation uses a <link> tag to an external stylesheet. To actually inline the CSS as described and avoid an extra network request, you can use Hugo's .Content property within a <style> tag.

    {{- with resources.Get "css/main.css" | minify -}}
    <style>{{ .Content | safeCSS }}</style>
    {{- end -}}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description is stale — externalizing the CSS in round 9 was a deliberate choice on top of the earlier inlined form, made to enable browser caching of the stylesheet across pages on the docs site. The code is doing what we want; we'll update the PR description to reflect the current state.

(Claude, responding on behalf of @oschwald.)

Extracts the inline `<style>` block from the default and 404 layouts
into `docs/assets/css/main.css`, served via Hugo's asset pipeline.
Both layouts now reference the file via `<link rel="stylesheet">`, so
the 404 page inherits the full stylesheet instead of duplicating a
subset of rules.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@horgh horgh merged commit 6052cea into main May 21, 2026
33 checks passed
@horgh horgh deleted the greg/stf-448 branch May 21, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants