jgniecki/sitemap-bundle
jgniecki/sitemap-bundle is a Symfony bundle for generating XML sitemaps from your application's routes and content. Configure sitemap definitions, collect URLs automatically, and output search-engine-friendly XML to simplify SEO setup.
First, verify what you actually have. jgniecki/sitemap-bundle is a Symfony bundle, not a Laravel package. Check composer.json in the repo: you will almost certainly see "type": "symfony-bundle" and symfony/framework-bundle in require. That has three consequences a Laravel developer must internalise before spending any time on it:
ServiceProvider, no Facade, no config/sitemap.php to publish, and no php artisan vendor:publish.config/bundles.php in a Symfony kernel, not through Laravel's package discovery.vendor/, but nothing in a Laravel app will ever boot it.Where to look first (in this order):
composer.json — PHP constraint, Symfony version constraint, and whether type is really symfony-bundle. This single file tells you whether it can run in the Symfony 7.x / PHP 8.3 project you or a teammate maintains.README.md — look for the phrase "register the bundle" and for any console command name (bin/console ...:sitemap:...). If the README only shows YAML config and no Laravel-style setup, your decision is made.src/ — look for a *Bundle.php class, Command/, Controller/, and Resources/config/services.yaml. Those four locations define the entire surface area of a bundle this size.The shape of the package has changed in v1.1.0. It is no longer purely "one sitemap from your routes." It now models sitemap groups scoped to hosts, with per-host output paths and host-aware route filtering. If you are single-domain, none of this affects you and the old mental model holds. If you are multi-domain or multi-locale-per-host, this is the first release where the bundle is a plausible fit at all — read the host/group config keys before anything else.
First use case (if you are in a Symfony app): register the bundle in config/bundles.php, define one host group in config/packages/<vendor>_sitemap.yaml, run the generation command, and dump the output to public/sitemap.xml. Explicitly configure a host even if you only have one — v1.1.0 emits warnings about the default group, and you do not want production deploys printing deprecation-style noise because you took the zero-config path. Treat that as a spike, not an install.
If you are writing Laravel code: do not adopt this. Use spatie/laravel-sitemap, which is the idiomatic solution and is designed for Route:: / Eloquent model crawling out of the box. The v1.1.0 host-group feature does not change this — multi-domain sitemaps in Laravel are still better solved natively. The only defensible reason to touch this package from Laravel is if you are bridging to an existing Symfony service, and even then the bridge (below) is the interesting part, not the bundle.
Symfony-side integration (the only native path).
config/bundles.php, then create config/packages/<vendor>_sitemap.yaml. Because this package almost certainly has no Symfony Flex recipe (0 dependents ⇒ no recipe submission), expect to write this config by hand and to read services.yaml in the bundle to discover the real config keys rather than trusting docs that may lag the code.public/, and never generate on the request path — sitemap generation is a batch concern and will blow up your p95 if you put it in a controller.UrlProviderInterface or similar) or an event listener. Implementing your own provider with repository queries is where the real logic lives; keep it out of the bundle's classes so you can swap the bundle later.www.example.com, shop.example.com, example.fr). Do not try to cram multiple hosts into one group — the bundle filters routes by host per group, and mixing them produces sitemaps containing URLs for domains the file is not served from, which is a validation error at best and a Search Console penalty at worst.public/, invalidate the CDN, then ping search engines. Multi-host means N files and N CDN invalidations — script the loop, don't do it by hand. Do not commit generated files to git.Cross-framework bridge (if you genuinely must serve Symfony-generated XML from Laravel).
public/. Laravel then just serves static files. This is boring, robust, and avoids loading Symfony's kernel inside a Laravel request lifecycle — which is where mixed-framework projects go to die.spatie/laravel-sitemap with a custom URL set fed by the same query, one sitemap per domain. For most teams this is strictly better than bridging, because the sitemap logic and the content both live in one codebase.If you are evaluating rather than adopting, write a 30-minute spike: fresh Symfony app, composer require, register, configure two host groups with distinct paths, generate, view source, and confirm each file contains only its own host's URLs. Validate against xmllint --noout. If that path isn't clean, the package is not ready for production regardless of star count — and v1.1.0's whole value proposition is that path.
spatie/laravel-sitemap plus the composer.json type field as evidence. v1.1.0's new features do not move this needle.example.com vs www.example.com), vanish from the output with no error. Diff your route list against the generated XML on the first run and again after every deploy that touches routing.find public -name 'sitemap*.xml' | wc -l equals group count).vendor/. Budget accordingly, and pin to an exact version ("1.1.0", not ^1.1) — a minor-version feature drop this large is exactly where you don't want unvetted drift on deploy.Resources/config/services.yaml, the *Bundle.php class, and the config tree class (look for Configuration.php / TreeBuilder) are the ground truth for host/group keys and whether the "default group" warning is a deprecation or a validation error.bin/console debug:container --tag=<tag> to find registered providers, bin/console debug:router to confirm any XML endpoint and to inspect the host column of your routes, bin/console list to find the generation command. debug:router is now doubly useful — it's the fastest way to explain a missing URL.http:// and internal hostnames. Configure trusted_proxies / framework.trusted_hosts and verify the XML by eye. v1.1.0 makes this more dangerous, not less: host group membership may now be decided from the same context, so a misconfigured proxy can route URLs into the wrong group's file.xmllint --noout in CI — loop over every host group's output. A malformed sitemap fails silently in Search Console and you may not notice for weeks.application/xml (or application/xml; charset=UTF-8), and if you gzip, name the file sitemap.xml.gz and reference it correctly. Don't let your web server serve it as text/plain. Per-host, per-file — check the vhost config for each domain, not just the primary one.composer.json and a handful of classes, still growing fast enough that its API is unstable. If you adopt it, vendor a copy or be prepared to fork; the cost of forking is an afternoon, and that should inform your build-vs-buy call far more than the star count.How can I help you explore Laravel packages today?