# Liberty Tools (libertytools.io) — Hugo static site A Hugo site built on the [hugo-book](https://github.com/alex-shpak/hugo-book) theme, with **Pagefind** client-side search and **lychee**-based dead-link checking. This document is the single reference for understanding the architecture, building, previewing, searching, and maintaining the site. > If you only need to build and preview, jump to > [Build & preview (§4)](#4-build--preview-make-commands). Everything you normally > type is a `make` target. --- ## Fresh git pull? Rebuild before serving `public/` (the built site) is **never in git** — it's regenerated locally and gitignored (§8). A `git pull` brings you source only: content, theme, Makefile, scripts. Until you rebuild, there is nothing to serve — and a stale `public/` left over from an older workflow (e.g. `hugo server`) will render pages with a broken search box and spurious `pagefind/*` / `livereload.js` 404s in the server log. From the project root: ``` make bootstrap # ONCE per machine: pinned Hugo/Node/lychee into .tools/ (no system changes) make tool-versions # diagnostic: pinned vs system tool versions make clean && make all # wipe stale output, then hugo --gc + pagefind index make serve-lan # serve on http://:8090/ (or: make serve, local :1414) ``` Success check: the `make all` log prints `Indexed N pages` (N > 0) and `public/pagefind/pagefind-ui.js` exists. `error 127` / "command not found" means a tool is missing: `make tool-versions` shows which, `make bootstrap` fixes it. Full details: [Prerequisites (§2)](#2-prerequisites-install-once), [Build & preview (§4)](#4-build--preview-make-commands). --- ## Table of contents - [Fresh git pull? Rebuild before serving](#fresh-git-pull-rebuild-before-serving) - [Architecture](#architecture) - [1. Clone](#1-clone) - [2. Prerequisites (install once)](#2-prerequisites-install-once) - [3. Configuration](#3-configuration) - [4. Build & preview (make commands)](#4-build--preview-make-commands) - [5. Search (Pagefind)](#5-search-pagefind) - [6. Dead links](#6-dead-links) - [7. Troubleshooting](#7-troubleshooting) - [8. Do not commit](#8-do-not-commit) - [Repository layout](#repository-layout) --- ## Architecture The site is a **fully static** output: no server-side rendering at request time, no database, no runtime. Hugo renders the markdown to plain HTML files *at build time*; a search index is generated from those files; and a trivial static file server (delivering the built directory) is all that runs in front of a browser. ### The three moving parts | Component | Role | |--------------|---------------------------------------------------------------------------------------| | **Hugo** | The static site generator. Reads `content/*.md` + the theme, emits `public/`. | | **hugo-book** | The theme (vendored under `themes/hugo-book/`). Layouts, SCSS styling, menu/TOC. | | **Pagefind** | Client-side full-text search. Indexes the built `public/` into `public/pagefind/`. | | **lychee** | Dead-link checker (used only by the `link-check`/`link-fix`/`external-check` targets).| Only Hugo and Node (for Pagefind's `npx` wrapper) are required to build. `lychee` is needed only if you run the dead-link targets. ### Content → build → serve, data flow ``` ┌──────────────────────────────────────────────┐ │ content/ │ │ *.md pages + images (the source) │ └──────────────────────┬───────────────────────┘ │ make build (hugo --gc) ▼ ┌──────────────────────────────────────────────┐ │ public/ │ │ rendered static HTML + fingerprinted CSS/JS │ │ (hugo-book SCSS compiled by the extended │ │ build; each asset hash-named + SRI-checked)│ └──────────────────────┬───────────────────────┘ │ make index (pagefind --site public) ▼ ┌──────────────────────────────────────────────┐ │ public/pagefind/ │ │ Pagefind search index (WASM + JSON) │ │ — ships inside public/, so any static │ │ server can serve a working search │ └──────────────────────┬───────────────────────┘ │ make serve / make serve-lan ▼ browser (any machine on the network) ``` Two consequences worth internalizing: 1. **`public/` is the single source of truth for what is served.** Both the search index and every preview server read from it. If the site "isn't showing your change," the build hasn't run — re-run `make index`. 2. **The Pagefind bundle lives inside `public/`.** That's why `make serve-lan` (a plain Python static server) serves working search with zero extra setup — there is no special search server required. ### The theme SCSS pipeline `html-head.html` compiles the theme's stylesheet on every build: ``` book.scss → resources.ExecuteAsTemplate → css.Sass → resources.Minify → resources.Fingerprint ``` `css.Sass` is why the **Hugo *extended*** edition is mandatory (the standard build has no SCSS compiler). `resources.Fingerprint` hashes the output into the filename (`book.min..css`) and embeds an SRI `integrity` attribute on the ``; a single byte change in the CSS produces a new filename, which is why old cached stylesheets never collide with new ones. ### Where your customizations live Two files hold all site-level customization — you rarely need to touch anything else: - **`themes/hugo-book/layouts/_partials/docs/search.html`** — the entire search UI: the Pagefind `new PagefindUI({...})` config, the `#search`-scoped `