A full SEO + GEO site audit as one workflow file.
Discover, crawl bounded, score deterministically, one narrated verdict,
artifacts as receipts. Checked before a single request leaves your machine.
This diagram is generated by nika graph site-audit.nika.yaml --format mermaid,
not drawn by hand. Eleven tasks, five waves:
graph TD
robots["robots · invoke · nika:fetch"]
llmstxt["llmstxt · invoke · nika:fetch"]
sitemap["sitemap · invoke · nika:fetch"]
crawl["crawl · invoke · nika:fetch"]
rubric["rubric · invoke · nika:read"]
geo_score["geo_score · invoke · nika:jq"]
seo_score["seo_score · invoke · nika:jq"]
scorecard["scorecard · invoke · nika:chart"]
verdict["verdict · infer · mock/echo"]
report["report · invoke · nika:write"]
done["done · invoke · nika:log"]
crawl --> seo_score
geo_score --> report
geo_score --> scorecard
geo_score --> verdict
llmstxt --> geo_score
report --> done
robots --> geo_score
rubric --> verdict
scorecard --> report
seo_score --> report
seo_score --> scorecard
seo_score --> verdict
sitemap --> seo_score
verdict --> report
One model call in the whole pipeline (verdict). Everything else is
deterministic: fetches, jq scoring, a chart, a report. That is the point.
brew install supernovae-st/tap/nika # single binary
nika check site-audit.nika.yaml # the audit BEFORE the audit:
# plan · cost floor · permits · secret flows
nika run site-audit.nika.yaml # offline verdict (mock model) · artifacts in out/
nika test site-audit.nika.yaml # the committed golden guards the outputsLive run against your own site, with a real model · local first, nothing leaves your machine but the audit itself:
nika run site-audit.nika.yaml \
--var url=https://your-site.com \
--model ollama/qwen3:8b # any provider/model works the same way:
# mistral/mistral-medium-latest ·
# anthropic/claude-sonnet-4-6 (needs its env key · `nika doctor`)Note the permits: block in the workflow pins the network to the audited
host. Widen it when you change vars.url; everything else stays default-deny.
| Wave | Tasks | What happens |
|---|---|---|
| 1 | robots llmstxt sitemap crawl rubric |
GEO discovery in parallel: robots.txt, llms.txt, sitemap.xml, plus a bounded same-origin crawl (8 pages, robots respected). A missing file is a finding, not a crash |
| 2 | geo_score seo_score |
deterministic scoring in jq: AI-crawler access, llms.txt presence, titles, canonicals, status codes |
| 3 | scorecard verdict |
a chart artifact from the scores, and the one LLM call: the narrated verdict, grounded in the rubric |
| 4-5 | report done |
everything folds into out/report.html + out/scorecard.svg |
Every run writes a hash-chained trace. nika trace verify exits 0 or names
the first broken link: the receipt comes from the runtime, not from the
model's prose.
The interesting failures in an audit pipeline happen before the model is
called: a crawl that hammers a site, a secret that leaks into a prompt, a
cost that surprises you. nika check catches those statically, and the
permits: boundary makes the blast radius readable in the file itself.
The model gets exactly one job: narrate the verdict from scores computed
deterministically.
legacy/site-audit-v10.nika.yaml preserves the original 1072-line pipeline
(April 2026, the brouillon era — the draft engine the Diamond rewrite
retired): 50 tasks, 22 layers, locale detection across 38 locales, an
interactive 10-tab dashboard, AI-generated imagery and a podcast narration.
It ran against the pre-rewrite nikab binary in the retired pre-v1 dialect
and does not parse on current engines, by design. Recorded legacy-era results:
| Site | Pages | Locales | Tasks |
|---|---|---|---|
| qrcode-ai.com | 1,654 | 38 | 50/50 |
| htmx.org | 278 | 1 | 50/50 |
| tailwindcss.com | ~1,900 | 1 | 50/50 |
Keep it as evidence of scale and a design archive. Do not learn the syntax from it; the current language is the public spec. The full era model — exploration · brouillon · diamond — is the machine-verified timeline.
| File | What it is |
|---|---|
site-audit.nika.yaml |
the v1 workflow: 11 tasks, declared permits, offline by default |
site-audit.nika.yaml.golden.json |
the committed golden: nika test compares typed outputs against it |
skills/ |
the audit rubric the verdict is grounded in |
legacy/ |
the brouillon-era showcase (April 2026), read-only |
prototypes/ |
exploration, not the product |
Docs: docs.nika.sh · Engine (AGPL-3.0): nika · Templates: nika-starter · nika-actions-starter