Maintaining These Docs

How to keep this site current — conventions, the auto-sync pipelines (plans + tool catalog), the doc-freshness discipline, and the build/deploy rules. Read this before editing pages.

This page is for whoever is editing this site — most often a Leif session Wayne has asked to update a page, sometimes a human with a clone. It exists so the docs keep their shape and don’t rot: the conventions to follow, the parts that are auto-generated (don’t hand-edit those), and the discipline that keeps facts trustworthy.

The golden rules

  1. main is production. A commit to main triggers a Cloudflare Pages build and goes live in a minute or two. Push to a branch for a preview.
  2. Don’t hand-edit generated content. The plans pages and the tool catalog are produced by jobs — edit the source, not the output.
  3. Date what you touch. When you change an infrastructure page, update its freshness footer (below).
  4. Verify before you assert. Most facts here are confirmable with a Leif tool. Prefer a quick check over a guess; mark unknowns rather than inventing.
  5. Don’t bump pinned dependencies casually — see build & deploy.

Repo structure

Content is Markdown/MDX under src/content/docs/, grouped by section folder. The folder is the URL prefix and the sidebar group:

FolderSectionURL
overview/Overview/overview/...
infrastructure/Infrastructure/infrastructure/...
patterns/Patterns/patterns/...
runbooks/Runbooks/runbooks/...
tools/Tools/tools/...
plans/Plans (auto-synced)/plans/...

The sidebar is generated from these folders by src/layouts/BaseLayout.astro — section order and labels live in the sectionOrder / sectionLabels arrays there. Adding a new top-level section means adding it to those arrays, or it lands in a catch-all group at the bottom.

Writing a page

Every page is Markdown with frontmatter:

---
title: Short Title
description: One sentence — used for the <meta> description and link previews.
order: 3        # position within the section sidebar (index pages sort first)
---

Conventions to match:

  • Voice. Dry, concise, direct. Lead with the answer. Surface the gotcha early. Don’t pad. (It’s the house style — read any existing page.)
  • Callouts. Use a :::callout::: block for the one thing a reader must not miss. This renders as a styled aside via remark-directive (wired in astro.config.mjs + src/remark-callout.mjs). The literal :::callout spelling matters — a space (::: callout) will not render.
  • Cross-link. End with a ## Related pages list. Link liberally between tools ⇄ patterns ⇄ runbooks ⇄ infrastructure — the cross-links are most of what makes the site usable.
  • Tables and code. Tables for param/field references; fenced code for tool calls and signatures. Escape literal | inside tables.

New-page checklist

  • File in the right section folder, with title / description / order
  • Voice and structure match the neighbouring pages
  • :::callout for the key caveat (correct spelling)
  • ## Related pages with at least a couple of links, and inbound links added from related pages so it’s discoverable
  • npm run build passes, no broken internal links
  • Committed to main (or a preview branch) with a clear message

Auto-synced & generated content

Two parts of the site are produced by jobs. Editing the output directly is pointless — it gets overwritten.

Plans (auto-synced)

The Plans pages mirror superhitech/leif:docs/plans/. A scheduled Leif job, leif-docs-plans-sync (daily ~06

), reads those .md files, adds the standard frontmatter, and commits changes here. Edit a plan in the Leif repo, not on this site — a manual edit to a synced plan page is transient. (list_scheduled_jobs() shows the job.)

The tool catalog (generated)

/tools/catalog/ is generated from the live FastMCP tool schemas. The pipeline:

  1. Introspection (Leif side). A job introspects the running FastMCP server and writes scripts/tools-catalog.json (the JSON contract is documented at the top of scripts/generate-tool-catalog.mjs).
  2. Generation (this repo). npm run gen:tools reads that JSON and writes src/content/docs/tools/catalog.md. A prebuild hook runs it automatically, so Cloudflare regenerates on every deploy.

When a tool is added, renamed, or its signature changes:

  • The generated catalog updates itself once scripts/tools-catalog.json is refreshed (by the introspection job, or by hand for a quick fix).
  • The curated namespace page (e.g. /tools/cwa/) is hand-written prose and must be updated by hand — that’s where the gotchas and examples live. Keep its signatures in step with the server.

Doc freshness

Infrastructure facts drift. Each infrastructure page carries a dated footer so staleness is visible:

---

*Last verified against live systems: YYYY-MM-DD — see [doc freshness](/infrastructure/#doc-freshness).*
  • “reviewed” = read through and looked correct on that date.
  • “verified” = the values were re-checked against the live source.

When you touch one of these pages, update the date. Better, verify and use the verified wording — most facts are one tool call away:

To confirm…Use
Proxmox node / guests / storagepve_node_status, pve_lxc_list, pve_vm_list, pve_storage_list
A container’s IPpve_lxc_exec(node="pve", vmid=N, command="hostname -I")
UniFi fleetunifi_status
DNS / zones / SSLcf_list_zones, cf_list_dns_records, cf_get_ssl_mode
Anything on a hostthe host’s shell tool (local_* / remote_* / shtops_* / pve_lxc_exec)
RS customer IDs / recordsrepairshopr_get

Build & deploy

  • Local: npm install then npm run dev (→ http://localhost:4321).
  • Build: npm run build. The prebuild hook regenerates the tool catalog first. Always build before pushing — a bad page fails the Cloudflare build and blocks the deploy (see Docs site deploy failure).
  • Deploy: commit to main → Cloudflare Pages builds and publishes. No manual step.
  • Dependencies are pinned on purpose (Astro 5.18 / Zod v4 / Starlight 0.30 incompatibility). Don’t bump without a local build passing first.

Editing through Leif

Most edits happen via Leif’s github_* tools rather than a clone:

  • github_get_file / github_search_code to read and find
  • github_create_or_update_file to write (commit message required) — writing to branch="main" deploys
  • github_batch_move_files to reorganize in one commit

See github and Cloudflare Pages Deploys.