lintpage
~/llms-txt/wordpress
§ WordPress

llms.txt on WordPress

WordPress routes every unknown URL through index.php, which is why an uploaded llms.txt can return your 404 template with a 200 status. Three ways to serve it, and how to tell which one your host allows.

WordPress hands every request that is not an existing file to index.php. A real file at the web root wins; anything else needs a rewrite rule.

§ how to serve it

Serving /llms.txt from WordPress.

step 1

Upload a real file to the web root

The simplest approach and the one that survives plugin changes. Put llms.txt in the same directory as wp-config.php - usually public_html or www - over SFTP or your host's file manager. Apache and nginx both serve an existing file before WordPress is consulted, so no rewrite is involved.

bash
public_html/
  wp-admin/
  wp-content/
  wp-includes/
  index.php
  wp-config.php
  llms.txt        ←  here, beside wp-config.php
step 2

Or generate it from your content with a small snippet

If you want the file to track your published pages, register a rewrite rule and render it from a query var. This is the same mechanism WordPress uses for its own feeds. Add it to a site-specific plugin rather than functions.php so a theme update cannot remove it.

wp-content/plugins/acme-llms-txt/acme-llms-txt.php
<?php
/* Plugin Name: Acme llms.txt */

add_action('init', function () {
    add_rewrite_rule('^llms\.txt$', 'index.php?acme_llms_txt=1', 'top');
});

add_filter('query_vars', function ($vars) {
    $vars[] = 'acme_llms_txt';
    return $vars;
});

add_action('template_redirect', function () {
    if (!get_query_var('acme_llms_txt')) {
        return;
    }

    header('Content-Type: text/plain; charset=utf-8');

    echo "# " . get_bloginfo('name') . "\n\n";
    echo "> " . get_bloginfo('description') . "\n\n";
    echo "## Pages\n\n";

    foreach (get_pages() as $page) {
        printf("- [%s](%s)\n", $page->post_title, get_permalink($page));
    }

    exit; // Without this, WordPress carries on and appends your theme.
});
step 3

Flush rewrite rules once, then never again

A new rewrite rule does nothing until WordPress rebuilds its rules cache. Visit Settings → Permalinks and save - that is the flush. Do not call flush_rewrite_rules() on every init; it is an expensive write on every page load and a well-known way to slow a site down.

§ what goes wrong here

What WordPress gets wrong.

The failures below are specific to WordPress. A generic llms.txt guide will not mention any of them.

01

Your 404 page is being served with a 200 status

The WordPress-specific trap. If the file is not where the web server looks, the request reaches index.php, WordPress finds no matching post, and some themes and security plugins render the 404 template with a 200 status instead of a 404. A checker sees a 200 and a body, and reports a malformed llms.txt. Check the status code, not just that "something loads".

bash
curl -sI https://example.com/llms.txt | head -1
# HTTP/2 200  with an HTML body  →  WordPress answered, not your file
02

A caching plugin is serving a stale copy

WP Rocket, W3 Total Cache, LiteSpeed Cache and host-level page caches all cache by URL, including this one. After adding or editing the file, purge the cache - otherwise you spend an afternoon debugging a file that was correct twenty minutes ago.

03

The file is in wp-content/ instead of the web root

A common misread of upload instructions. wp-content/llms.txt is served at /wp-content/llms.txt, which is not where anything looks. The file must be at the root of the domain.

04

A multisite install resolves the root differently

On WordPress multisite, the physical web root belongs to the network, not to an individual site. A file dropped there appears on every site in the network at once, and a subsite cannot serve its own. Use the rewrite rule approach on multisite and switch on get_current_blog_id().

§ faq

Questions, answered.

Do I need a plugin to add llms.txt to WordPress?
No. Uploading a file to your web root - the directory containing wp-config.php - is enough, because the web server serves existing files before WordPress sees the request. A plugin is only worth it if you want the file generated from your published content, and even then a twenty-line site-specific plugin does the job.
Where exactly is the WordPress web root?
The directory holding wp-config.php, wp-admin, and wp-includes. On most shared hosts it is public_html or www; on a managed host it may be site/ or app/public. If you can see wp-config.php in a directory listing, you are in the right place. It is not wp-content.
Why does my WordPress llms.txt show my site's 404 page?
Because WordPress, not your web server, answered the request - meaning the file is not where the server looks for it. The confusing part is the status code: several themes and security plugins render the 404 template with a 200 status, so tools report a malformed llms.txt rather than a missing one. Confirm the file is in the web root and check the status code directly.
Will Yoast or Rank Math generate an llms.txt for me?
Some SEO plugins have started shipping llms.txt features, and what they generate varies from a genuine curated index to a reformatted sitemap. If you use one, check what it actually produced before trusting it - the file is public, and a list of every URL on your site is not an index.
§ the part that matters

An llms.txt will not fix a site AI cannot read.

Before writing an index for AI clients, check that they can fetch your pages at all. LintPage runs 60 checks against a URL in about 30 seconds - free, no signup.

run a full scan →