Building your first website using Hugo and GitHub Pages#

This repository documents how to set up a Hugo site using the Hugo Book theme with a custom landing page, global dark mode, and automatic deployment to GitHub Pages using GitHub Actions.

The setup provides:

  • A custom landing page at /
  • Hugo Book documentation/blog under /blog
  • Shared styling and dark mode across all pages
  • Automatic deployment on push to main

Prerequisites#

  • Hugo (extended version recommended for local development)
  • Git
  • GitHub account

Verify Hugo:

hugo version

Create the Hugo site#

hugo new site my-hugo-blog
cd my-hugo-blog

Add the Hugo Book theme#

git submodule add https://github.com/alex-shpak/hugo-book.git themes/hugo-book

Configure hugo.toml:

baseURL = "https://<username>.github.io/<repo>/"
languageCode = "en-us"
title = "My Hugo Book"
theme = "hugo-book"

[params]
  BookTheme = "auto"
  BookSection = "blog"
  customCSS = ["css/darkmode.css"]

Create the landing page#

Content#

Create content/_index.md:

---
title: Home
layout: landing
---

Layout#

Create layouts/_default/landing.html:

{{ define "main" }}
<link rel="stylesheet" href="{{ "css/landing.css" | relURL }}">

<section class="hero">
  <h1>Welcome</h1>
  <p>Engineering notes and technical articles.</p>
  <a href="/blog" class="btn">Read the blog</a>
</section>
{{ end }}

Styling#

Create assets/css/landing.css:

.hero {
  min-height: 80vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.btn {
  margin-top: 1.5rem;
  padding: 0.75rem 1.25rem;
  border-radius: 0.5rem;
  background: #4f46e5;
  color: white;
  text-decoration: none;
}

Add blog / documentation content#

hugo new blog/first-post.md

Enable global dark mode#

Dark mode CSS#

Create assets/css/darkmode.css:

:root {
  --bg: #ffffff;
  --bg-alt: #f8fafc;
  --text: #0f172a;
  --border: #e5e7eb;
}

html.dark {
  --bg: #0f172a;
  --bg-alt: #020617;
  --text: #e5e7eb;
  --border: #1e293b;
}

body {
  background: var(--bg);
  color: var(--text);
}

.book-page,
.book-menu {
  background: var(--bg);
}

Toggle button#

Create layouts/partials/darkmode-toggle.html:

<button id="dark-toggle">Toggle theme</button>

<script>
  const root = document.documentElement;

  if (
    localStorage.getItem("theme") === "dark" ||
    (!localStorage.getItem("theme") &&
      window.matchMedia("(prefers-color-scheme: dark)").matches)
  ) {
    root.classList.add("dark");
  }

  document.getElementById("dark-toggle").onclick = () => {
    root.classList.toggle("dark");
    localStorage.setItem(
      "theme",
      root.classList.contains("dark") ? "dark" : "light"
    );
  };
</script>

Inject toggle into header#

Create layouts/partials/header.html:

{{ partial "book-header.html" . }}
{{ partial "darkmode-toggle.html" . }}

Run locally#

hugo server -D

Open http://localhost:1313.


Deploy with GitHub Actions#

Deployment is handled automatically using GitHub Actions. On every push to the main branch, the site is built and published to GitHub Pages.

Create the workflow file:

.github/workflows/deploy.yml

With the following contents:

name: Deploy Hugo site

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
          fetch-depth: 0
          token: ${{ secrets.GITHUB_TOKEN }}

      - uses: peaceiris/actions-hugo@v3
        with:
          hugo-version: 'latest'

      - run: hugo --minify

      - uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./public

Notes on deployment#

  • The Hugo Book theme is included as a Git submodule and must be checked out recursively.
  • The site is built using the latest Hugo version.
  • The generated public/ directory is published to GitHub Pages.
  • No additional secrets are required; GITHUB_TOKEN is provided automatically.

Key project structure#

.github/workflows/
  deploy.yml
assets/css/
  landing.css
  darkmode.css
content/
  _index.md
  blog/
layouts/
  _default/landing.html
  partials/
    header.html
    darkmode-toggle.html
themes/
  hugo-book/
hugo.toml

Notes#

  • Do not modify files inside themes/hugo-book
  • Use layouts/ and assets/ for all overrides
  • Dark mode is implemented using CSS variables and localStorage