Skip to content

Deploy docs site with Hugo via GitHub Actions#455

Merged
horgh merged 2 commits into
mainfrom
greg/stf-448
May 19, 2026
Merged

Deploy docs site with Hugo via GitHub Actions#455
horgh merged 2 commits into
mainfrom
greg/stf-448

Conversation

@oschwald
Copy link
Copy Markdown
Member

Summary

Migrates the Pages index from Jekyll on gh-pages to a Hugo build that
publishes back onto gh-pages from GitHub Actions. All CSS is now
inlined in the layout template — no external CDN dependencies.

The historical Doxygen output under /doc/vX.Y.Z/ (frozen since 2022)
is preserved untouched by the workflow's keep_files: true, matching
the Terraform comment that calls out the intent of keeping old API doc
links alive.

  • Hugo site lives under docs/ on main and mounts README.md as
    the home page
  • A small pill nav links from the overview to the Doxygen output at
    /doc/latest/
  • .github/workflows/pages.yml builds with mise run build-docs and
    pushes to gh-pages via peaceiris/actions-gh-pages with
    keep_files: true
  • No release.sh change needed — this repo's release script doesn't
    publish to gh-pages

Same design as MaxMind-DB PR #221.

For STF-448.

Post-merge steps

  1. Verify the live site at https://maxmind.github.io/GeoIP2-dotnet/ and
    a sample /doc/latest/ still loads after the next workflow run
  2. In a separate commit on gh-pages, drop the legacy Jekyll source
    files

Pages source stays on gh-pages — no Terraform change for this repo.

Test plan

  • mise run build-docs succeeds with no warnings
  • Rendered <title>, <h1>, and pill nav are correct
  • No static-gh.maxmind.com references in the new site
  • Build job passes in CI (push step only runs on main)
  • After merge, confirm the workflow pushes successfully to gh-pages
    and /doc/vX.Y.Z/ subtrees are preserved

🤖 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 introduces a Hugo-based documentation site for the GeoIP2 .NET API, including a base layout, custom heading anchors, and build tasks in the mise configuration. Feedback includes a suggestion to use a leading slash in the API documentation link for more robust URL resolution, a recommendation to clean up redundant tool versions in the mise.lock file, and a suggestion to externalize hardcoded strings in the layout template to facilitate future internationalization.

<body>
<nav class="page-nav">
<a href="{{ .Site.Home.RelPermalink }}"{{ if .IsHome }} class="active"{{ end }}>Overview</a>
<a href="{{ "doc/latest/" | relURL }}">API documentation</a>
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 a relative path without a leading slash in relURL can lead to broken links if the site is accessed without a trailing slash (e.g., .../GeoIP2-dotnet). In such cases, the browser may resolve the link relative to the parent directory instead of the site root. Adding a leading slash ensures Hugo prepends the baseURL path correctly, making the link more robust across different entry points.

Suggested change
<a href="{{ "doc/latest/" | relURL }}">API documentation</a>
<a href="{{ "/doc/latest/" | relURL }}">API documentation</a>

Comment thread mise.lock
Comment on lines +118 to +156
[[tools.node]]
version = "26.1.0"
backend = "core:node"

[tools.node."platforms.linux-arm64"]
checksum = "sha256:fcb4c339eef70c909cae72091008a6497278e2d0fcd221c0653068cf4ea4f0c7"
url = "https://nodejs.org/dist/v26.1.0/node-v26.1.0-linux-arm64.tar.gz"

[tools.node."platforms.linux-arm64-musl"]
checksum = "sha256:fcb4c339eef70c909cae72091008a6497278e2d0fcd221c0653068cf4ea4f0c7"
url = "https://nodejs.org/dist/v26.1.0/node-v26.1.0-linux-arm64.tar.gz"

[tools.node."platforms.linux-x64"]
checksum = "sha256:62d555c329e05e3625109f2e3a8b5195b368d5ef38266292469d32f63cd98ffd"
url = "https://nodejs.org/dist/v26.1.0/node-v26.1.0-linux-x64.tar.gz"

