A clean, static documentation site generated from the project's docs/ Markdown with
Hugo. Layout: top nav + section sidebar + per-page "on this page" TOC, light/dark
theme, offline search. The look is ported from the project's earlier refsworld design.
You only ever edit Markdown. The site is decoupled from how the docs are organised:
- Navigation is fixed in
hugo.toml(it doesn't care where files live). - Each section page auto-lists whatever Markdown is in its folder.
- Internal
[x](y.md)links are resolved by filename, so they keep working even when you move a page to another folder (and the build warns if a target truly disappears). - Page titles come from each file's first
# H1— no front matter to maintain. - The analysis-only
**Status:** … Evidence E2/RD … Findings #…footer is stripped automatically.
Hugo extended ≥ 0.128 (single binary):
# Linux example — or use your package manager / https://gohugo.io/installation/
curl -sSL https://github.com/gohugoio/hugo/releases/download/v0.140.2/hugo_extended_0.140.2_linux-amd64.tar.gz | tar xz hugo
sudo mv hugo /usr/local/bin/
hugo version # must say "+extended"cd website
python3 build.py # docs/ -> content/ (strips footers, derives titles, folds examples)
hugo server # http://localhost:1313 (live-reload)Edit any .md in ../forefst/docs/ (or pages/home.md / pages/about.md), re-run python3 build.py, and the live server updates. To point at docs elsewhere: REFS_DOCS=/path/to/docs python3 build.py.
Build the static site for deployment:
python3 build.py && hugo --minify # output in public/website/
├── hugo.toml # config: nav menu, params (title, github URL, default theme)
├── build.py # docs/ -> content/ (the only "magic"; well-commented)
├── pages/ # site-only Markdown you edit directly
│ ├── home.md # the Home / forensic overview
│ └── about.md # context, thesis, how it was built/verified
├── assets/css/main.css # the theme (ported from refsworld) + syntax-{light,dark}.css
├── layouts/ # templates
│ ├── _default/_markup/render-link.html # the filename-based link resolver
│ ├── partials/{topbar,sidebar,toc,head}.html
│ ├── index.html # Home · list.html (section pages) · single.html (a page)
│ └── index.json # the search index
├── static/js/{theme,search}.js
└── content/ # GENERATED by build.py — do not edit (gitignored)
- Repo link / title / default theme →
hugo.toml[params](setgithubto the public repo). - Nav items / order →
hugo.toml[[menu.main]]. - Colours / fonts → the
:root(and[data-theme="dark"]) variables at the top ofassets/css/main.css. - Regenerate syntax stylesheets →
hugo gen chromastyles --style=github > assets/css/syntax-light.css(andgithub-darkwrapped in[data-theme="dark"]{ … }→syntax-dark.css).
The site publishes to GitLab Pages at https://<username>.gitlab.io/forefst/ from a GitLab project
named forefst — separate from your blog project, so it has its own pipeline. Two files (both in the repo
root) drive it:
.gitlab-ci.yml— the GitLab Pages job: runswebsite/build.py, thenhugo --minifywith the PagesbaseURL, and publishespublic/. Rebuilds on every push. EditBASEURLto your real URL..github/workflows/mirror-to-gitlab.yml— on every push, mirrors a clean source snapshot (with the large LFS-tracked lab disk images stripped out — GitLab doesn't need them) into the GitLabforefstproject, so GitLab rebuilds automatically. Needs aGITLAB_TOKENsecret (setup in the file header).
Sub-path (/forefst/) is handled: baseURL comes from the CI -b flag, and the search-index fetch is
base-aware (window.SEARCH_INDEX, injected in layouts/_default/baseof.html). To host on GitHub Pages
instead (https://<user>.github.io/<repo>/), point a GitHub Pages Action at build.py && hugo --minify.
- The reference pages still contain a few inline analysis terms (an occasional
(E2)/#327in prose); the footer block is removed, the inline bits will fade as you revise the docs content. - Figures: the bootstrap-chain + 13-roots figure is on the home page (the
bootstrap-rootsshortcode); more diagrams (B+-tree, version timeline) can be added understatic/img/and referenced from Markdown.