The go-audit docs had two copies of the truth
Collapsing the go-audit docs onto a single MDX source, documenting the Store interface that was missing, code blocks that mean something, and the same LLM-friendly endpoints.
This is the third docs overhaul in a row — go-migration, then open-swaggo, now go-audit. The first had drifted. The second had drifted into fiction. go-audit’s problem was quieter and, honestly, more my own fault: the docs had two ways of rendering the same page, and the two had stopped agreeing.
Two renderers, one set of facts
Most of the site is MDX — Markdown with a few components. But a handful of the
heavier pages had been hand-built as bespoke React/TSX components instead:
getting-started/quick-start, api-reference, adapters/overview,
features/api-logging, features/snapshot-restore. They looked nicer for a
while. Then the MDX versions of those same pages got edited, the TSX versions
didn’t, and the site quietly started serving whichever one the router resolved
first.
That’s the worst kind of docs bug, because nothing is wrong on the page you’re looking at — it’s just not the same as the page next to it. Two sources of truth is a synonym for zero.
So I deleted the bespoke TSX pages. Every doc now renders from its MDX file and nothing else.
The page that was missing
While realigning everything against the package, one omission stood out:
go-audit’s entire persistence model runs through a Store, and there was no
page for it. Every Auditor writes through a Store — there’s a
database/sql-backed one by default, an in-memory one for tests, and you can
supply your own. That’s a core extension point, and it was undocumented.
So there’s a new Store Interface page covering the actual interface:
type Store interface { SaveDataLog(ctx context.Context, table string, log AuditLog) error SaveAPILog(ctx context.Context, table string, log AuditAPILog) error QueryDataLogs(ctx context.Context, table string, filter DataFilter) ([]AuditLog, error) QueryAPILogs(ctx context.Context, table string, filter APIFilter) ([]AuditAPILog, error) Purge(ctx context.Context, table string, before time.Time) (int64, error) Exec(ctx context.Context, stmt string) error }
…the two built-in constructors (NewSQLStore, NewMemoryStore), how to wire a
custom one through audit.NewWithStore, and — the part that actually matters —
the contract a custom store has to honor: filter on every non-zero field,
return rows newest-first, respect Limit/Offset, and purge strictly older
than the cutoff. The rest of the reference pages got the usual drift pass so the
signatures match the real package.
Code blocks that mean something
A smaller change, but one I’ve wanted across all the gopackx docs: code blocks now carry meaning instead of all looking identical. The renderer keys off the fence language and picks one of three treatments:
macOS-style window — traffic lights, filename, language label, footer with line + char count.
Plain block — copying a command is the whole point, so the chrome stays minimal.
You don't paste a program's output back into a terminal, so offering to copy it is just noise.
It’s a small thing. Small things are most of what separates docs you trust from docs you tolerate.
Docs for humans and machines
The LLM-friendly layer is the same one go-migration and open-swaggo got, now on go-audit:
/llms.txt— a compact index of the docs for crawlers./llms-full.txt— the whole site as one clean Markdown file.- Raw Markdown per page — every page is served as plain Markdown under
/llms/..., with the frontmatter stripped and a title + URL header prepended so a model gets clean, self-describing text instead of HTML. - A “Copy as Markdown” button — grabs that raw Markdown and puts it on your clipboard.
- An “Open in LLM” dropdown — “View raw Markdown”, or open the page straight in ChatGPT or Claude with a prompt that points the model at the raw URL.
Because the raw route reads the same MDX file the page renders from, the machine view and the human view can’t drift apart — which, after spending this update deleting a second renderer, is a property I now care about a lot.
Three down
The pattern across all three has settled into one sentence: documentation is a promise, and the failure modes are just different ways of breaking it — drift, fiction, or quietly keeping two copies and letting them diverge. go-audit was the third. The docs now render from one source, document the parts that were missing, and read cleanly to both people and models.
If you’re using go-audit and something in the docs doesn’t match the package, that’s a bug — tell me on the repo.