[tools.node."platforms.linux-x64-musl"]
checksum = "sha256:62d555c329e05e3625109f2e3a8b5195b368d5ef38266292469d32f63cd98ffd"
url = "https://nodejs.org/dist/v26.1.0/node-v26.1.0-linux-x64.tar.gz"

[tools.node."platforms.macos-arm64"]
checksum = "sha256:91063f665c2f5d6e69e4f8fcb66d3d476bc2785ace82267274bf4da789985ceb"
url = "https://nodejs.org/dist/v26.1.0/node-v26.1.0-darwin-arm64.tar.gz"

[tools.node."platforms.macos-x64"]
checksum = "sha256:33519b28a352de668ab0a2a64366db032a45cb629d5353f86e4576e2780f4fcf"
url = "https://nodejs.org/dist/v26.1.0/node-v26.1.0-darwin-x64.tar.gz"

[tools.node."platforms.windows-x64"]
checksum = "sha256:089a02c4c687451c9f0b7f1bfd252dae85a7ba27df0295a14096bdcc956fdc92"
url = "https://nodejs.org/dist/v26.1.0/node-v26.1.0-win-x64.zip"

[[tools."npm:prettier"]]
version = "3.8.1"
backend = "npm:prettier"

[[tools."npm:prettier"]]
version = "3.8.3"
backend = "npm:prettier"
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 lockfile now contains multiple versions of node (25.8.0 and 26.1.0) and prettier (3.8.1 and 3.8.3). Since mise.toml specifies latest for these tools, it is cleaner to only lock the single latest version to avoid redundant tool installations in development and CI environments. This can be resolved by running mise lock --force or manually removing the older entries from the lockfile.

Comment on lines +2 to +201
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ or .Title .File.BaseFileName }} | {{ .Site.Title }}{{ end }}</title>
<style>
:root {
--fg: #2d2d2d;
--bg: #faf9f7;
--accent: #1a6b50;
--accent-soft: rgba(26, 107, 80, 0.06);
--border: #d5d0c8;
--code-bg: #f0eeea;
--heading: #1a1a1a;
--muted: #70695f;
}

::selection {
background: rgba(26, 107, 80, 0.15);
}

*,
*::before,
*::after {
box-sizing: border-box;
}

body {
font-family: Charter, "Bitstream Charter", "Sitka Text", Cambria, serif;
font-size: 1.05rem;
line-height: 1.78;
color: var(--fg);
background: var(--bg);
max-width: 50rem;
margin: 0 auto;
padding: 3rem 1.5rem 5rem;
}

h1,
h2,
h3,
h4 {
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, Arial,
sans-serif;
line-height: 1.35;
}

h1 {
font-size: 1.75rem;
font-weight: 800;
color: var(--heading);
margin: 0 0 1.5rem;
padding-bottom: 0.75rem;
border-bottom: 3px solid var(--accent);
}

h2 {
font-size: 1.3rem;
font-weight: 700;
color: var(--heading);
margin: 3rem 0 0.75rem;
padding-bottom: 0.4rem;
border-bottom: 1px solid var(--border);
}

h3 {
font-size: 1.05rem;
font-weight: 700;
color: var(--accent);
margin: 2.5rem 0 0.5rem;
padding: 0.4rem 0.75rem;
border-left: 3px solid var(--accent);
background: linear-gradient(
135deg,
var(--accent-soft),
transparent 80%
);
border-radius: 0 3px 3px 0;
}

h4 {
font-size: 0.92rem;
font-weight: 700;
color: var(--muted);
margin: 2rem 0 0.5rem;
padding-bottom: 0.2rem;
border-bottom: 1px dashed var(--border);
}

p {
margin: 0.8rem 0;
}

a {
color: var(--accent);
text-decoration-thickness: 1px;
text-underline-offset: 2px;
transition: text-decoration-thickness 0.15s;
}

a:hover {
text-decoration-thickness: 2px;
}

strong {
color: var(--heading);
font-weight: 700;
}

ol,
ul {
padding-left: 1.75rem;
}

li + li {
margin-top: 0.3rem;
}

code {
font-family: "JetBrains Mono", "Cascadia Code", Menlo, Consolas,
monospace;
font-size: 0.88em;
background: var(--code-bg);
padding: 0.15em 0.4em;
border-radius: 3px;
border: 1px solid rgba(0, 0, 0, 0.06);
}

