llms.txt для Laravel

Каталог public/ в Laravel является корневым веб-каталогом и не требует настройки. Для динамической генерации добавьте маршрут в routes/web.php или отдельный контроллер с фасадом Cache от Laravel.

Последнее обновление:

Вариант 1: статический файл в public/

Laravel public/ каталог — это корень документов, который отдаёт nginx или Apache. Любой помещённый туда файл доступен по соответствующему URL-пути без настройки маршрутизации. Это самый простой подход, не требующий изменений кода.

public/llms.txt, directory structure
# Laravel static file approach
#
# Laravel's public/ directory is the web root (served by nginx/Apache).
# Drop your file here and it is immediately available at /llms.txt.
#
# Project structure:
# your-laravel-app/
# ├── public/
# │   ├── index.php
# │   └── llms.txt   ← add this
# ├── routes/
# └── app/
#
# No code change needed. Works on Forge, Vapor, Heroku, and bare VPS.

Этот подход работает со всеми вариантами развёртывания Laravel: Laravel Forge, Laravel Vapor, Heroku, Railway, а также обычные VPS-серверы. Веб-сервер (nginx/Apache) предоставляет файл напрямую, не задействуя PHP, что также быстрее.

Вариант 2: маршрут в routes/web.php

Если вы хотите генерировать контент программно или управлять им из кода, а не из файла, добавьте именованный маршрут в routes/web.php:

routes/web.php
<?php
// routes/web.php, serve llms.txt via a named route

use Illuminate\Support\Facades\Route;

Route::get('/llms.txt', function () {
    $content = <<<'LLMS'
# Your Site

> One-sentence description of what your site or product does.

## Documentation

- [Getting Started](https://yoursite.com/docs/start): Install and configure in minutes.
- [API Reference](https://yoursite.com/docs/api): Full endpoint catalog with examples.

## Product

- [Overview](https://yoursite.com/product): Core features and capabilities.
- [Pricing](https://yoursite.com/pricing): Plans and billing details.

## Optional

- [Changelog](https://yoursite.com/changelog): Release history.
LLMS;

    return response($content, 200)
        ->header('Content-Type', 'text/plain; charset=utf-8')
        ->header('Cache-Control', 'public, max-age=3600, stale-while-revalidate=86400');
})->name('llms-txt');

Используйте синтаксис heredoc в PHP (<<<'LLMS') для записи содержимого непосредственно без забот об экранировании. Маркер heredoc в одинарных кавычках означает отсутствие интерполяции переменных: содержимое обрабатывается как литеральная строка.

Вариант 3: контроллер с кэшированием

Для контента, который динамически создаётся из базы данных, например для публикации страниц документации, используйте отдельный вызываемый контроллер с Cache::remember() чтобы избежать запроса к базе данных при каждом обращении:

app/Http/Controllers/LlmsTxtController.php
<?php
// app/Http/Controllers/LlmsTxtController.php

namespace App\Http\Controllers;

use Illuminate\Http\Response;
use Illuminate\Support\Facades\Cache;

class LlmsTxtController extends Controller
{
    public function __invoke(): Response
    {
        // Cache for 1 hour, regenerates automatically when expired
        $content = Cache::remember('llms_txt', 3600, function () {
            return $this->buildContent();
        });

        return response($content, 200)
            ->header('Content-Type', 'text/plain; charset=utf-8')
            ->header('Cache-Control', 'public, max-age=3600, stale-while-revalidate=86400');
    }

    private function buildContent(): string
    {
        // You can query your database here:
        // $docs = \App\Models\Doc::published()->get();
        // $links = $docs->map(fn($d) => "- [{$d->title}](https://yoursite.com/docs/{$d->slug}): {$d->summary}")->join("\n");

        return <<<'LLMS'
# Your Site

> One-sentence description of your product.

## Documentation

- [Getting Started](https://yoursite.com/docs/start): Install and configure in minutes.
- [API Reference](https://yoursite.com/docs/api): Full endpoint catalog with examples.

## Optional

- [Changelog](https://yoursite.com/changelog): Release history.
LLMS;
    }
}
routes/web.php, controller registration
<?php
// routes/web.php, register the controller route

use App\Http\Controllers\LlmsTxtController;
use Illuminate\Support\Facades\Route;

Route::get('/llms.txt', LlmsTxtController::class)->name('llms-txt');

Cache::remember() хранит результат в настроенном драйвере кэша (Redis, Memcached, базе данных или файле). Кэш автоматически обновляется через 3600 секунд. Чтобы немедленно удалить его после обновления контента, вызовите Cache::forget('llms_txt') в observer вашей модели или после хука развёртывания.

Макрос ответа для повторного использования

Если вы отдаёте несколько текстовых файлов или хотите единообразный шаблон для своего приложения, зарегистрируйте plaintext() макроса ответа в AppServiceProvider:

app/Providers/AppServiceProvider.php
<?php
// app/Providers/AppServiceProvider.php, response macro for reusability

namespace App\Providers;

use Illuminate\Support\Facades\Response;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Register a plaintext() macro for serving text/plain responses
        Response::macro('plaintext', function (string $content, int $maxAge = 3600) {
            return Response::make($content, 200, [
                'Content-Type'  => 'text/plain; charset=utf-8',
                'Cache-Control' => "public, max-age={$maxAge}, stale-while-revalidate=86400",
            ]);
        });
    }
}

// Usage in a route or controller:
// return response()->plaintext($content);

После этого макрос доступен в любой части приложения через response()->plaintext($content), сохраняя Content-Type и Cache-Control заголовки согласованными.

Проверить

После развёртывания убедитесь, что файл обслуживается корректно:

Verification
curl -I https://yoursite.com/llms.txt
# Expected:
# HTTP/2 200
# content-type: text/plain; charset=utf-8
# cache-control: public, max-age=3600

curl https://yoursite.com/llms.txt | head -5
# Should print: # Your Site

Затем вставьте URL в Валидатор llms.txt для проверки полного соответствия спецификации .

Контрольный список перед выпуском

  • Файл отдан по адресу /llms.txt с помощью 200 OK.
  • Content-Type: text/plain; charset=utf-8 установлен.
  • Cache-Control заголовок присутствует.
  • Ответ представляет собой обычный текст: без HTML и без вывода Blade.
  • Ровно один заголовок H1 в начале.
  • Сводка в blockquote сразу после H1.
  • Все URL абсолютны (https://).
  • Аутентификационное промежуточное ПО не применяется к /llms.txt маршрута.
  • Валидатор не возвращает ошибок: llmtxt.info/validator/

Связанные руководства

Источники