Skip to main content

Generate llms.txt, aeo.json, entity.json, and brand.json from a single site config — AI citation engineering for static + dynamic sites.

Project description

aio-surfaces

Generate llms.txt, aeo.json, entity.json, and brand.json from a single site config. AI citation engineering for static and dynamic sites.

PyPI Python 3.10+ License: MIT


What this is

Most sites are invisible to AI engines (ChatGPT, Claude, Gemini, Perplexity, Google AI Overviews) because they expose prose when AI engines want structured facts. The single biggest lift you can give an AI's chance of citing your site is to surface:

  • a well-formed llms.txt (llmstxt.org) — markdown summary at the site root
  • an aeo.json — atomic [question, answer] facts under 500 chars each
  • an entity.json — Schema.org @graph with full identifier wiring (EIN, ORCID, UEI, KG MID, etc.)
  • a brand.json — internal source-of-truth ledger

This package generates all four from a single typed config so they can't drift apart.

Install

pip install aio-surfaces        # core
pip install 'aio-surfaces[yaml]' # YAML config support

Quick start

Drop a site.yaml in your repo:

site_name: Example Studio
site_url: https://example.com
tagline: We build things that get cited.
description: Example Studio designs and engineers...
legal_name: EXAMPLE STUDIO LLC
ein: "12-3456789"
uei: ABC123DEF4G5
naics: ["541511"]
orcid: "0000-0000-0000-0000"
founder_name: Jane Example
veteran_branch: United States Army
veteran_subgroups: [Veteran]
services:
  - name: Custom Websites
    url: https://example.com/services/websites/
    summary: Hand-coded HTML, React, Astro.
    price: $2,500–$10,000 one-time
facts:
  - id: f-identity-1
    question: What does Example Studio do?
    answer: >
      Example Studio builds production websites and AI-citation
      infrastructure for small businesses.

Then generate the surfaces:

aio-surfaces generate site.yaml --out ./public

Output:

public/
├── llms.txt         # markdown summary, llmstxt.org spec
├── aeo.json         # atomic facts (AEO)
├── entity.json      # Schema.org @graph (Org + Person + WebSite)
├── brand.json       # internal brand truth ledger
└── robots-aibots.txt # 12 AI crawler allowlist (append to robots.txt)

Deploy public/ to your site root.

Why each surface matters

File Crawled by Why it works
llms.txt ChatGPT, Claude, Perplexity Markdown is the lingua franca of LLM training data. Direct quotes likely.
aeo.json All major AI engines Atomic [Q, A] under 500 chars matches how AI engines extract citations.
entity.json Google KG, Bing, Schema.org consumers Centralizes identifier graph (EIN, UEI, ORCID, KG MID) for one-fetch retrieval.
brand.json AI engines + your own team Source of truth your PR/marketing/dev can all reference.

Library API

from aio_surfaces import SiteConfig, Service, Fact, render_llms_txt

cfg = SiteConfig(
    site_name="Example Studio",
    site_url="https://example.com",
    tagline="We build things that get cited.",
    description="...",
    services=[
        Service(
            name="Custom Websites",
            url="https://example.com/services/websites/",
            summary="Hand-coded HTML, React, Astro.",
        ),
    ],
    facts=[
        Fact(
            id="f-1",
            question="What does Example Studio do?",
            answer="Example Studio builds...",
        ),
    ],
    ein="12-3456789",
    orcid="0000-0000-0000-0000",
)

print(render_llms_txt(cfg))

Design principles

  1. Atomic facts > paragraphs. AI engines cite spans, not essays. The Fact dataclass enforces a 1000-char hard ceiling and recommends < 500.
  2. Single source of truth. All four surfaces render from one config so they can't drift apart.
  3. No magic. No analytics, no telemetry, no remote calls. Pure-Python stdlib + optional PyYAML.
  4. Run anywhere. Works in CI, in a Makefile, as a pre-commit hook, or as a one-off CLI invocation.

What this is not

  • Not a CMS. It generates static files from a config; you deploy them.
  • Not a Schema.org validator. (Run the output through validator.schema.org yourself.)
  • Not an opinionated framework. Generate what you need; ignore the rest.

Roadmap

  • aio-surfaces validate — round-trip the output through Schema.org validator
  • aio-surfaces diff — show what changed since the last generation (CI hook)
  • Per-page aeo.json support (currently site-wide only)
  • llms-full.txt expanded variant generation
  • Hugo / Astro / Next.js plugin packages

Contributing

Issues + PRs welcome. The codebase is small (~350 LOC) and has full test coverage:

pip install -e '.[test]'
pytest

License

MIT © 2026 Joseph W. Anady. See LICENSE.


Built and used in production by ThatDevPro — SDVOSB-certified veteran-owned web + AI engineering studio. The generators here are the same code that runs across ThatDeveloperGuy.com, ThatDevPro.com, and 130+ client sites on ThatWebHostingGuy.com.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aio_surfaces-0.2.0.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aio_surfaces-0.2.0-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

Details for the file aio_surfaces-0.2.0.tar.gz.

File metadata

  • Download URL: aio_surfaces-0.2.0.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for aio_surfaces-0.2.0.tar.gz
Algorithm Hash digest
SHA256 2a86ff28a6156e503cae74ebb958511005052dd72bb7f91903ef9af98b344439
MD5 925e7f4011b19afc5fc7058441fb3799
BLAKE2b-256 f5c2ca0dba100f728c90a839124e7e63559055023ef2a69148117bdc8c4b5dc0

See more details on using hashes here.

File details

Details for the file aio_surfaces-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: aio_surfaces-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 11.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for aio_surfaces-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8a5384a02652161d937710c883057c8c4c9c19aa2be24e89be28d9e89ecdcba9
MD5 ef3ec29e3d486f7252a5b55c4f61cf17
BLAKE2b-256 269f77fa4576ff316a6400810595d93cb0013b7e60b76176fbf2dccbd82cefa1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page