pre {
background: var(--code-bg);
border: 1px solid var(--border);
border-radius: 5px;
padding: 1rem 1.25rem;
overflow-x: auto;
line-height: 1.55;
}

pre code {
background: none;
padding: 0;
border: none;
font-size: 0.85em;
}

.heading-anchor {
opacity: 0;
margin-left: 0.3em;
font-weight: 400;
text-decoration: none;
transition: opacity 0.15s;
}

h1:hover .heading-anchor,
h2:hover .heading-anchor,
h3:hover .heading-anchor,
h4:hover .heading-anchor,
.heading-anchor:focus {
opacity: 0.4;
}

.heading-anchor:hover {
opacity: 1;
}

.page-nav {
margin-bottom: 2.5rem;
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}

.page-nav a {
font-family: system-ui, -apple-system, "Segoe UI", Helvetica, Arial,
sans-serif;
font-size: 0.85rem;
font-weight: 600;
text-decoration: none;
color: var(--muted);
padding: 0.3rem 0.75rem;
border: 1px solid var(--border);
border-radius: 999px;
transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.page-nav a:hover {
color: var(--accent);
border-color: var(--accent);
}

.page-nav a.active {
color: var(--bg);
background: var(--accent);
border-color: var(--accent);
}
</style>
</head>
<body>
<nav class="page-nav">
<a href="{{ .Site.Home.RelPermalink }}"{{ if .IsHome }} class="active"{{ end }}>Overview</a>
<a href="{{ "doc/latest/" | relURL }}">API documentation</a>
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

Several user-facing strings and the document language are hardcoded in the layout template (e.g., lang="en" on line 2, "Overview" on line 200, and "API documentation" on line 201). To support future internationalization (i18n) and improve maintainability, consider moving these to Hugo's i18n files or site parameters.

@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 introduces a Hugo-based documentation site for the project, including the initial configuration, a base HTML layout with embedded CSS, and custom heading templates. It also updates the project's tool configuration and build tasks to support generating and serving the documentation. The review feedback focuses on improving the documentation's internationalization and responsiveness, specifically suggesting the use of site-configured language codes, the implementation of i18n for navigation strings, and the addition of CSS to ensure images are responsive.

@@ -0,0 +1,207 @@
<!doctype html>
<html lang="en">
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 lang attribute is hardcoded to "en". It is better to use the site's configured language code to support potential future internationalization.

Suggested change
<html lang="en">
<html lang="{{ .Site.LanguageCode | default "en" }}">

background: var(--accent);
border-color: var(--accent);
}
</style>
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 CSS is missing a rule to ensure that images within the content (e.g., from the README) are responsive and do not overflow their container on smaller screens.

      img {
        max-width: 100%;
        height: auto;
      }
    </style>

Comment thread docs/layouts/_default/default.html Outdated
Comment on lines +200 to +201
<a href="{{ .Site.Home.RelPermalink }}"{{ if .IsHome }} class="active" aria-current="page"{{ end }}>Overview</a>
<a href="{{ "/doc/latest/" | relURL }}">API documentation</a>
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

User-facing strings like "Overview" and "API documentation" are hardcoded. Consider using Hugo's i18n features (e.g., the i18n or T function) to make these strings translatable, especially since this is a new documentation setup.

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

The site mounts the existing `README.md` as the home page so the source
of truth stays in one place. A small pill nav links from Overview to
the versioned API documentation that lives on the `gh-pages` branch
under `doc/latest/`.

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) <[email protected]>
Deploys the Hugo docs site on push to main. The workflow builds the
site with `mise run build-docs` and pushes the rendered output onto
the existing `gh-pages` branch with `keep_files: true` — that
preserves every `/doc/vX.Y.Z/` Doxygen subtree exactly as it lives on
gh-pages today. Pages keeps deploying from `gh-pages`, so no Terraform
change is needed for this repo.

All actions are SHA-pinned.

For STF-448.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@horgh horgh merged commit cc8044a into main May 19, 2026
16 checks passed
@horgh horgh deleted the greg/stf-448 branch May 19, 2026 23:36
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