Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Seo Files Laravel Package

asignua/filament-seo-files

A Filament plugin for managing SEO-related files such as robots.txt and sitemap.xml directly from your admin panel, making it easy to edit and maintain essential site configuration without touching the filesystem.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by registering the plugin in the Filament panel that should expose the SEO files UI, then define the sources that feed sitemap.xml, llms.txt, and llms-full.txt. The first practical use case is a public site with a handful of Eloquent models: add a ModelSource for pages/posts, run php artisan seo-files:sitemap and php artisan seo-files:llms manually, inspect the generated files, then schedule the commands nightly.

After installing or upgrading, run:

php artisan filament:assets

This is required after v1.0.2 because the plugin stylesheet now uses scoped fi-seo-files-* classes and is only linked on the plugin’s own pages. Skipping this step can leave stale generic utility classes that override the panel theme.

Where to look first:

  • The package config for source registration and output paths.
  • The Filament “SEO files” page for generation, preview, search, and status.
  • seo-files:sitemap and seo-files:llms for scheduler integration.
  • ModelSource for the common Eloquent-backed source pattern.

A good first source is a published Page model with a translatable title and a description field. Once that works, add more sources and restrict locales with ->locales([...]) where needed.

Implementation Patterns

Register sources centrally, usually in a service provider or the package config, and keep them deterministic. ModelSource is the default path for Eloquent models: it can read a translatable title for the file’s language, decode HTML entities in descriptions, apply length limits, and avoid scanning locales it does not serve when restricted with ->locales().

Use the panel buttons for ad hoc generation and the Artisan commands for scheduled runs. Both paths share the same safety model: generation runs outside the admin context, with no Filament panel, tenant, or logged-in user. The scheduler already behaved this way; v1.0.2 makes the panel “Generate” buttons and llms editor match it. Design source queries for a public context. If a global scope depends on auth()->user() or a tenant, it will not see the admin who clicked the button, and it should not leak tenant-specific rows into a global sitemap.xml or llms-full.txt.

For multilingual sites, rely on app()->getLocale() inside source closures. The llms files are built in the language of the file, and ModelSource uses the translatable title for that language. Use ->locales() to limit both output and database scanning. BCP 47 locales such as es-419 and zh-Hant-TW are supported in v1.0.2.

Schedule the commands like any other nightly job:

$schedule->command('seo-files:sitemap')->daily();
$schedule->command('seo-files:llms')->daily();

Both commands take a non-blocking cache lock. If a panel click and the nightly run collide, one run is refused with a non-zero exit code. The panel reports that as a failure, so treat command failures as real operational signals rather than ignoring them.

For tenant-aware applications, do not expect the package to generate tenant-scoped files from the admin panel context. The global files are intentionally built without a tenant. If you need per-tenant outputs, generate them in separate processes or custom jobs where you explicitly establish the tenant context, rather than relying on the panel’s current tenant.

In tests and Octane, the source registry is reset when the service provider registers. A host test suite that boots a fresh application per test will not accumulate duplicate sources, and Octane’s cloned per-request applications keep the sources registered at boot. If you register sources dynamically at runtime, verify that behavior against your boot lifecycle.

Gotchas and Tips

Always run php artisan filament:assets after upgrading. The v1.0.2 stylesheet fix is not just cosmetic: generic utilities like .flex, .text-sm, and .text-gray-400 previously beat the panel theme’s responsive and dark: variants. The plugin now scopes its classes and loads the stylesheet only on its own pages.

Generation is deliberately context-free. No Filament panel, tenant, or authenticated user is available while the public files are built, and Filament::auth() is covered by the same guard swap. If your source closures call auth()->user(), Filament::auth(), or a tenant helper, expect null or empty results. This is the intended fix for tenant scopes and user-dependent global scopes leaking into public files.

The cache lock is non-blocking. A refused run exits with an error; the panel shows it as a failure, and it does the same for any non-zero exit code. Check scheduler logs if nightly files stop updating, and avoid manually clearing the lock unless you are sure no generation is running.

For llms output, keep descriptions as plain text or let ModelSource decode entities and no-break spaces before the length limit is applied. Do not double-encode. A non-string title no longer throws, but translatable titles should still be strings for predictable output.

Use ->locales() on ModelSource when a model only has content for some languages. It skips table scans for unsupported languages, which matters on large tables.

The “SEO files” page shows generation time in the app timezone as of v1.0.2. If timestamps look wrong, check config('app.timezone') before assuming the package is at fault.

The “Sitemap URLs” search is case-insensitive on MySQL/MariaDB in v1.0.2. On other databases, verify search behavior if your workflow depends on it.

If you extend the package with custom sources, register them through the same source registry and keep them free of request-specific state. The registry reset on provider registration is there to prevent duplicate sources in test suites and long-running workers; it also means sources registered at boot are the ones Octane expects.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource