{"id":35759201,"url":"https://github.com/thegrowthproject/wp-llms-txt","last_synced_at":"2026-01-13T21:47:04.392Z","repository":{"id":331401046,"uuid":"1124888240","full_name":"thegrowthproject/wp-llms-txt","owner":"thegrowthproject","description":"WordPress plugin that generates llms.txt and llms-full.txt endpoints for AI/LLM consumption","archived":false,"fork":false,"pushed_at":"2026-01-07T00:38:05.000Z","size":365,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-07T17:44:09.607Z","etag":null,"topics":["ai","gutenberg","gutenberg-blocks","llm","llmstxt","markdown","wordpress","wordpress-plugin"],"latest_commit_sha":null,"homepage":"https://thegrowthproject.com/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thegrowthproject.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-29T19:43:09.000Z","updated_at":"2026-01-07T00:38:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/thegrowthproject/wp-llms-txt","commit_stats":null,"previous_names":["thegrowthproject/wp-llms-txt"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/thegrowthproject/wp-llms-txt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thegrowthproject%2Fwp-llms-txt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thegrowthproject%2Fwp-llms-txt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thegrowthproject%2Fwp-llms-txt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thegrowthproject%2Fwp-llms-txt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thegrowthproject","download_url":"https://codeload.github.com/thegrowthproject/wp-llms-txt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thegrowthproject%2Fwp-llms-txt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28401058,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","gutenberg","gutenberg-blocks","llm","llmstxt","markdown","wordpress","wordpress-plugin"],"created_at":"2026-01-06T22:30:14.862Z","updated_at":"2026-01-13T21:47:04.386Z","avatar_url":"https://github.com/thegrowthproject.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WP LLMs Plugin\n\n[![CI](https://github.com/thegrowthproject/wp-llms-txt/actions/workflows/lint.yml/badge.svg)](https://github.com/thegrowthproject/wp-llms-txt/actions/workflows/lint.yml)\n![WordPress 6.5+](https://img.shields.io/badge/WordPress-6.5%2B-blue?logo=wordpress)\n![PHP 8.2+](https://img.shields.io/badge/PHP-8.2%2B-purple?logo=php)\n[![License: GPL v2](https://img.shields.io/badge/License-GPL_v2-blue.svg)](https://www.gnu.org/licenses/gpl-2.0)\n\nA WordPress plugin that makes your site readable by AI systems.\n\nBuilt by [The Growth Project](https://thegrowthproject.com).\n\n## The Problem\n\nAI tools and LLMs struggle with WordPress content:\n\n- **Gutenberg blocks are messy** — Block comments, nested divs, inline styles. None of it helps an AI understand your content.\n- **No standard index** — AI crawlers don't know what pages matter or how your content is structured.\n- **HTML isn't ideal** — LLMs work better with clean markdown than raw HTML.\n\nThe [llmstxt.org](https://llmstxt.org/) standard solves this. It defines a `/llms.txt` endpoint that tells AI systems what content exists and how to access it.\n\n## The Solution\n\nThis plugin implements the llms.txt standard for WordPress:\n\n1. **`/llms.txt`** — An index of your site's pages and posts, with links to markdown versions\n2. **`/llms-full.txt`** — Your entire site content in a single markdown file\n3. **`.md` endpoints** — Every page and post available as clean markdown (e.g., `/about.md`)\n\nAI tools can now crawl your site efficiently. Your content is accessible in a format they understand.\n\n## Usage\n\n### Copy for LLM Button\n\nAdd a button that copies the current page content as markdown to the clipboard.\n\n1. Open the block editor for any page or post\n2. Click the **+** inserter and search for \"Copy for LLM\"\n3. Insert the block where you want the button to appear\n4. The button inherits your theme's button styles automatically\n\n\u003c!-- Screenshot: copy-button-inserter.png --\u003e\n*Block inserter showing \"Copy for LLM\" block*\n\nWhen clicked, the button:\n- Shows \"Copying...\" during fetch\n- Fetches content from the `.md` endpoint\n- Copies markdown to clipboard\n- Shows \"Copied!\" confirmation\n\n\u003c!-- Screenshot: copy-button-states.png --\u003e\n*Button states: default, copying, copied*\n\n### View as Markdown Button\n\nAdd a link that opens the markdown version of the current page.\n\n1. Open the block editor for any page or post\n2. Click the **+** inserter and search for \"View as Markdown\"\n3. Insert the block where you want the link to appear\n\nThe link automatically points to the current page's `.md` URL (e.g., `/about.md`).\n\n### LLM Buttons Pattern\n\nFor convenience, both buttons are available as a pattern:\n\n1. Click the **+** inserter\n2. Switch to the **Patterns** tab\n3. Search for \"LLM Buttons\"\n4. Insert the pattern to get both buttons in a row\n\n\u003c!-- Screenshot: llm-buttons-pattern.png --\u003e\n*LLM Buttons pattern with both buttons*\n\n### Blog Filters (Bonus Blocks)\n\nThis plugin includes three blocks for filtering blog archives. These demonstrate WordPress Interactivity API patterns with shared global state.\n\n#### Blog Category Filter\n\nDisplays category pills for filtering posts without page reload.\n\n```\n\u003c!-- wp:tgp/blog-category-filter /--\u003e\n```\n\n\u003c!-- Screenshot: blog-category-filter.png --\u003e\n*Category filter pills with active state*\n\n#### Blog Search\n\nSearch input that filters posts in real-time.\n\n```\n\u003c!-- wp:tgp/blog-search /--\u003e\n```\n\n#### Blog Filters (Container)\n\nOrchestrates the filter state and provides the post list. Wrap your query loop with this block.\n\n```\n\u003c!-- wp:tgp/blog-filters --\u003e\n    \u003c!-- wp:tgp/blog-category-filter /--\u003e\n    \u003c!-- wp:tgp/blog-search /--\u003e\n    \u003c!-- Your query loop here --\u003e\n\u003c!-- /wp:tgp/blog-filters --\u003e\n```\n\nThe three blocks share state via the WordPress Interactivity API. Changing a category or search term updates all blocks and filters the visible posts.\n\n\u003c!-- Screenshot: blog-filters-demo.gif --\u003e\n*Blog filters in action: category selection and search*\n\n## GEO: Generative Engine Optimization\n\nSEO optimizes for Google. GEO optimizes for AI.\n\nAI assistants like ChatGPT, Claude, and Perplexity are becoming primary research tools. When someone asks \"what's the best approach to systems integration?\", these tools pull from sources they can read and trust.\n\n**The shift is measurable:**\n- AI-referred traffic increased 527% in early 2025 (Ahrefs)\n- 60% of Google searches now end without a click — users get answers from AI summaries\n- ChatGPT and Perplexity are routing millions of queries daily\n\n**How this plugin helps with GEO:**\n\n| GEO Factor | How Plugin Addresses It |\n|------------|------------------------|\n| **Structured content** | Clean markdown with clear headings, not messy HTML |\n| **Machine-readable index** | `/llms.txt` tells AI what content exists |\n| **Frontmatter metadata** | YAML provides title, date, author, URL context |\n| **Single-file export** | `/llms-full.txt` for complete site ingestion |\n| **Standard compliance** | Follows llmstxt.org specification |\n\nIf your content isn't accessible to AI systems, you're invisible to a growing segment of search. This plugin fixes that.\n\n## Installation\n\n1. Upload the `tgp-llms-txt` folder to `/wp-content/plugins/`\n2. Activate the plugin in WordPress admin\n3. Visit `yoursite.com/llms.txt` to verify\n\nNo configuration needed. It works out of the box.\n\n## Endpoints\n\n| Endpoint | Content-Type | Description |\n|----------|--------------|-------------|\n| `/llms.txt` | `text/plain` | Index of all pages and posts with markdown links |\n| `/llms-full.txt` | `text/plain` | Complete site content concatenated |\n| `/page-slug.md` | `text/markdown` | Individual page as markdown with YAML frontmatter |\n| `/blog/post-slug.md` | `text/markdown` | Individual post as markdown with YAML frontmatter |\n\n## Development\n\nThis plugin is open source and demonstrates production engineering practices.\n\n### Documentation\n\n| Document | Description |\n|----------|-------------|\n| [CONTRIBUTING.md](CONTRIBUTING.md) | How to contribute, code style, PR process |\n| [docs/TESTING.md](docs/TESTING.md) | Testing guide: PHPUnit, Jest, Playwright |\n| [docs/BLOCK-DEVELOPMENT.md](docs/BLOCK-DEVELOPMENT.md) | Block development patterns and Interactivity API |\n| [docs/BUTTON-STYLING.md](docs/BUTTON-STYLING.md) | Block Supports API and theme integration |\n\n### Architecture Decisions\n\nSignificant technical decisions are documented as ADRs:\n\n| ADR | Decision |\n|-----|----------|\n| [001](docs/adr/001-interactivity-api-state-vs-context.md) | State vs Context in Interactivity API |\n| [002](docs/adr/002-skip-serialization-pattern.md) | Skip serialization for server-rendered blocks |\n| [003](docs/adr/003-shared-helper-classes.md) | Shared PHP helper classes for block rendering |\n\n### Testing\n\n```bash\n# Install dependencies\ncomposer install\nnpm install\n\n# Run tests\ncomposer test        # PHPUnit (PHP logic)\nnpm test             # Jest (JS stores)\nnpm run test:e2e     # Playwright (browser tests, requires Docker)\n\n# Linting\ncomposer lint        # PHPCS\n```\n\nTests run automatically on GitHub Actions for every push and pull request.\n\n### Local Development\n\nThe plugin uses `@wordpress/env` for local development:\n\n```bash\nnpm run wp-env start   # Start WordPress environment\nnpm run wp-env stop    # Stop environment\n```\n\n## Plugin Structure\n\n```\ntgp-llms-txt/\n├── tgp-llms-txt.php              # Main plugin file\n├── includes/\n│   ├── class-endpoint-handler.php     # Routes .md and llms.txt requests\n│   ├── class-llms-txt-generator.php   # Generates /llms.txt index\n│   ├── class-markdown-converter.php   # Gutenberg to markdown conversion\n│   ├── class-frontmatter.php          # YAML frontmatter generation\n│   ├── class-button-block-renderer.php    # Shared button rendering logic\n│   └── class-pill-block-renderer.php      # Shared pill/filter rendering\n├── blocks/\n│   ├── copy-button/              # \"Copy for LLM\" button\n│   │   ├── block.json\n│   │   ├── index.js              # Editor component\n│   │   ├── view.js               # Interactivity API store\n│   │   ├── render.php            # Server-side rendering\n│   │   └── style.css\n│   ├── view-button/              # \"View as Markdown\" link\n│   │   ├── block.json\n│   │   ├── index.js\n│   │   ├── render.php\n│   │   └── style.css\n│   ├── blog-filters/             # Filter state orchestrator\n│   │   ├── block.json\n│   │   ├── index.js\n│   │   ├── view.js               # Global filter state\n│   │   └── render.php\n│   ├── blog-category-filter/     # Category pills\n│   │   ├── block.json\n│   │   ├── index.js\n│   │   ├── view.js\n│   │   ├── render.php\n│   │   └── style.css\n│   └── blog-search/              # Search input\n│       ├── block.json\n│       ├── index.js\n│       ├── view.js\n│       ├── render.php\n│       └── style.css\n├── tests/\n│   ├── php/                      # PHPUnit tests\n│   ├── js/                       # Jest tests\n│   └── e2e/                      # Playwright tests\n└── docs/\n    ├── TESTING.md\n    ├── BLOCK-DEVELOPMENT.md\n    ├── BUTTON-STYLING.md\n    └── adr/                      # Architecture Decision Records\n```\n\n### Core Classes\n\n**`TGP_Endpoint_Handler`**\nIntercepts requests early in the WordPress lifecycle. Matches URL patterns (`*.md`, `llms.txt`) and routes them to the appropriate handler.\n\n**`TGP_LLMs_Txt_Generator`**\nBuilds the `/llms.txt` index file. Queries all published pages and posts, groups posts by category, and formats everything according to the llmstxt.org specification.\n\n**`TGP_Markdown_Converter`**\nConverts WordPress Gutenberg block content to clean markdown. Handles headings, paragraphs, lists, tables, blockquotes, and inline formatting.\n\n**`TGP_Frontmatter`**\nGenerates YAML frontmatter for individual `.md` endpoints. Includes title, URL, date, author, and excerpt metadata.\n\n**`TGP_Button_Block_Renderer`** / **`TGP_Pill_Block_Renderer`**\nShared helper classes for consistent block rendering. Extract Block Supports styles, build class names, generate inline styles.\n\n### Gutenberg Blocks\n\n| Block | Purpose | Interactivity |\n|-------|---------|---------------|\n| `tgp/copy-button` | Copy page as markdown | Local context |\n| `tgp/view-button` | Link to .md endpoint | None (static) |\n| `tgp/blog-filters` | Filter state container | Global state provider |\n| `tgp/blog-category-filter` | Category pill filters | Reads global state |\n| `tgp/blog-search` | Search input | Reads/writes global state |\n\n## How It Works\n\n1. User visits `/about.md`\n2. `TGP_Endpoint_Handler` intercepts the request at `init` (priority 0)\n3. It extracts the slug (`about`) and loads the corresponding page\n4. `TGP_Frontmatter` generates YAML metadata\n5. `TGP_Markdown_Converter` transforms Gutenberg HTML to markdown\n6. Response is served with `Content-Type: text/markdown`\n\nThe same flow applies to `/llms.txt`, except `TGP_LLMs_Txt_Generator` builds the full index instead of converting a single page.\n\n## Caching\n\nResponses include a `Cache-Control: public, max-age=3600` header (1 hour). For production sites with caching plugins, the `.md` and `.txt` endpoints will be cached like any other page.\n\n## Rate Limiting\n\nThe `/llms.txt` and `*.md` endpoints include rate limiting to prevent abuse:\n\n| Header | Description |\n|--------|-------------|\n| `X-RateLimit-Limit` | Maximum requests per window (default: 100) |\n| `X-RateLimit-Remaining` | Requests remaining in current window |\n| `X-RateLimit-Reset` | Unix timestamp when the window resets |\n\n**Default limits:**\n- 100 requests per minute per IP address\n- Returns `429 Too Many Requests` with `Retry-After` header when exceeded\n\n### Customizing the Rate Limit\n\nUse the `tgp_llms_txt_rate_limit` filter to adjust limits:\n\n```php\n// Increase limit for trusted IPs\nadd_filter( 'tgp_llms_txt_rate_limit', function( $limit, $ip ) {\n    $trusted_ips = [ '10.0.0.1', '192.168.1.100' ];\n    if ( in_array( $ip, $trusted_ips, true ) ) {\n        return 1000; // Higher limit for trusted sources\n    }\n    return $limit;\n}, 10, 2 );\n\n// Disable rate limiting entirely (not recommended)\nadd_filter( 'tgp_llms_txt_rate_limit', '__return_zero' );\n```\n\n## Requirements\n\n- WordPress 6.5+ (Interactivity API required)\n- PHP 8.2+\n\n## Built By\n\n[The Growth Project](https://thegrowthproject.com) — Technology delivery for founders and operators.\n\nWe build systems that work. AI implementation, DevOps, integration, platform builds.\n\n- [AI Implementation Services](https://thegrowthproject.com/services/ai-implementation/)\n- [All Services](https://thegrowthproject.com/services/)\n- [Get in Touch](https://thegrowthproject.com/contact/)\n\n## License\n\nGPL v2 or later\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthegrowthproject%2Fwp-llms-txt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthegrowthproject%2Fwp-llms-txt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthegrowthproject%2Fwp-llms-txt/lists"}