gatsby-plugin-ai-pages
v1.0.8
Published
Generates AI-readable .md pages and llms.txt for Gatsby + WordPress projects
Downloads
769
Maintainers
Readme
gatsby-plugin-ai-pages
Generates AI-readable .md pages and llms.txt for Gatsby + WordPress (headless CMS) projects.
Every WordPress post gets a clean Markdown version at /{lang}/{path}/{slug}.md. A combined site index is generated at /llms.txt. Files are written as raw static files — no HTML wrapper, no JavaScript bundle — so AI agents and LLM crawlers receive pure text instantly.
Install
npm install gatsby-plugin-ai-pagesRequirements
- Gatsby v4 or v5
gatsby-source-wordpressconfigured and connected to WordPress- WPGraphQL plugin active on your WordPress site
Usage
Single language
// gatsby-config.js
module.exports = {
siteMetadata: {
title: "My Site",
description: "My site description",
siteUrl: "https://your-site.com",
},
plugins: [
// ... your existing plugins
{
resolve: "gatsby-plugin-ai-pages",
options: {
postTypes: [
{ graphqlType: "allWpPost", urlPath: "blog", label: "Blog Posts" },
],
},
},
],
};Produces:
/blog/{slug}.md
/llms.txtMultiple post types
{
resolve: "gatsby-plugin-ai-pages",
options: {
postTypes: [
{ graphqlType: "allWpPost", urlPath: "blog", label: "Blog Posts" },
{ graphqlType: "allWpProject", urlPath: "projects", label: "Projects" },
{ graphqlType: "allWpCaseStudy", urlPath: "case-studies",label: "Case Studies" },
{ graphqlType: "allWpEvent", urlPath: "events", label: "Events" },
],
},
}Multilingual sites (WPML)
For path-based multilingual sites (/en/blog/slug, /ar/blog/slug), pass a langMapping object that maps WordPress locale IDs to URL prefixes. This matches how WPML exposes language per post via the locale.id field.
{
resolve: "gatsby-plugin-ai-pages",
options: {
langMapping: {
"en_US": "en",
"ar": "ar",
"zh_CN": "zh-hans",
"tr_TR": "tr",
},
postTypes: [
{ graphqlType: "allWpPost", urlPath: "blog", label: "Blog Posts" },
{ graphqlType: "allWpNews", urlPath: "news", label: "News" },
{ graphqlType: "allWpInsight", urlPath: "insights", label: "Insights" },
],
},
}Produces:
/en/blog/{slug}.md
/ar/blog/{slug}.md
/zh-hans/blog/{slug}.md
/llms.txt ← combined index, grouped by language and post typeThe plugin fetches all posts in a single GraphQL query per post type, reads locale.id from each post, and routes each post to the correct language folder automatically.
Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| postTypes | array | [{ graphqlType: "allWpPost", urlPath: "blog", label: "Blog Posts" }] | Post types to generate .md pages for |
| postTypes[].graphqlType | string | — | GraphQL query name for this post type, e.g. allWpProject |
| postTypes[].urlPath | string | — | URL prefix, e.g. projects → /projects/{slug}.md |
| postTypes[].label | string | urlPath | Section heading used in /llms.txt |
| langMapping | object | null | Maps WPML locale IDs to URL prefixes. Omit for single-language sites. |
| siteUrl | string | siteMetadata.siteUrl | Override the site URL used to build links in frontmatter. |
What gets generated
/{lang}/{path}/{slug}.md
---
title: "Your Post Title"
description: "Excerpt up to 200 characters"
date: "2024-06-01T10:00:00"
slug: "your-post-slug"
lang: "en"
url: "https://your-site.com/en/blog/your-post-slug"
canonical: "https://your-site.com/en/blog/your-post-slug"
image: "https://your-wp.com/wp-content/uploads/hero.jpg"
author: "Author Name"
categories: ["Tech"]
tags: ["gatsby", "wordpress"]
---
## Post heading
Full post body converted from WordPress HTML to clean Markdown.../llms.txt
# My Site
> My site description
# Language: EN
## Blog Posts
- [Post Title](https://your-site.com/en/blog/post-slug)
Short excerpt...
Markdown: https://your-site.com/en/blog/post-slug.md
# Language: AR
## Blog Posts
- [Post Title in Arabic](https://your-site.com/ar/blog/post-slug)
Short excerpt...
Markdown: https://your-site.com/ar/blog/post-slug.md
---
Generated: 2026-07-06Home page
The home page (WordPress slug home) is automatically written as index.md per language:
/en/index.md
/ar/index.md
/zh-hans/index.mdNo extra config needed — this happens automatically when allWpPage is included in postTypes.
AWS Amplify
customHttp.yml is not required. Amplify automatically serves .md and llms.txt files with the correct content type when they exist as raw static files in /public.
If you want to explicitly enforce Content-Type: text/markdown in the response headers (for strict AI agent compatibility), add customHttp.yml to your project root:
# customHttp.yml — optional
customHeaders:
- pattern: "*.md"
headers:
- key: Content-Type
value: "text/markdown; charset=utf-8"
- pattern: "/llms.txt"
headers:
- key: Content-Type
value: "text/plain; charset=utf-8"How it works
The plugin uses Gatsby's onPostBuild hook — after Gatsby finishes building all pages, it writes raw .md and llms.txt files directly to /public. Amplify deploys the entire /public folder to the CDN, so the files are served as plain static text with no HTML wrapper and no JavaScript.
gatsby build
→ Gatsby builds all pages into /public
→ onPostBuild runs
→ plugin writes /public/en/blog/slug.md (raw text)
→ plugin writes /public/llms.txt
→ Amplify deploys /public to CDN
→ AI agents fetch /en/blog/slug.md → instant plain text responseFinding GraphQL type names
Custom post types in WordPress must be registered with WPGraphQL (show_in_graphql: true). The Gatsby GraphQL type name follows the pattern all + Wp + PascalCase post type name.
To find the exact name for your project, run this in GraphiQL (http://localhost:8000/___graphql):
{
__schema {
queryType {
fields {
name
}
}
}
}Look for fields starting with allWp.
| WordPress post type | GraphQL type name |
|---|---|
| Posts (default) | allWpPost |
| Custom: news | allWpNews |
| Custom: case_study | allWpCaseStudy |
| Custom: our_people | allWpOurpeople |
Testing locally
gatsby build && gatsby servecurl http://localhost:9001/en/blog/your-post-slug.md
curl http://localhost:9001/llms.txtLicense
MIT
