Skip to content
go-libfossil Artifact [0d7a426695]
Login

Artifact [0d7a426695]

Artifact 0d7a4266955ed729d9cb262dd58e43eee6e95e4b5c0d7cec7175a28263f04ddf:


# libfossil docs site + landing page + Cloudflare auto-deploy

**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`](https://github.com/danmestas/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 `main` via 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.yml` test 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).
- **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/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/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/libfossil`
- `editURL.base` → `https://github.com/danmestas/libfossil/edit/main/docs/site/content`
- Menu adds an `SDK` entry 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`:

```make
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 walking `docs/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/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`:

```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:

1. Download pinned Hugo extended (`v0.160.0` — same pin as dagnats).
2. `bash scripts/gen-llms-txt.sh` — refresh both llms artifacts from committed markdown.
3. `hugo --minify` — write static output to `docs/site/public/`.
4. 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):

1. Workers & Pages → Create → Connect to Git → select `danmestas/libfossil`.
2. Production branch = `main`. Build command and output dir come from `wrangler.jsonc`.
3. Default URL: `libfossil-docs.<cf-subdomain>.workers.dev`. Custom domain attached later.
4. 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.md` and existing `docs/*.md`; user iterates.
- **`baseURL` in `hugo.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:

1. `make docs-serve` renders the site locally with the SDK pages and llms artifacts present.
2. `make docs` produces `docs/site/public/` with all pages, search index, and `static/llms*.txt` artifacts.
3. The pre-commit hook fails when SDK pages are out of date and passes when they are in sync.
4. 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.sum`
- `docs/site/content/_index.md`, `docs/site/content/docs/_index.md`, `docs/site/content/docs/quickstart.md`, `docs/site/content/examples/_index.md`
- `docs/site/content/docs/reference/sdk/**/api.md` (generated, committed)
- `scripts/gen-llms-txt.sh`
- `wrangler.jsonc`

**Changed:**
- `Makefile` (new docs targets, hook drift check)
- `.gitignore` (`docs/site/public/`, `docs/site/static/llms*.txt`, `docs/site/_vendor/`, `docs/site/hugo` binary)

**Moved:**
- `docs/architecture.md` → `docs/site/content/docs/architecture.md`
- `docs/extension-points.md` → `docs/site/content/docs/extension-points.md`
- `docs/migration-from-fossil.md` → `docs/site/content/docs/migration-from-fossil.md`
- `docs/testing.md` → `docs/site/content/docs/testing.md`