@obaronai/astro-ai-readiness
v0.0.6
Published
AI Readiness toolkit for Astro — six JSON-LD components + dist/llms.txt, dist/agents.md, dist/.well-known/mcp.json. dist/llms-full.txt and dist/robots.txt on the roadmap.
Downloads
699
Maintainers
Readme
@obaronai/astro-ai-readiness
AI Readiness toolkit for Astro — six JSON-LD helper components plus
dist/llms.txt,dist/agents.md, anddist/.well-known/mcp.jsontoday;llms-full.txtandrobots.txton the v0.1 roadmap.
Status: v0.0.6 — sixth slice shipped. Component sub-line complete (6 of 6); three of five file outputs live. Multi-output orchestration on the astro:build:done hook is established — subsequent file-output slices wire in without hook changes.
What ships in v0.0.6
Six JSON-LD components (component sub-line complete):
<OrganizationSchema />— Organization block. Config-driven; place in yourBaseLayoutso it ships site-wide and the#organization@idreference resolves on every page.<WebSiteSchema />— WebSite block. Config-driven; alongside<OrganizationSchema />inBaseLayout.<CollectionSchema name url description? />— CollectionPage block. Props-driven; place on collection-index pages (/articles/,/tags/[tag]/, etc.).<BreadcrumbSchema items={[{ name, url }, ...]} />— BreadcrumbList. Items-array prop; place on multi-level pages where the navigation hierarchy isn't already declared inline. Emptyitemsskips emission.<FAQPageSchema items={[{ question, answer }, ...]} />— FAQPage. Items-array prop; place on pages with FAQ data. Long-form answers escape</script>and U+2028 / U+2029 automatically. Emptyitemsskips emission.<TechArticleSchema headline description datePublished {...optional} />— TechArticle block. Heavy-props; place on article-detail pages.authordefaults to a Person synthesized fromconfig.organization.founder; pass an explicitauthorprop to override.
Three file outputs (three of five file-output sub-line entries live):
dist/llms.txt— llmstxt.org format from thellmsTxtconfig block. H1 / blockquote summary / optional body / H2 sections with bulleted links / optional canonical-reference footer. Opt-in.dist/agents.md— Markdown discovery file for AI-agent crawlers from theagentsMdconfig block. H1 / blockquote description / optional## Audience,## Contact,## Linkssections. Opt-in.dist/.well-known/mcp.json— Model Context Protocol discovery file from themcpconfig block. Pretty-printed JSON with$schemareference to the toolkit-published v1 shape (per D-22). Supportsstatus: 'active'(requiresurl+tools[]) andstatus: 'planned'(requiresplanned_tools[];urlforbidden by schema). Opt-in.
@astrojs/sitemap detection per D-8. When you call aiReadiness({...}) and @astrojs/sitemap isn't in your integrations list, the toolkit logs a build-time warning. Sitemap is an AI-Readiness baseline; the sitemap reference itself ships in robots.txt (v0.0.8).
All six components emit canonical Schema.org JSON-LD with cross-component @id references (#organization, #website) so search and AI consumers can resolve the entity graph without redeclaring shared fields.
URL config fields (site, organization.url, organization.logo, founder.sameAs, llmsTxt.*.url) require https:// (or http://localhost for dev).
Config validation errors are formatted with one issue per line — path: message per Zod issue — instead of the default ZodError JSON blob.
On the roadmap (toward v0.1.0)
- v0.0.7 —
dist/llms-full.txt(content-collection introspection — first time the toolkit reads consumer content) - v0.0.8 —
dist/robots.txtcomposition (compose-with-existing pattern; sitemap reference lands here) - v0.1.0 — polish, tests, docs; FF-3.7 full install (obaron.ai)
Track progress: https://github.com/obaronai/astro-ai-readiness/milestones
Install
npm install @obaronai/astro-ai-readinessQuick start
Configure (v0.0.6 accepts site, organization, optional webSite, optional llmsTxt, optional agentsMd, and optional mcp blocks — the Zod schema rejects unknown keys, and URL fields must use https:// or http://localhost):
// astro.config.mjs
import { defineConfig } from 'astro/config'
import sitemap from '@astrojs/sitemap'
import aiReadiness from '@obaronai/astro-ai-readiness'
export default defineConfig({
site: 'https://your-site.com',
integrations: [
sitemap(), // recommended — AI Readiness baseline (D-8)
aiReadiness({
site: 'https://your-site.com',
organization: {
name: 'Your Brand',
url: 'https://your-site.com',
logo: 'https://your-site.com/logo.png',
founder: {
name: 'Your Name',
jobTitle: 'Founder',
sameAs: ['https://your-site.com', 'https://x.com/handle'],
},
},
webSite: {
// Optional. `name` defaults to organization.name when absent.
description: 'What your site does, in one sentence.',
},
llmsTxt: {
// Optional. When set, the toolkit ships dist/llms.txt at build time.
// Note: `summary` must be single-line — multi-paragraph summaries break
// the llms.txt blockquote shape. Use `body` (free-form markdown) for
// additional prose. Multi-line summary throws at config-validation time.
summary: 'What your site does, in one sentence — for AI agents discovering your content.',
body: 'A free-form markdown paragraph or two between summary and sections. Plain prose; no top-level H2 here (those are reserved for link sections below).',
sections: [
{
title: 'Articles',
links: [
{ title: 'All Articles', url: 'https://your-site.com/articles/' },
{ title: 'RSS Feed', url: 'https://your-site.com/rss.xml' },
],
},
],
deferTo: {
// Single canonical-reference link, rendered as a footer.
title: 'Articles Index',
url: 'https://your-site.com/articles/',
},
},
agentsMd: {
// Optional. When set, the toolkit ships dist/agents.md at build time.
description: 'What your site does and who it serves — for AI-agent crawlers.',
audience: 'Developers and AI agents acting on their behalf.',
contact: '[email protected]',
links: [
{ title: 'Articles', url: 'https://your-site.com/articles/', description: 'All articles' },
{ title: 'RSS Feed', url: 'https://your-site.com/rss.xml', description: 'Machine-readable article stream' },
],
},
mcp: {
// Optional. When set, the toolkit ships dist/.well-known/mcp.json at build time.
// Each server must have status: 'active' or status: 'planned'.
// Active: requires url + tools[]. Planned: requires planned_tools[]; url is forbidden.
servers: [
{
// A live MCP server — must have url + tools.
status: 'active',
name: 'your-knowledge',
url: 'https://mcp.your-site.com',
description: 'MCP server exposing your site knowledge for AI agents.',
tools: [
{ name: 'search_articles', description: 'Search articles by keyword or tag.' },
{ name: 'fetch_article', description: 'Fetch a specific article by slug.' },
],
},
{
// A planned server — declares intent without a live URL.
status: 'planned',
name: 'your-future-server',
description: 'Planned MCP server for future capability.',
planned_tools: [
{ name: 'lookup', description: 'Lookup by ID once the server ships.' },
],
},
],
},
}),
],
})Note on raw markdown.
llmsTxt.*andagentsMd.*string fields are emitted as raw markdown. If you're templating user-generated content intollmsTxt.summary,llmsTxt.body,llmsTxt.sections[].*.title,agentsMd.description,agentsMd.audience,agentsMd.contact, oragentsMd.links[].*.title/agentsMd.links[].*.description, escape],), and leading>to avoid breaking the rendered Markdown shape. Author-controlled strings (typical case) need no escaping.mcp.jsonis JSON-serialized and has no markdown-injection surface.
Use the components:
---
// src/layouts/BaseLayout.astro — site-wide
import { OrganizationSchema, WebSiteSchema } from '@obaronai/astro-ai-readiness/components'
---
<head>
<OrganizationSchema />
<WebSiteSchema />
</head><OrganizationSchema /> declares @id: '<site>#organization'; <WebSiteSchema /> references it. Order matters in the head — Organization first.
---
// src/pages/articles/index.astro — collection index pages
import { CollectionSchema } from '@obaronai/astro-ai-readiness/components'
---
<CollectionSchema
name="All Articles"
url={new URL('articles/', Astro.site).toString()}
description="Production-tested articles, version-pinned environments."
/>---
// any multi-level page — site-context navigation
import { BreadcrumbSchema } from '@obaronai/astro-ai-readiness/components'
import type { BreadcrumbItem } from '@obaronai/astro-ai-readiness/components'
const crumbs: BreadcrumbItem[] = [
{ name: 'Home', url: new URL('/', Astro.site).toString() },
{ name: 'Articles', url: new URL('/articles/', Astro.site).toString() },
{ name: 'How agents handle errors', url: Astro.url.toString() },
]
---
<BreadcrumbSchema items={crumbs} />---
// pages with FAQ data — items-array of question/answer pairs
import { FAQPageSchema } from '@obaronai/astro-ai-readiness/components'
import type { FAQItem } from '@obaronai/astro-ai-readiness/components'
const faqs: FAQItem[] = [
{ question: 'What is X?', answer: 'X is...' },
{ question: 'Why does Y matter?', answer: 'Because...' },
]
---
<FAQPageSchema items={faqs} />---
// article-detail pages — required props only
import { TechArticleSchema } from '@obaronai/astro-ai-readiness/components'
---
<TechArticleSchema
headline="How agents handle errors"
description="A pattern for agent error handling that doesn't lose context."
datePublished="2026-04-01T12:00:00Z"
/><TechArticleSchema> defaults author to a Person synthesized from config.organization.founder (name from founder.name, url from founder.sameAs[0]). Pass an explicit author={{ name, url? }} to override on multi-author sites. The component throws at build time if author is omitted and founder is unset — actionable error pointing at the aiReadiness({...}) config.
Advanced — full prop surface:
<TechArticleSchema
headline={article.title}
description={article.description}
datePublished={article.pubDate.toISOString()}
dateModified={(article.updatedDate ?? article.pubDate).toISOString()}
author={{ name: 'Guest Author', url: 'https://example.com' }}
image={{ url: 'https://your-site.com/og.png', width: 1200, height: 630 }}
articleSection="Tutorials"
keywords={['ai', 'agents', 'error-handling']}
proficiencyLevel="intermediate"
dependencies={['Node 22', 'Astro 5.5']}
/>Build your site (npm run build); inspect any dist/*.html — you'll see inline <script type="application/ld+json"> blocks with cross-referenced @ids tying the entity graph together.
Design principles
- Zero client JS. Every component emits inline
<script type="application/ld+json">at build time. Hydrating JSON-LD would erode the very Schema.org category it's meant to lift. - Compose, don't clobber. Future file outputs (
robots.txtetc.) will merge with existing user files rather than overwrite. User intent wins. - Composes with
@astrojs/sitemap. Doesn't replace it. Will warn when needed once sitemap-touching outputs land.
What's beyond v0.1
The v0.1 line is content → artifacts: components and files. Build-time AI-readiness self-scoring (against Obaron's published rubric), spec validation against llmstxt.org, and content lints are on the v0.2 horizon — but not committed scope yet. v0.1 ships first.
Shipped on
- aiallthethings.com — AATT, the toolkit's first reference implementation. Runs all six components on production plus three toolkit-emitted files:
dist/llms.txtat https://aiallthethings.com/llms.txt,dist/agents.mdat https://aiallthethings.com/agents.md, anddist/.well-known/mcp.jsonat https://aiallthethings.com/.well-known/mcp.json. Components: Organization + WebSite (site-wide via BaseLayout), CollectionPage (articles + framework + tag indexes), BreadcrumbList (/about), FAQPage (articles with FAQ frontmatter), TechArticle (every article-detail page). - obaron.ai — Obaron's main site. Will install in FF-3.7 once v0.1.0 publishes.
Contributing
PRs welcome. See CONTRIBUTING.md and our Code of Conduct.
License
MIT — Copyright (c) 2026 Adam Kinney, LLC (DBA Obaron).
