PHPackages                             schaefersoft/laravel-llms-txt - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. schaefersoft/laravel-llms-txt

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

schaefersoft/laravel-llms-txt
=============================

Automatically generate llms.txt and llms-full.txt for Laravel applications

1.2.0(1mo ago)22.6k↓10.7%MITPHPPHP ^8.2CI passing

Since Mar 26Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/schaefersoft/laravel-llms-txt)[ Packagist](https://packagist.org/packages/schaefersoft/laravel-llms-txt)[ Docs](https://github.com/schaefersoft/laravel-llms-txt)[ RSS](/packages/schaefersoft-laravel-llms-txt/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (6)Dependencies (28)Versions (13)Used By (0)

laravel-llms-txt
================

[](#laravel-llms-txt)

[![Latest Version on Packagist](https://camo.githubusercontent.com/78ae05e1dc37435230ca63a5f0fc9a4d663fcc7f8fd5f9be8a3ba85889936661/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7363686165666572736f66742f6c61726176656c2d6c6c6d732d7478742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/schaefersoft/laravel-llms-txt)[![Tests](https://camo.githubusercontent.com/fff321726f50fd49aa8a5ec845b079c789905611b956798e53cce04ff18186b1/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7363686165666572736f66742f6c61726176656c2d6c6c6d732d7478742f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/schaefersoft/laravel-llms-txt/actions/workflows/run-tests.yml)[![Total Downloads](https://camo.githubusercontent.com/f4012b5abf5c0dbd858e3d91856d27745a5029b42b80768616b052420d0292e9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7363686165666572736f66742f6c61726176656c2d6c6c6d732d7478742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/schaefersoft/laravel-llms-txt)

Automatically generate `llms.txt` and `llms-full.txt` files for your Laravel application — helping AI models understand your website, just like `sitemap.xml` helps search engines.

Built according to the [llmstxt.org](https://llmstxt.org/) specification.

**Requirements:** PHP 8.2+ and Laravel 10, 11, 12, or 13.

---

Table of Contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- [Quick Start](#quick-start)
- [Building Your Document](#building-your-document)
    - [Title and Description](#title-and-description)
    - [Sections and Entries](#sections-and-entries)
    - [Fluent Shorthand](#fluent-shorthand)
    - [Conditional Content](#conditional-content)
- [Configuration](#configuration)
- [Routes](#routes)
    - [Automatic Route Registration](#automatic-route-registration)
    - [Excluding Routes from Auto-Generation](#excluding-routes-from-auto-generation)
    - [Manual Route Registration](#manual-route-registration)
- [Localization](#localization)
    - [Translating Content](#translating-content)
    - [Locale-Prefixed Routes](#locale-prefixed-routes)
    - [Using mcamara/laravel-localization](#using-mcamaralaravel-localization)
- [Static File Generation](#static-file-generation)
    - [Artisan Command](#artisan-command)
    - [Programmatic Export](#programmatic-export)
- [llms-full.txt](#llms-fulltxt)
    - [Serving llms-full.txt Dynamically](#serving-llms-fulltxt-dynamically)
- [Caching](#caching)
- [Output Format](#output-format)
- [Testing](#testing)
- [License](#license)

---

Installation
------------

[](#installation)

```
composer require schaefersoft/laravel-llms-txt
```

Publish the configuration file:

```
php artisan vendor:publish --tag=llms-txt-config
```

That's it. The package is auto-discovered by Laravel, and `/llms.txt` is available immediately.

---

Quick Start
-----------

[](#quick-start)

The package works in two modes:

1. **Zero-config** — Without any setup, `/llms.txt` is automatically generated from all registered `GET` routes in your application. Internal routes (Telescope, Horizon, Debugbar) and routes with URI parameters are excluded. Additional routes can be excluded via the [`exclude_routes` config option](#excluding-routes-from-auto-generation).
2. **Custom definition** (recommended) — Register a configure callback to have full control over the output. It always takes precedence over auto-generation.

```
// app/Providers/AppServiceProvider.php

use SchaeferSoft\LaravelLlmsTxt\LlmsTxt;

public function boot(): void
{
    LlmsTxt::configure(fn ($llms) => $llms
        ->title('My App')
        ->description('A short description of what this site offers.')
        ->section('Services', fn ($s) => $s
            ->entry('Web Development', 'https://example.com/web', 'Laravel & Vue.js')
            ->entry('Hosting', 'https://example.com/hosting', 'Managed hosting')
        )
    );
}
```

This produces:

```
# My App

> A short description of what this site offers.

## Services
- [Web Development](https://example.com/web): Laravel & Vue.js
- [Hosting](https://example.com/hosting): Managed hosting
```

> **Tip:** For larger projects, consider a dedicated `LlmsTxtServiceProvider` to keep your `AppServiceProvider` clean.

---

Building Your Document
----------------------

[](#building-your-document)

### Title and Description

[](#title-and-description)

Every document starts with a title and an optional description:

```
LlmsTxt::make()
    ->title('My App')
    ->description('Short tagline for the site.');
```

Both methods accept a string or a `Closure` for lazy evaluation (useful for [localization](#localization)):

```
LlmsTxt::make()
    ->title(fn () => __('llms.title'))
    ->description(fn () => __('llms.description'));
```

### Sections and Entries

[](#sections-and-entries)

Sections group related entries under a heading. Entries are links with a title, URL, and optional description.

**Verbose style** — useful when you need to store references to entries:

```
use SchaeferSoft\LaravelLlmsTxt\Entry;
use SchaeferSoft\LaravelLlmsTxt\Section;

$section = Section::create('Services')
    ->addEntry(Entry::create('Web Development', 'https://example.com/web', 'Laravel & Vue.js'))
    ->addEntry(Entry::create('Hosting', 'https://example.com/hosting'));

LlmsTxt::make()
    ->title('My App')
    ->addSection($section);
```

### Fluent Shorthand

[](#fluent-shorthand)

For a more compact style, use `section()` and `entry()` directly on the builder:

```
LlmsTxt::make()
    ->title('My App')
    ->section('Services', fn ($s) => $s
        ->entry('Web Development', 'https://example.com/web', 'Laravel & Vue.js')
        ->entry('Hosting', 'https://example.com/hosting', 'Managed hosting')
    )
    ->section('References', fn ($s) => $s
        ->entry('Projects', 'https://example.com/references', 'All client projects')
    );
```

> `create()` and `make()` are identical — use whichever you prefer.

> **Note:** The `entry()` shorthand returns the `Section`, not the `Entry`. To call methods on the `Entry` itself (e.g. `description()`), use `Entry::create()` with `addEntry()` — or simply pass the description as the third argument to `entry()`.

### Model-Based Entries

[](#model-based-entries)

Use `entries()` on a section to map a collection of models (or any iterable) into entries. The callback receives each item and must return an `Entry` instance.

```
LlmsTxt::configure(fn ($llms) => $llms
    ->title('My App')
    ->section('Services', fn ($s) => $s
        ->entries(Service::published()->get(), fn ($service) => Entry::create(
            $service->name,
            route('services.show', $service),
            $service->tagline,
        ))
    )
);
```

You can combine `entry()` and `entries()` freely in the same section:

```
->section('Blog', fn ($s) => $s
    ->entry('All Posts', route('blog.index'))
    ->entries(Post::featured()->get(), fn ($post) => Entry::create(
        $post->title,
        route('blog.show', $post),
    ))
)
```

### Conditional Content

[](#conditional-content)

Both `LlmsTxt` and `Section` support a `when()` method that mirrors Laravel's own `when()`:

```
LlmsTxt::make()
    ->title('My App')
    ->section('Services', fn ($s) => $s
        ->entry('Web Development', 'https://example.com/web')
        ->when((bool) config('features.shop'), fn ($s) => $s
            ->entry('Shop', 'https://example.com/shop')
        )
    )
    ->when((bool) config('features.api'), fn ($llms) => $llms
        ->section('API', fn ($s) => $s
            ->entry('API Docs', 'https://example.com/api')
        )
    );
```

You can also pass a `Closure` as the condition for lazy evaluation:

```
->when(fn () => Feature::active('shop'), fn ($s) => $s
    ->entry('Shop', 'https://example.com/shop')
)
```

---

Configuration
-------------

[](#configuration)

After publishing, the config file is at `config/llms-txt.php`:

OptionDefaultDescription`route_enabled``true`Enable or disable the HTTP routes entirely.`llms_txt_route``'/llms.txt'`URL path for the standard file.`llms_full_txt_route``'/llms-full.txt'`URL path for the full file.`full_route_enabled``false`Serve `llms-full.txt` dynamically. Disabled by default — see [llms-full.txt](#llms-fulltxt).`register_routes``true`Auto-register routes. Set to `false` for [manual registration](#manual-route-registration).`cache_enabled``true`Cache rendered output.`cache_ttl``3600`Cache lifetime in seconds.`disk``null`Output location for static files. `null` writes directly into the `public/` folder; set a disk name to use a filesystem disk.`exclude_routes``[]`URI or route-name patterns (with `*` wildcards) to exclude from [auto-generation](#excluding-routes-from-auto-generation).`locales``[]`List of supported locales (e.g. `['en', 'de']`).`localize_routes``false`Register locale-prefixed routes like `/en/llms.txt`.---

Routes
------

[](#routes)

### Automatic Route Registration

[](#automatic-route-registration)

By default, the package registers one route:

RouteDescription`GET /llms.txt`Serves the standard `llms.txt` output.A second route, `GET /llms-full.txt`, is only registered when `full_route_enabled` is set to `true` — see [llms-full.txt](#llms-fulltxt) for why it is opt-in.

Routes are registered automatically when `register_routes` is `true` (the default).

### Excluding Routes from Auto-Generation

[](#excluding-routes-from-auto-generation)

In zero-config mode the document is built from all registered `GET` routes. Use `exclude_routes` to keep specific routes out of the output. Patterns are matched against both the route URI and the route name, and support the `*` wildcard:

```
// config/llms-txt.php
'exclude_routes' => [
    'admin/*',        // URI wildcard: excludes /admin and everything below
    'legal/imprint',  // exact URI
    'internal.*',     // route-name wildcard
],
```

### Manual Route Registration

[](#manual-route-registration)

To apply custom middleware or headers, disable automatic registration and call `LlmsTxt::routes()` yourself:

```
// config/llms-txt.php
'register_routes' => false,
```

```
// routes/web.php
use SchaeferSoft\LaravelLlmsTxt\LlmsTxt;

Route::middleware(['web', 'cache.headers:public;max_age=3600'])
    ->group(function () {
        LlmsTxt::routes();
    });
```

`LlmsTxt::routes()` is idempotent — it is safe to call more than once.

---

Localization
------------

[](#localization)

### Translating Content

[](#translating-content)

A single configure callback covers all locales. The package sets the application locale before invoking your callback, so `__()` and `route()` return the correct values automatically.

```
LlmsTxt::configure(fn ($llms) => $llms
    ->title(__('llms.title'))
    ->description(__('llms.description'))
    ->section(__('llms.sections.services'), fn ($s) => $s
        ->entry(
            __('llms.entries.web_dev'),
            route('services.web'),
            __('llms.entries.web_dev_desc'),
        )
    )
);
```

Create your language files as usual:

```
// lang/en/llms.php
return [
    'title'       => 'My App',
    'description' => 'Software agency',
    'sections'    => ['services' => 'Services'],
    'entries'     => [
        'web_dev'      => 'Web Development',
        'web_dev_desc' => 'Modern web applications with Laravel & Vue.js',
    ],
];
```

```
// lang/de/llms.php
return [
    'title'       => 'Meine App',
    'description' => 'Software-Agentur',
    'sections'    => ['services' => 'Leistungen'],
    'entries'     => [
        'web_dev'      => 'Webentwicklung',
        'web_dev_desc' => 'Moderne Webanwendungen mit Laravel & Vue.js',
    ],
];
```

### Locale-Prefixed Routes

[](#locale-prefixed-routes)

Enable locale-prefixed routes to serve translated versions at `/en/llms.txt`, `/de/llms.txt`, etc.:

```
// config/llms-txt.php
'locales'          => ['en', 'de'],
'localize_routes'  => true,
```

Unknown locale segments return a 404 response.

### Using mcamara/laravel-localization

[](#using-mcamaralaravel-localization)

If you use `mcamara/laravel-localization`, disable automatic registration and wrap the routes in a localized group:

```
// config/llms-txt.php
'register_routes' => false,
```

```
// routes/web.php
Route::group(
    ['prefix' => LaravelLocalization::setLocale(), 'middleware' => ['localize']],
    function () {
        LlmsTxt::routes();
    }
);
```

---

Static File Generation
----------------------

[](#static-file-generation)

### Artisan Command

[](#artisan-command)

Generate static files with the `llms:generate` command:

```
# Generate public/llms.txt
php artisan llms:generate

# Also generate public/llms-full.txt
php artisan llms:generate --full

# Generate for a specific locale (e.g. public/de/llms.txt)
php artisan llms:generate --locale=de

# Generate for all configured locales
php artisan llms:generate --all-locales

# Combine flags
php artisan llms:generate --all-locales --full
```

By default, files are written directly into your application's `public/` folder, so `public/llms.txt` is immediately served at `https://your-app.test/llms.txt`. To write to a filesystem disk instead (e.g. `s3`), set the `disk` config option.

### Programmatic Export

[](#programmatic-export)

You can also write files to disk from code:

```
// Write to the default location
LlmsTxt::make()->title('My App')->writeToDisk();

// Write to a custom path
LlmsTxt::make()->title('My App')->writeToDisk('custom/path/llms.txt');

// Write with a locale prefix (writes to de/llms.txt)
LlmsTxt::make()->title('My App')->locale('de')->writeToDisk();

// Write the full version
LlmsTxt::make()->title('My App')->writeFullToDisk();
```

---

llms-full.txt
-------------

[](#llms-fulltxt)

The full variant fetches the content of each entry URL and appends it below the entry. URLs that cannot be fetched are silently skipped.

```
// Render as a string
$content = LlmsTxt::make()
    ->title('My App')
    ->section('Docs', fn ($s) => $s
        ->entry('API', 'https://example.com/api')
    )
    ->renderFull();

// Write directly to disk
LlmsTxt::make()->title('My App')->writeFullToDisk();
```

### Serving llms-full.txt Dynamically

[](#serving-llms-fulltxt-dynamically)

The `/llms-full.txt` route is **disabled by default**: on a cache miss it performs an HTTP request to every entry URL — which is slow, usually calls back into your own application, and lets any visitor trigger outbound traffic.

The recommended approach is generating a static file instead:

```
php artisan llms:generate --full
```

If you understand the trade-offs and want the dynamic route anyway, enable it explicitly:

```
// config/llms-txt.php
'full_route_enabled' => true,
```

With `cache_enabled => true` (the default), the fetched content is cached for `cache_ttl` seconds, so the entry URLs are only fetched once per TTL.

---

Caching
-------

[](#caching)

When `cache_enabled` is `true` (the default), rendered output is cached for the duration specified by `cache_ttl`.

```
// Use the default cache key ('llms-txt')
$content = LlmsTxt::make()->title('My App')->getCached();

// Use a custom cache key
$content = LlmsTxt::make()->title('My App')->getCached('my-custom-key');

// Flush ALL package cache keys (base keys + locale variants used by the routes)
LlmsTxt::make()->flushCache();

// Flush a single custom key
LlmsTxt::make()->flushCache('my-custom-key');
```

You can also clear the cache from the command line:

```
php artisan llms:clear
```

> **Note:** `php artisan llms:generate` flushes the cache automatically after a successful run, so the dynamic routes immediately reflect the new content.

---

Output Format
-------------

[](#output-format)

### llms.txt

[](#llmstxt)

```
# Site Title

> Site description

## Section Name
- [Entry Title](https://example.com): Entry description
- [Another Entry](https://example.com/other)
```

### llms-full.txt

[](#llms-fulltxt-1)

Same structure as `llms.txt`, but with the fetched HTML/text content of each URL appended below its entry.

---

Testing
-------

[](#testing)

```
composer test
```

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance87

Actively maintained with recent releases

Popularity26

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 89.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~19 days

Total

6

Last Release

40d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/141330650?v=4)[SchäferSoft](/maintainers/schaefersoft)[@schaefersoft](https://github.com/schaefersoft)

---

Top Contributors

[![TheGodlyLuzer](https://avatars.githubusercontent.com/u/71211303?v=4)](https://github.com/TheGodlyLuzer "TheGodlyLuzer (42 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (5 commits)")

---

Tags

aiai-agentsai-crawlerslaravellaravel-packagellmsseolaravelaillmsllms.txtschaefersoft

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/schaefersoft-laravel-llms-txt/health.svg)

```
[![Health](https://phpackages.com/badges/schaefersoft-laravel-llms-txt/health.svg)](https://phpackages.com/packages/schaefersoft-laravel-llms-txt)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9922.4M146](/packages/roots-acorn)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

79227.1M211](/packages/laravel-mcp)[laravel/boost

Laravel Boost accelerates AI-assisted development by providing the essential context and structure that AI needs to generate high-quality, Laravel-specific code.

3.6k26.0M783](/packages/laravel-boost)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[laravel/ai

The official AI SDK for Laravel.

1.1k4.6M295](/packages/laravel-ai)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
