Date: 2026-04-25
Branch: feat/docs-site-cf-deploy
Status: Design — awaiting implementation plan
Goal
Add a public web presence for libfossil that mirrors the sibling project dagnats:
- A single-page landing site as a Hugo home-page layout override (
docs/site/layouts/index.html). - A documentation site built with Hugo + Hextra (
docs/site/). - Auto-generated Go API reference via
gomarkdoc. - Two
llms.txt-style artifacts for LLM consumption. - Cloudflare Workers Static Assets deployment, auto-deployed on every push to
mainvia Cloudflare's git integration (no GitHub Actions deploy step).
Non-goals
- No versioned docs (single live version follows
main). - No analytics, no comments, no auth.
- No GitHub Action for deployment — Cloudflare's git integration handles it.
- No changes to the existing
.github/workflows/test.ymltest pipeline.
Visual aesthetic
The dagnats live landing page sets the visual vocabulary, and libfossil reuses it verbatim. The look is a technical-manual / spec-sheet aesthetic — utilitarian, monospace, dual-mode:
- Dual-mode via
prefers-color-scheme— the page auto-switches between light and dark variants of the same design:- Light: paper
#f5f1e6(warm cream) on ink#14110b(warm black). - Dark: paper
#15140f(warm near-black) on ink#ece8dc(warm chalk).
- Light: paper
- Mono only. Geist Mono via Google Fonts drives every text element — wordmark, body, nav, metadata table, code, labels. There is no serif and no sans. The wordmark is an
<h1>styled with size and weight in the same Geist Mono. - Single accent: ember
#c63a0f(deep red-orange) — used sparingly: install-block$prompt, primary CTA hover, copy-button "copied" state, comparison-column highlight, link selection. - Layout idioms: §NN section numbering with anchor slugs (
§01,§02, …), hairline 1px rules in--ink, spec-sheet metadata table with single-line borders, COPY-on-click code blocks, narrow centered measure (--measure: 76ch).
Implementation reuses the dagnats CSS and HTML chrome verbatim — only the content underneath changes. The spec does not redefine the visual system.
Repository layout (post-implementation)
libfossil/
├── docs/
│ ├── site/ # Hugo site root
│ │ ├── hugo.yaml # Hextra theme config
│ │ ├── go.mod, go.sum # Hugo modules (Hextra)
│ │ ├── layouts/
│ │ │ └── index.html # landing page (Hugo home override, served at /)
│ │ ├── content/
│ │ │ ├── _index.md # docs site landing
│ │ │ ├── docs/
│ │ │ │ ├── _index.md
│ │ │ │ ├── quickstart.md # NEW
│ │ │ │ ├── architecture.md # MOVED from docs/
│ │ │ │ ├── extension-points.md # MOVED from docs/
│ │ │ │ ├── migration-from-fossil.md # MOVED from docs/
│ │ │ │ ├── testing.md # MOVED from docs/
│ │ │ │ └── reference/sdk/ # generated by gomarkdoc
│ │ │ │ ├── libfossil/api.md
│ │ │ │ ├── cli/api.md
│ │ │ │ ├── db/api.md
│ │ │ │ ├── db/driver/modernc/api.md
│ │ │ │ ├── db/driver/ncruces/api.md
│ │ │ │ ├── observer/otel/api.md
│ │ │ │ └── dst/api.md
│ │ │ └── examples/_index.md
│ │ ├── static/ # gitignored: gen-llms-txt output
│ │ └── public/ # gitignored: Hugo build output
│ └── superpowers/specs/ # this spec lives here
├── scripts/
│ └── gen-llms-txt.sh # ported from dagnats
├── wrangler.jsonc # CF Worker deploy config
└── Makefile # adds docs targets
The four existing files in docs/ (architecture.md, extension-points.md, migration-from-fossil.md, testing.md) move under docs/site/content/docs/. Single canonical location; avoids drift.
Component 1 — Landing page (docs/site/layouts/index.html)
The landing page is a Hugo home-page layout override — it replaces Hextra's default home template. Hugo compiles it into docs/site/public/index.html during hugo --minify, and Cloudflare Workers serves that file at /. The site nav and /docs/... pages continue to use Hextra layouts unchanged.
Approach: fork dagnats's docs/site/layouts/index.html — a self-contained HTML file (~21KB) with embedded CSS and vanilla JS and zero Hugo template directives. It lives in layouts/ only because that is the path Hugo serves at /, not because it interpolates Hugo data. Keep all CSS variables, fonts, layout primitives, COPY chrome. Rewrite the textual content for libfossil.
Section structure (one-to-one with the live dagnats landing):
| § | Section | libfossil content |
|---|---|---|
| — | Topbar | left wordmark LIBFOSSIL; right v0.4.1 · license MIT · github · docs |
| — | Hero | <h1>libfossil</h1> (Geist Mono, sized + weighted). Tagline: "A pure-Go library for Fossil SCM repositories. Zero CGo. Static binaries. WASM-ready." |
| — | Spec-sheet metadata table | rows: PROJECT, LANGUAGE, RUNTIME DEPS, BINARIES, LICENSE, STATUS |
| §01 | Install | go install github.com/danmestas/go-libfossil/cmd/libfossil@latest plus libfossil --help |
| §02 | What it is | 2 paragraphs — pure-Go reader/writer for .fossil SQLite repos; embeddable; WASM target via GOOS=wasip1 |
| §03 | Why you might want it | prose contrasting libfossil with shelling out to the upstream fossil binary, and with CGo bindings |
| §04 | How it fits together (architecture) | inline diagram for libfossil layers: CLI → Repo → Transport / DB Driver / Observers |
| §05 | Compared to neighbors (comparison) | short comparison: libfossil vs. shell-out vs. CGo bindings — covering deps, static binaries, WASM, observability, embeddability |
| §06 | What it is not (limits) | scope boundaries — what libfossil deliberately does not do (e.g., GUI, hosting, web UI) |
| §07 | Get going (CTA) | Read the docs · GitHub · Install copy block |
| — | Footer | license MIT · v0.4.1 · year · repo link |
Spec-sheet metadata values:
| Field | Value |
|---|---|
| PROJECT | libfossil — pure-Go Fossil SCM library |
| LANGUAGE | Go (module github.com/danmestas/go-libfossil) |
| RUNTIME DEPS | none · pluggable SQLite drivers (modernc · ncruces) |
| BINARIES | 1 (libfossil CLI) |
| LICENSE | MIT |
| STATUS | v0.4.1 · alpha · breaking changes possible |
Content prose is drafted during implementation from README.md and the existing docs/*.md files; the user iterates on the draft.
Component 2 — Docs site (docs/site/)
Hugo (extended) + Hextra theme via Hugo modules. Mirrors dagnats's hugo.yaml with three deltas:
title: libfossil- GitHub menu URL →
https://github.com/danmestas/go-libfossil editURL.base→https://github.com/danmestas/go-libfossil/edit/main/docs/site/content- Menu adds an
SDKentry pointing to/docs/reference/sdk/
Inherited from Hextra without modification: dark/light toggle (system default), edit-on-GitHub link, wide page width, FlexSearch (client-side, indexes content, forward tokenization).
Reading order (Hextra menu weights): Quickstart → Architecture → Migration from Fossil → Extension points → Testing → SDK → Examples.
Component 3 — Auto-generated SDK reference
gomarkdoc reads Go doc comments and writes Hextra-compatible markdown. Output is committed to the repo (so GitHub renders the pages and search engines index them); a pre-commit hook re-runs the generator and fails the commit if the working tree differs afterward, keeping committed pages in sync with the code.
make docs-gen-sdk:
docs-gen-sdk:
@command -v gomarkdoc >/dev/null || go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@latest
gomarkdoc --output docs/site/content/docs/reference/sdk/libfossil/api.md ./
gomarkdoc --output docs/site/content/docs/reference/sdk/cli/api.md ./cli/
gomarkdoc --output docs/site/content/docs/reference/sdk/db/api.md ./db/
gomarkdoc --output docs/site/content/docs/reference/sdk/db/driver/modernc/api.md ./db/driver/modernc/
gomarkdoc --output docs/site/content/docs/reference/sdk/db/driver/ncruces/api.md ./db/driver/ncruces/
gomarkdoc --output docs/site/content/docs/reference/sdk/observer/otel/api.md ./observer/otel/
gomarkdoc --output docs/site/content/docs/reference/sdk/dst/api.md ./dst/
Excluded: internal/ (unexported, not part of the public API surface).
Component 4 — scripts/gen-llms-txt.sh
Two artifacts written into docs/site/static/, served by Hugo at the site root:
/llms.txt— curated summary written inline as a heredoc. Sections: project blurb, Key Concepts (Repo, Transport, Driver, Observer, DST), Quick Start (4 steps), Go SDK Packages (7 entries), Documentation pointer./llms-full.txt— generated by walkingdocs/site/content/**/*.md, stripping YAML frontmatter, concatenating with# Source: <path>separators, prefixed with a UTC generation timestamp.
Both files are gitignored (build artifacts only). Invoked by make docs-gen-llms and again by the inline build in wrangler.jsonc, so the deployed site is always fresh.
Curated llms.txt content:
# libfossil
> Pure-Go library and CLI for Fossil SCM repositories.
> Zero CGo. Static binaries. WASM-ready.
## Key Concepts
- Repo — open .fossil SQLite-backed repository handle
- Transport — pluggable sync interface (HTTP, custom)
- Driver — pluggable SQLite implementation (modernc, ncruces)
- Observer — hooks for sync/checkout/commit (OpenTelemetry-ready)
- DST — deterministic simulation harness for fault injection
## Quick Start
1. go install github.com/danmestas/go-libfossil/cmd/libfossil@latest
2. libfossil clone <url> repo.fossil
3. Open from Go: repo, err := libfossil.Open("repo.fossil")
4. Sync: repo.Sync(ctx, transport)
## Go SDK Packages
- libfossil — Repo handle, Open/Create, public API
- cli/ — Kong command structs (embeddable)
- db/ — SQLite abstraction with pluggable drivers
- db/driver/modernc — pure-Go SQLite (default)
- db/driver/ncruces — Wasm-friendly SQLite
- observer/otel — OpenTelemetry integration
- dst/ — deterministic simulation harness
## Documentation
Full docs: <site URL — set once domain is configured>
Component 5 — Makefile additions
| Target | Action |
|---|---|
docs-serve |
cd docs/site && hugo server -D (local preview with drafts) |
docs-build |
cd docs/site && hugo --minify (production build) |
docs-gen-sdk |
as above |
docs-gen-llms |
bash scripts/gen-llms-txt.sh |
docs |
runs docs-gen-sdk → docs-gen-llms → docs-build, in order |
The docs-gen-sdk target is also wired into the existing setup-hooks pre-commit hook with a working-tree-drift check.
Component 6 — Cloudflare deploy (wrangler.jsonc)
Top-level wrangler.jsonc:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "libfossil-docs",
"compatibility_date": "2026-04-25",
"observability": { "enabled": true },
"assets": { "directory": "./docs/site/public" },
"build": {
"command": "curl -sSL https://github.com/gohugoio/hugo/releases/download/v0.160.0/hugo_extended_0.160.0_linux-amd64.tar.gz | tar xz hugo && bash scripts/gen-llms-txt.sh && cd docs/site && ../../hugo --minify"
},
"compatibility_flags": ["nodejs_compat"]
}
Build steps, in order:
- Download pinned Hugo extended (
v0.160.0— same pin as dagnats). bash scripts/gen-llms-txt.sh— refresh both llms artifacts from committed markdown.hugo --minify— write static output todocs/site/public/.- Wrangler serves
docs/site/public/via Workers Static Assets.
Drift protection comes from the pre-commit hook (Component 5), not from regenerating in CF. This matches dagnats's working setup exactly and keeps the CF build minimal and fast.
Component 7 — Auto-deploy mechanism
Cloudflare Workers' git integration handles auto-deploy. No GitHub Actions deploy step.
One-time operational steps (the user performs these in the CF dashboard):
- Workers & Pages → Create → Connect to Git → select
danmestas/libfossil. - Production branch =
main. Build command and output dir come fromwrangler.jsonc. - Default URL:
libfossil-docs.<cf-subdomain>.workers.dev. Custom domain attached later. - Preview-branch deploys: enable for PRs (free, useful for reviewing doc changes).
The existing .github/workflows/test.yml is unchanged. Tests and docs-deploy are independently triggered.
Open items not blocking design
- Custom domain — attached later via the CF dashboard; not required for v1.
- Content prose — drafted during implementation from
README.mdand existingdocs/*.md; user iterates. baseURLinhugo.yaml— left empty in v1 (matches dagnats); set once a custom domain is attached.
Out of scope (deferred)
- Versioned docs (multi-version selector).
- Analytics / comments / auth.
- A GitHub Action for deployment.
- Search beyond FlexSearch.
Testing strategy
Manual verification once implemented:
make docs-serverenders the site locally with the SDK pages and llms artifacts present.make docsproducesdocs/site/public/with all pages, search index, andstatic/llms*.txtartifacts.- The pre-commit hook fails when SDK pages are out of date and passes when they are in sync.
- CF deploy succeeds and the live URL serves the landing page at
/and the docs at/docs/.
Files added / changed / moved
Added:
docs/site/layouts/index.html(landing page, Hugo home-page layout override)docs/site/hugo.yaml,docs/site/go.mod,docs/site/go.sumdocs/site/content/_index.md,docs/site/content/docs/_index.md,docs/site/content/docs/quickstart.md,docs/site/content/examples/_index.mddocs/site/content/docs/reference/sdk/**/api.md(generated, committed)scripts/gen-llms-txt.shwrangler.jsonc
Changed:
Makefile(new docs targets, hook drift check).gitignore(docs/site/public/,docs/site/static/llms*.txt,docs/site/_vendor/,docs/site/hugobinary)
Moved:
docs/architecture.md→docs/site/content/docs/architecture.mddocs/extension-points.md→docs/site/content/docs/extension-points.mddocs/migration-from-fossil.md→docs/site/content/docs/migration-from-fossil.mddocs/testing.md→docs/site/content/docs/testing.md