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

Sitemap Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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):

  1. composer require nucleos/sitemap-bundle — pin to ^4.4 knowingly; this is the final feature line.
  2. Register Nucleos\SitemapBundle\NucleosSitemapBundle in config/bundles.php.
  3. Import the bundle routing (it ships an opt-in routing file; without this the /sitemap.xml controller is never reachable):
    # config/routes.yaml
    nucleos_sitemap:
        resource: "@NucleosSitemapBundle/Resources/config/routing.xml"
    
  4. Create config/packages/nucleos_sitemap.yaml if you need to change the route path, template, or pagination size.
  5. Visit /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.
  • The 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.

Implementation Patterns

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:

  • Keep your subscriber logic (DB queries, Url construction, static route enumeration) as the unit that survives; only the event class, bundle name, and config namespace change.
  • Register the SEO bundle alongside/after the sitemap bundle, keep both routings live temporarily, and diff /sitemap.xml output byte-for-byte (xmllint --format both) before cutting over.
  • Ported config moves out of nucleos_sitemap into the SEO bundle's namespace; re-read the SEO bundle's Configuration.php rather than copying old YAML across.
  • Remove the old bundle registration only after the new route serves identical URLs and the old /sitemap.xml path is either redirected or preserved.

Laravel translation of the same pattern, if you're porting the idea:

  • A queued job / scheduled command writes public/sitemap.xml.
  • A route returns it with Content-Type: application/xml.
  • Use spatie/laravel-sitemap for the crawling/URL-set side instead of reimplementing UrlSet.

Gotchas and Tips

  • Deprecated as of 4.4.0 (2022-09-18). The single PR in this release is a formal deprecation pointing at 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.
  • The deprecation shipped under a "minor / feature release" label but is tagged BC Break. Composer constraint semantics won't warn you — ^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.
  • Routes are opt-in. The most common "it doesn't work" is forgetting to import the bundle routing. You'll get a 404, not an error.
  • Absolute URLs and router context. 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.
  • XML escaping. Titles/slugs with &, ?, or non-ASCII must be escaped by the renderer. If you override the template, don't hand-concatenate strings.
  • Pagination limits. Cap page size (typically 50k URLs) and ensure the index lists every page; an off-by-one leaves content uncrawled with no visible error.
  • Debugging. 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.
  • Extension points. Decorate the URL-set/builder service, override the Twig template via the bundle's template namespace, or replace the controller route entirely. Configuration lives under nucleos_sitemap.
  • Don't force it into Laravel. There is no adapter, no facade, no Laravel service provider. For a Laravel project the pragmatic choice is 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.
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.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment