nucleos/sitemap-bundle
NucleosSitemapBundle is a Symfony bundle for generating XML sitemaps from routes, Doctrine entities, and custom providers. It supports sitemap indexes, URL sets, priorities, change frequencies, last-modified dates, and caching, making it easy to expose content to search engines.
First, the framework mismatch: nucleos/sitemap-bundle is a Symfony bundle, not a Laravel package. It has no Laravel service provider, no facade, and no config/sitemap.php. In a Laravel app you cannot composer require it and expect it to work; the closest Laravel-native equivalent is spatie/laravel-sitemap. Treat this package as usable only in a Symfony application (or a highly unusual mixed stack where you already run Symfony's routing/HTTP kernel).
Second, and newly relevant: 4.4.0 formally deprecates the project in favor of nucleos/seo-bundle (PR #483). If you are starting fresh today, do not adopt this bundle — go to nucleos/seo-bundle (or spatie/laravel-sitemap on Laravel). Only stay here if you are maintaining an existing install and need a deliberate migration window.
Minimal Symfony setup (existing installs only):
composer require nucleos/sitemap-bundle — pin to ^4.4 knowingly; this is the final feature line.Nucleos\SitemapBundle\NucleosSitemapBundle in config/bundles.php./sitemap.xml controller is never reachable):
# config/routes.yaml
nucleos_sitemap:
resource: "@NucleosSitemapBundle/Resources/config/routing.xml"
config/packages/nucleos_sitemap.yaml if you need to change the route path, template, or pagination size./sitemap.xml. With no URL providers registered you should get a valid but empty <urlset> — that confirms wiring before you add content.Where to look first:
README.md (sparse — the package has 5 stars and 0 dependents, so docs are thin).DependencyInjection/Configuration.php for the actual config keys.Controller/ for the route shape (/sitemap.xml plus a paginated /sitemap.{page}.xml variant).Sitemap/ for the UrlSet / Url model classes you will populate.nucleos/seo-bundle docs — the deprecation notice points there, so that is the API you will be porting to.First real use case: populate the URL set from an event subscriber (dynamic pages such as blog posts or product detail pages) rather than trying to auto-crawl routes.
Event-driven population (the primary pattern). The bundle exposes a sitemap event/subscriber hook. Register a listener, receive the UrlSet, and append Url objects with absolute loc, lastmod, changefreq, and priority. This is how you feed DB-backed content:
public function onSitemap(SitemapEvent $event): void
{
foreach ($this->posts->findPublished() as $post) {
$event->getUrlSet()->add(new Url(
$this->router->generate('post_show', ['slug' => $post->slug], UrlGeneratorInterface::ABSOLUTE_URL),
$post->updatedAt,
'weekly',
0.8
));
}
}
Route-derived static pages. For a small set of static routes, enumerate them explicitly in the same subscriber (home, about, contact) rather than reflecting over the router — reflection picks up admin, auth, and API routes you don't want in a sitemap.
Sitemap index for large sites. Once you exceed ~50,000 URLs or 50 MB uncompressed, use the paginated route as a sitemap index target: emit sitemap.1.xml, sitemap.2.xml, … and a top-level index. Keep pagination deterministic (stable ordering by ID) so search engines don't see churn between crawls.
Caching. Sitemap generation is often a full table scan. Generate on a schedule into a static file or wrap the controller response in Symfony's HTTP cache with a short TTL plus tag-based invalidation on content changes. If you have a queue, generate off-request.
Migration pattern to nucleos/seo-bundle. The deprecation is an API reshuffle, not a data change. In practice:
Url construction, static route enumeration) as the unit that survives; only the event class, bundle name, and config namespace change./sitemap.xml output byte-for-byte (xmllint --format both) before cutting over.nucleos_sitemap into the SEO bundle's namespace; re-read the SEO bundle's Configuration.php rather than copying old YAML across./sitemap.xml path is either redirected or preserved.Laravel translation of the same pattern, if you're porting the idea:
public/sitemap.xml.Content-Type: application/xml.spatie/laravel-sitemap for the crawling/URL-set side instead of reimplementing UrlSet.nucleos/seo-bundle. This is the end of the line: no further feature work, no PHP 8.3/Symfony 7 compatibility fixes. Budget the migration now rather than pinning indefinitely.^4.3 will float you onto the deprecated line silently. Pin exactly if you need to freeze behavior, and read the changelog, not just the version number.loc must be absolute and use the public scheme/host. Behind a proxy this silently becomes http://localhost/.... Configure framework.router.default_uri / trusted proxies, or generate with an explicit context.lastmod formatting. Use DateTimeInterface; emit W3C/ISO-8601. Watch timezones — a lastmod in the future is treated as unreliable by crawlers.&, ?, or non-ASCII must be escaped by the renderer. If you override the template, don't hand-concatenate strings.xmllint --noout sitemap.xml for well-formedness; assert the response Content-Type is XML; log the UrlSet count in the subscriber to confirm it fires.nucleos_sitemap.spatie/laravel-sitemap plus a scheduled command — you'll spend less time than wiring Symfony routing and DI into an artisan context. The 4.4.0 deprecation makes this even clearer: there will never be a Laravel story here.How can I help you explore Laravel packages today?