A publishing engine for GEO resource pages — the pages large language models cite.
auto-geo is a content publishing primitive built for the AI search era. Where traditional CMSs optimize for human readers, auto-geo optimizes for citation by AI engines (ChatGPT, Perplexity, Google AI Overviews, Claude, Gemini). It enforces the structural and quality patterns that empirical research links to higher citation rates — TL;DR capsules, question-format H2 headings, answer-first paragraphs, dense entity references, FAQ schema, and a rigid page architecture — at the publish boundary.
Hand the URL of this repo to your coding agent. It will set up a publishing endpoint in your existing app that any other agent can call as a tool. You can then schedule, automate, or wire it into your own workflow.
Built by Shadow — a media research lab building the next generation of AI-powered media intelligence and communications technology, in partnership with the teams that put OpenAI, TikTok, Meta, Amazon, and Lovable on the map. Shadow uses
auto-geoto publish to shadow.inc/resources.
- What is a GEO resource page?
- Why auto-geo
- Install
- 60-second quickstart
- What's in this repo
- Quickstart (production setup)
- Examples
auto-geo doctor— audit any page for citation readinessauto-geo fix— rewrite a page for citation readinessauto-geo write— generate pages from queriesauto-geo check— measure actual citation coverage- The publishing flow
- Hard rejects vs. soft warnings
- How it compares
- API
- LLM-friendly
- Roadmap
- Contributing
- License
A GEO resource page (Generative Engine Optimization resource page) is a public web page whose structure, density, and citation signals are engineered to be quoted verbatim by AI search engines when answering a user's question. It is a successor to the SEO landing page.
A GEO resource page differs from a blog post in five ways:
- Architecture, not prose. The page is composed of named, validated blocks (TL;DR, intro, sections, related guides, key takeaways, FAQ, disclosure) — not a freeform document. AI engines extract structured chunks; rigid structure improves extraction.
- Answer-first. Every H2 section opens with a 40–60 word "answer capsule" that fully answers the section's question before any supporting paragraph. AI engines preferentially quote self-contained answers.
- Question-format headings. H2 headings are written as the questions a user would ask an AI engine. The page is indexed against query intent, not topic.
- Entity-dense. Named entities (companies, people, products, frameworks) appear at high density. Empirical studies link entity density to ~4.8x higher citation probability.
- Schema-derived. Article, BreadcrumbList, FAQPage, Person, and ImageObject JSON-LD are auto-emitted from a typed payload. The agent never writes JSON-LD by hand.
auto-geo enforces all five at the API boundary. Publishing is a contract; malformed pages are rejected with a structured error.
See docs/concept.md for a deeper walkthrough.
Markdown is freeform — there's no contract that a post has a TL;DR, that every H2 opens with a 40–60 word answer capsule, or that the FAQ exists. AI engines preferentially quote self-contained, structurally regular chunks, so a freeform Markdown corpus leaves citation probability on the table. auto-geo enforces the structure at the publish boundary so every page that ships is shaped for extraction, not just human reading.
Traditional and headless CMSs optimize for editorial workflow — drafts, scheduling, multi-user review, freeform field shapes. auto-geo is a typed publishing primitive that lives inside your own app and rejects malformed payloads with a structured error your agent can iterate on. It's downstream of editorial, not a replacement for it: pair it with a CMS if you need one, or generate payloads from an agent. Either way, the contract enforces GEO structure before the page goes live.
SEO optimizes for ranking in a link-based search results page; GEO optimizes for being quoted inside an AI-generated answer. The signals diverge — citation favors answer-first paragraphs, question-format H2s, entity density, and self-contained chunks; ranking historically rewarded backlinks and on-page keyword optimization. auto-geo enforces the citation signals empirically linked to higher inclusion rates in ChatGPT, Perplexity, Google AI Overviews, Claude, and Gemini answers — patterns most SEO tooling doesn't measure or enforce.
npm install auto-geo zodpnpm add auto-geo zodyarn add auto-geo zodInside a pnpm workspace? Use
pnpm add.npm installsometimes errors withCannot read properties of null (reading 'matches')when it traverses ancestorpnpm-lock.yamlfiles.
Node >=18.17 required. zod is a peer dependency. Framework / storage peers (next, hono, @vercel/kv, @supabase/supabase-js, react) are optional — install only what your adapter uses. One runtime dep is bundled: linkedom (pure-JS HTML parser, MIT, no native deps) powers the auto-geo doctor CLI.
Paste this into a fresh quickstart.ts, run with tsx quickstart.ts (or compile and run), and you'll see a published URL.
// quickstart.ts
import { runPublish } from "auto-geo";
import { createMemoryStore } from "auto-geo/storage/memory";
const store = createMemoryStore();
// A minimal payload satisfying every schema constraint.
const payload = {
slug: "hello-auto-geo",
title: "What is auto-geo and how do I publish my first resource page?",
metaDescription:
"A minimal first publish showing how auto-geo validates and stores a GEO resource page end to end.",
category: "Tutorials",
excerpt:
"A minimal first publish showing how auto-geo validates and stores a GEO resource page end to end.",
author: {
name: "Jane Doe",
jobTitle: "Head of Content",
bio: "Jane writes about generative engine optimization and the architecture of pages that AI search engines cite.",
},
publishedAt: "2026-06-01",
geoMetadata: {
targetQueries: ["how does auto-geo publishing work"],
pageType: "resource" as const,
primaryFunction:
"Show a developer how to publish their first resource page.",
optimizationFramework: ["GEO" as const],
targetPlatforms: ["chatgpt" as const],
informationGainStatement:
"First-party demonstration of the auto-geo publish pipeline using the in-memory store, end to end.",
refreshCadence: "quarterly" as const,
},
tldr: {
text: "Auto-geo's publish pipeline validates an incoming payload, persists it to a content store, and returns a URL plus an array of soft warnings; this minimal example wires the pipeline against an in-memory store so you can see a successful publish in your terminal in under a minute without any external services involved at all.",
},
intro: {
blocks: [
{
type: "paragraph" as const,
text: "This minimal payload satisfies every required field of the auto-geo schema; in a real integration you would generate this payload from an agent or your editorial pipeline and POST it to your publishing endpoint, but here we call the underlying runPublish function directly against an in-memory store to demonstrate the contract without any external network calls or storage setup.",
},
],
},
sections: [
{
heading: "How does the publish call work?",
answerCapsule:
"runPublish takes an unknown body plus options containing your store and site config; it parses the body against the Zod schema, calls store.publish on success, runs soft validation, and returns a discriminated-union result with a URL or an issues array so callers can act programmatically without parsing prose error messages.",
blocks: [],
},
],
relatedGuides: {
items: [
{
title: "The GEO SOP",
url: "https://github.com/shadowresearch/auto-geo/blob/main/docs/sop.md",
},
{
title: "Page architecture",
url: "https://github.com/shadowresearch/auto-geo/blob/main/docs/architecture.md",
},
{
title: "Validation reference",
url: "https://github.com/shadowresearch/auto-geo/blob/main/docs/validation.md",
},
{
title: "Storage adapters",
url: "https://github.com/shadowresearch/auto-geo/blob/main/docs/storage.md",
},
],
},
keyTakeaways: {
items: [
"Auto-geo enforces a strict seven-block architecture at the publish boundary so every published page is structurally citation-ready by design.",
"The runPublish function returns a discriminated-union result so callers branch on result.kind without parsing prose error strings ever.",
"Storage adapters are pluggable; the in-memory store ships for tests and demos, KV and Supabase ship for production deployments today.",
"Soft warnings come back on a successful publish so an agent can iterate on quality heuristics without being blocked by every non-critical recommendation.",
],
},
faq: {
items: [
{
question: "Do I need a database to try auto-geo?",
answer:
"No, the in-memory store ships with the package and persists publishes for the lifetime of the process; it is intended for tests, demos, and the quickstart you are running right now, and you swap in a KV or Supabase adapter when you go to production without changing any of your call sites.",
},
{
question: "What does the publish result look like?",
answer:
"On success runPublish returns an object shaped kind ok with a slug, a url constructed from your site origin plus the base path plus the slug, and an array of soft warnings from the audit step; on failure it returns one of validation_failed, slug_reserved, or store_failed, each carrying enough context for the caller to surface or retry.",
},
{
question: "How do I wire this into a real HTTP endpoint?",
answer:
"Import createNextHandlers from auto-geo/next or the Hono adapter from auto-geo/hono, pass your store and site config, and export the returned POST and DELETE handlers from your route file; the adapters wrap runPublish with auth and revalidation so your endpoint becomes a one-file integration instead of a hand-rolled pipeline.",
},
],
},
disclosure: {
text: "This quickstart is a runnable demonstration of the auto-geo publish pipeline using the in-memory store.",
},
};
const result = await runPublish(payload, {
store,
site: {
origin: "https://example.com",
publisher: {
name: "Example",
url: "https://example.com",
logo: "https://example.com/logo.png",
},
},
});
if (result.kind === "ok") {
console.log("Published:", result.url);
console.log("Warnings:", result.warnings.length);
} else {
console.error("Publish failed:", result);
}That's it — no database, no auth setup, no framework. Once you've seen Published: https://example.com/resources/hello-auto-geo in your terminal, follow the production setup below to wire it into your real app.
| Path | What it is |
|---|---|
AGENT.md |
The canonical setup spec. Hand this to your coding agent. |
core/ |
Framework-agnostic schema, publish logic, validation heuristics, JSON-LD derivation. Zero framework deps. |
adapters/storage/ |
Storage adapters — KV (Vercel KV / Upstash Redis), Supabase, in-memory. Implement the ContentStore interface. |
adapters/http/ |
HTTP adapters — Next.js App Router, Hono, Cloudflare Workers. Wrap core/publish as a request handler. |
components/react/ |
Reference React renderer. Restyleable Tailwind defaults; pluggable LinkComponent. |
cli/ |
auto-geo doctor — CLI that audits any URL (or a whole sitemap) for GEO citation readiness. See docs/doctor.md. |
mcp/ |
MCP server that wraps the publish endpoint as a tool. Any MCP client (Claude, Cursor, your own agent) can publish. |
examples/ |
Working example apps for Next.js, Hono on Bun, Cloudflare Workers, Express, SvelteKit, and Fastify. See Examples. |
docs/ |
The substantive product. The GEO SOP, page architecture spec, validation reference, storage adapter guide. |
tests/ |
Vitest suite covering schema, validation, JSON-LD, publish pipeline, memory store, and inline parser. |
Once you've run the 60-second quickstart above, this is how you wire auto-geo into a real app with a persistent store. The recommended path is to give this repo URL to your coding agent and let it read AGENT.md. If you want the short version:
# In an existing Next.js 15+ App Router project
pnpm add zod @vercel/kv
# Copy these files into your repo:
# - core/ → src/lib/auto-geo/core/
# - adapters/storage/kv.ts → src/lib/auto-geo/storage.ts
# - adapters/http/next.ts → src/app/api/resources/publish/route.ts
# - components/react/ → src/components/auto-geo/
# Set GEO_PUBLISH_TOKEN in .env.local (openssl rand -hex 32)
# Wire a /resources/[slug]/page.tsx that reads from your store and renders ResourceArticle.See examples/next-minimal/ for a working reference and AGENT.md for the step-by-step setup.
pnpm add auto-geo zod// app/api/resources/publish/route.ts
import { createNextHandlers } from "auto-geo/next";
import { createKvStore } from "auto-geo/storage/kv";
const handlers = createNextHandlers({
store: createKvStore(),
site: {
origin: "https://example.com",
publisher: {
name: "Acme",
url: "https://example.com",
logo: "https://example.com/logo.png",
},
},
});
export const POST = handlers.POST;
export const DELETE = handlers.DELETE;// app/resources/[slug]/page.tsx
import { ResourceArticle } from "auto-geo/react";
import { deriveAllJsonLd, safeJsonLd } from "auto-geo/jsonld";
// ... resolve payload from your store, then renderWorking minimal example apps for the most common backends. Each one
boots locally with pnpm install + the framework's dev script, ships
with an in-memory store seeded with one valid payload, and is tested
end to end against auto-geo@0.1.1 from npm.
| Framework | Path | Storage | Notes |
|---|---|---|---|
| Next.js (App Router) | examples/next-minimal | memory | Full render + publish |
| Hono (Bun) | examples/hono-bun | memory | Endpoint only — uses auto-geo/hono |
| Cloudflare Workers | examples/cloudflare-workers | memory | Endpoint only — uses auto-geo/cloudflare |
| Express | examples/express | memory | Endpoint only — runPublish inline |
| SvelteKit | examples/sveltekit | memory | Endpoint only — runPublish in +server.ts |
| Fastify | examples/fastify | memory | Endpoint only — runPublish inline |
next-minimal is the integration template — it has both the publish
endpoint and the React render path. The other four are endpoint-only:
they prove the publish contract on each backend with a sample curl,
and rely on next-minimal (or your own renderer) for HTML output. Each
example's README has a copy-pasteable curl for the canonical payload
and a verification step.
auto-geo ships with a CLI that audits any public webpage for GEO citation readiness. Run it on any URL — yours, a competitor's, every page in your sitemap — and get a structured report on the citation signals AI engines look for.
npx auto-geo@latest doctor https://example.com/some-pageauto-geo doctor — GEO citation readiness audit
fetched https://example.com/some-page (1,247 words)
✓ TL;DR present (52 words, in range)
✗ Question-format H2 headings (2 of 6 are question-format; SOP §3 targets all)
✓ Article JSON-LD present (Schema.org/Article JSON-LD found)
✗ FAQPage JSON-LD present (No FAQPage JSON-LD block detected)
✓ Entity density (12.3/1k words (49 entities in 1247 words))
✗ Image cadence (0 images for 1247 words (target ~2, 1 per 500 words))
✓ Answer-first first paragraph (96-word lede, leads with a declarative answer)
✓ No self-link in related guides (No self-links detected in related section)
Score: 5 / 8 checks pass — moderate GEO posture
Top 3 fixes (ranked by citation lift):
1. Add a FAQPage JSON-LD block. Each Q is a citable extraction target.
2. Convert 4 statement-form H2 headings to question form (the questions a user would ask an AI engine).
3. Add 2 images with descriptive alt text (entity + context).
Generated by auto-geo doctor (https://github.com/shadowresearch/auto-geo)
Run on your other pages: npx auto-geo doctor <url>
Learn more about GEO: https://www.shadow.inc/resources/what-is-geo
Three modes:
# Single page
npx auto-geo doctor https://example.com/page
# Whole sitemap — mean score, lowest-scoring pages, most common failures
npx auto-geo doctor --site https://example.com/sitemap.xml
# JSON for CI / dashboards (schema in cli/types.ts)
npx auto-geo doctor https://example.com/page --jsonExit code: 0 if score ≥ 75%, 1 otherwise. Drop it into CI:
npx auto-geo doctor https://example.com/page && deployUse cases:
- Audit your own page before deploy — gate publishes on a CI run that fails on regressions in citation signals.
- Audit a competitor's page — see the exact citation gaps in a competitor's resource library.
- Whole-site sweep — point
--siteat your sitemap and surface the lowest-scoring pages first. - Dashboard integration —
--jsonreturns a stable schema you can wire into Datadog, your internal admin, or your weekly GEO scorecard.
See docs/doctor.md for the full check reference, JSON schema, and programmatic API (runDoctor, runSitemapDoctor, auditHtml).
Where auto-geo doctor tells you what's wrong with a page, auto-geo fix produces a GEO-optimized rewrite that would pass all 8 doctor checks. The output is a typed ResourcePublishPayload validated against the same Zod schema your publish endpoint enforces, so it's ready to POST.
npx auto-geo@latest fix https://www.example.com/some-blog-post \
--out ./fixed.json \
--provider openai \
--model gpt-4o-miniauto-geo fix — generate a GEO-optimized rewrite
url: https://www.example.com/some-blog-post
fetched: 1,247 words
Audit (before):
✗ TL;DR present
✗ Question-format H2 headings (2 of 6)
✗ Article JSON-LD present
✗ FAQPage JSON-LD present
✓ Entity density (12.3/1k)
✗ Image cadence (0/page)
✓ Answer-first first paragraph
✗ Self-link detected
Score (before): 3 / 8
Generating rewrite via openai gpt-4o-mini...
Audit (projected for rewrite):
✓ TL;DR present (52 words)
✓ Question-format H2 headings (6 of 6)
✓ Article JSON-LD (auto-emitted by ResourceArticle renderer)
✓ FAQPage JSON-LD (auto-emitted)
✓ Entity density (18.1/1k)
✓ Image cadence (n/a — add via the publish endpoint)
✓ Answer-first first paragraph
✓ No self-link
Score (projected): 8 / 8 — strong GEO posture
→ ./fixed.json (validated by resourcePublishSchema)
Total: ~$0.04 estimated · 12s elapsed
Next steps:
1. Review ./fixed.json (especially TL;DR + FAQ — the citation-target chunks)
2. Publish to your endpoint
3. Re-audit: npx auto-geo doctor https://www.example.com/<new-slug>
The pipeline orchestrates fetch → audit → LLM generation → Zod validation → disk write. The LLM uses the Vercel AI SDK's generateObject with resourcePublishSchema as the typed-output target — so the model is constrained at the type-system level, not just by prose instructions. If the output still fails strict schema parsing, the Zod issues are fed back as a follow-up message and the call is retried (up to --max-retries, default 2).
# Anthropic instead of OpenAI:
export ANTHROPIC_API_KEY=sk-ant-…
npx auto-geo fix https://example.com/page --provider anthropic --model claude-sonnet-4-5
# Dry-run: fetch + audit + cost estimate, skip the LLM call:
npx auto-geo fix https://example.com/page --dry-run
# JSON for CI / dashboards:
npx auto-geo fix https://example.com/page --jsonTwo of the doctor checks — article-jsonld and faqpage-jsonld — pass automatically once the generated payload is published and rendered by <ResourceArticle>. core/jsonld.ts derives Article + BreadcrumbList + FAQPage + Person + ImageObject blocks from the structured fields, so the LLM doesn't need to generate any JSON-LD itself.
See docs/fix.md for the full flag reference, prompt template, cost model, and programmatic API (runFix).
auto-geo doctor tells you whether a page is citation-ready. auto-geo write produces a page that already passes the audit. Give it your domain and the queries you want to be cited for; get back validated, publish-ready JSON files.
export OPENAI_API_KEY=sk-… # or ANTHROPIC_API_KEY=… with --provider anthropic
npx auto-geo@latest write \
--domain https://www.shadow.inc \
--query "what is GEO" \
--query "GEO vs SEO" \
--query "how to get cited by ChatGPT" \
--out ./resourcesauto-geo write — generate publish-ready resource pages from target queries
domain: https://www.shadow.inc
queries: 3
provider: openai (gpt-4o-mini)
✓ "what is GEO"
→ ./resources/geo.json (validated, ~$0.06)
✓ "GEO vs SEO"
→ ./resources/geo-vs-seo.json (validated, ~$0.06)
✓ "how to get cited by ChatGPT"
→ ./resources/get-cited-chatgpt.json (validated, ~$0.06)
Total: 3 pages · 3 ok · ~$0.18 spent · 47s elapsed
Each JSON file is validated against the canonical resourcePublishSchema — the same schema your publish endpoint enforces — so a successful write is guaranteed-publishable. POST them to your endpoint or commit them to your content store.
The system prompt encodes the GEO SOP (TL;DR length, answer-capsule windows, banned superlatives, FAQ structure, related-guides count, …) and the soft heuristics from auto-geo doctor (question-format H2s, entity density ≥ 8/1k words, image cadence). The Vercel AI SDK's generateObject constrains output to the Zod schema; we re-validate with the canonical schema defense-in-depth and feed the issues back to the LLM as a bounded self-correction loop on failure.
# Try it before paying — shows the plan + cost estimate, no LLM calls
npx auto-geo write --domain https://example.com --query "what is X" --dry-run
# Multiple providers
npx auto-geo write --domain … --query … --provider anthropic --model claude-sonnet-4-6
# A whole batch from a file
echo "what is GEO\nGEO vs SEO\nhow do I rank in AI Overviews" > queries.txt
npx auto-geo write --domain https://example.com --queries-file queries.txtSee docs/write.md for the full flag reference, the system prompt, cost-model details, and the programmatic API (runWrite).
Where doctor grades a page for citation readiness, check measures the citation outcome: for a list of queries, do AI search engines actually surface your domain?
export PERPLEXITY_API_KEY=pplx-xxxx
npx auto-geo@latest check \
--domain shadow.inc \
--query "what is GEO" \
--query "how do I get cited by ChatGPT" \
--query "open source GEO tools" \
--engine perplexityauto-geo check — measure citation coverage in AI search engines
domain: shadow.inc
queries: 3
engine: perplexity (sonar)
[1/3] "what is GEO"
✗ shadow.inc NOT cited (5 sources: arxiv.org, searchengineland.com, …)
[2/3] "how do I get cited by ChatGPT"
✓ shadow.inc cited — 2 pages
· https://www.shadow.inc/resources/get-cited-by-ai-search (rank 1 of 6)
· https://github.com/shadowresearch/auto-geo (rank 4 of 6)
[3/3] "open source GEO tools"
✓ shadow.inc cited — 1 page
· https://github.com/shadowresearch/auto-geo (rank 2 of 4)
Coverage: 2/3 queries (67%) · 3 page citations total · ~$0.012 spent
Exit code: 0 if coverage > 0%, 1 if 0%. Drop into CI to fail deploys when none of your critical queries cite you:
npx auto-geo check --domain shadow.inc --queries-file geo/critical-queries.txt && deployEngines today:
perplexity(default) — full Perplexity Sonar API integration. RequiresPERPLEXITY_API_KEY.--model sonar-profor the higher-quality tier.openai— scaffolded but not yet wired (throws "not yet implemented"). The Responses-APIweb_search_previewcitation parser is in place; the HTTP call lands in a follow-up.
See docs/check.md for the full flag reference, JSON schema, domain-matching rules, rank semantics, and CI examples.
┌─────────────────┐ POST /api/resources/publish ┌──────────────────┐
│ Your agent │ ───────────────────────────────▶ │ Your Next/Hono │
│ (Claude, your │ Bearer GEO_PUBLISH_TOKEN │ app │
│ custom tool, │ JSON body: ResourcePayload │ │
│ Shadow, etc.) │ │ validate (Zod) │
└─────────────────┘ │ audit (soft) │
│ store.publish() │
│ revalidate │
└────────┬─────────┘
│
┌────────────────▼─────────────┐
│ /resources/[slug] page │
│ - ResourceArticle render │
│ - Article + FAQPage JSON-LD │
│ - canonical, OG, Twitter │
└──────────────────────────────┘
The publishing endpoint is the contract. Anything that can issue an authenticated POST can publish — your own scheduled job, an MCP-aware AI client, a CLI, a webhook. auto-geo does not prescribe how content is generated or when it's published. That's your moat.
auto-geo distinguishes between structural violations (rejected with HTTP 400) and quality heuristics (returned as warnings[] on a 200 response). The split is deliberate: structure is a contract; quality is a continuum.
Hard rejects include: missing required blocks, TL;DR not 40–60 words, FAQ answer not 40–60 words, related-guides count outside 4–8, key-takeaways count outside 4–6, banned promotional superlatives without attribution, raw HTML in prose fields, invalid URLs.
Soft warnings include: section length outside 134–167 words, paragraph length outside 60–100 words, entity density below 15, statistics density below page-type target, image cadence below 1 per 500 words, H2 heading not in question format, self-link in related guides.
Your agent can iterate on soft warnings by re-posting an updated payload (republishing overwrites by slug). Or surface the warnings to the user and ship as-is. See docs/validation.md for the full reference.
| Traditional CMS | Headless CMS | auto-geo |
|
|---|---|---|---|
| Optimized for | Human reading | Multi-channel delivery | AI engine citation |
| Content shape | Freeform prose | Freeform with custom fields | Validated 7-block architecture |
| Validation | Editorial review | Schema-light | Strict Zod at publish boundary |
| Schema.org | Manual | Manual or plugin | Auto-derived from payload |
| Agent integration | Custom | Custom | First-class (MCP, REST) |
| Storage | Bundled | Bundled or hosted | Pluggable adapter (your choice) |
| Lock-in | High | Medium | None — copy the files |
auto-geo is not a CMS. It is a typed publishing primitive that lives inside your app. If you need editorial workflows, drafts, scheduled publish, multi-user collaboration, or a media library, pair it with a CMS — auto-geo is downstream of the editorial process, not a replacement for it.
The publish endpoint contract is described as an OpenAPI 3.1 document at openapi.yaml. It covers the two operations the reference adapters expose:
POST /api/resources/publish— validate, persist, and revalidate aResourcePublishPayload.DELETE /api/resources/publish?slug={slug}— remove a previously published resource.
The point isn't a hosted endpoint — there isn't one. The point is to give any HTTP client (Postman, Insomnia, ChatGPT Custom GPT Action, Claude with HTTP tools, your own typed client generator) a machine-readable description of the contract you're mounting in your own app via createNextHandlers or createHonoRouter. See docs/architecture.md for the architectural spec the schema enforces and docs/validation.md for the hard-reject / soft-warning split.
auto-geo is, in essence, a tool whose output is content meant to be cited by LLMs. So this repo eats its own dogfood — it's discoverable by AI agents and crawlers in the same ways it teaches you to make your own pages discoverable.
llms.txt— a curated index of the most important content in the repo, following the llmstxt.org convention. Hand the URL to any LLM and it gets a fast, structured map of the project.llms-full.txt— the expanded variant. Inlines the README plus every substantive doc (concept, SOP, architecture, validation, storage adapters) into a single file so an LLM can ingest the whole project in one fetch.openapi.yaml— machine-readable contract for the publish endpoint, usable by any HTTP-tool-aware AI client.- GitHub Pages site at shadowresearch.github.io/auto-geo — every page advertises
llms.txt,llms-full.txt, andopenapi.yamlvia<link rel="alternate" type="text/plain">tags in the<head>, emits JSON-LDArticlemarkup, and carries a "Built with auto-geo" footer.
Tracked in GitHub issues. Headline items for v0.2+:
- Additional HTTP adapters: Express, Fastify, Elysia.
- Additional storage adapters: Postgres (direct), DynamoDB, Cloudflare D1.
- A canonical Vue/Svelte renderer parity with React.
- A standalone CLI for publishing from scripts and CI pipelines.
- Audit / "page health" command that re-runs
auditResourceagainst all stored pages on a schedule. - An optional
geo-metafield for indexing recipes (semantic anchors, query-cluster routing).
Have a proposal? Open a feature request.
See CONTRIBUTING.md. Bug reports, schema improvements, new adapters, and documentation refinements all welcome.
Quick links:
MIT. The reference React components include a default "Built with auto-geo by Shadow" credit in the disclosure block; pass disclosureSuffix={null} to suppress, or override with your own JSX.
- The GEO SOP —
docs/sop.md. The full standard operating procedure for GEO resource pages. This is the substantive product. - Page architecture —
docs/architecture.md. Spec for the seven mandatory blocks. - Shadow — shadow.inc. The media research lab building the next generation of AI-powered media intelligence and communications technology, in partnership with the teams that put OpenAI, TikTok, Meta, Amazon, and Lovable on the map. Shadow runs
auto-geoend-to-end on a schedule for media research, PR, and communications teams.
Shadow is a media research lab building the next generation of AI-powered media intelligence and communications technology. Shadow is built in partnership with the teams that put OpenAI, TikTok, Meta, Amazon, and Lovable on the map.
Learn more at shadow.inc.