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

kunstmaan/sitemap-bundle

Symfony bundle for generating XML sitemaps for Kunstmaan CMS sites. It integrates with Kunstmaan page/node structures, provides sitemap generation and routing, and helps expose search-engine-friendly sitemap URLs for your application.

View on GitHub
Deep Wiki
Context7

Getting Started

First, a reality check. kunstmaan/sitemap-bundle is a Symfony bundle, not a Laravel package. It targets the Kunstmaan CMS stack (kunstmaan/node-bundle, Doctrine ORM, Symfony 2.x-era DI), was last released in 2014-04-05, has 10 stars and zero dependents. There is no service provider, no facade, and no Laravel integration surface. Installing it into a Laravel app will not get you a working sitemap.xml; it will get you a bundle whose kernel/DI/config expectations Laravel does not satisfy.

So "getting started" splits into two paths:

Path A — you're actually on a Kunstmaan/Symfony site (the intended use case):

  1. composer require kunstmaan/sitemap-bundle (pin to your Symfony version; expect old constraint conflicts).
  2. Register the bundle in AppKernel.php, and confirm the node bundle it depends on is present — the generators enumerate Node entities.
  3. Expose the route provided by the bundle's SitemapController (typically /sitemap.xml) and check the config for the cache directory used to store the generated file.
  4. Generate the static file with the bundle's console command (kuma:sitemap:generate) and point your web server at the cached file, or serve the dynamic controller response.

Path B — you're a Laravel developer evaluating this for a Laravel project (the realistic one):

  • Read the source as a reference implementation, don't install it. The useful idea is small: an abstract generator base class where each generator calls addUrl($url, $priority, $changeFreq) into a shared collection, a service that aggregates all registered generators, and a command/route that renders the collection to XML.
  • For an actual Laravel site, use spatie/laravel-sitemap and write custom generators that mirror the Kunstmaan pattern (one generator per content type, registered in a service provider).
  • First use case to port: "one <url> per published, non-hidden, localized node with a canonical absolute URL." That is 90% of what this bundle does for a Kunstmaan site.

Implementation Patterns

Custom generator (the extension point that matters). The bundle's contract is: subclass the abstract sitemap generator, implement your getUrls()-style logic, and tag the service so the aggregator picks it up (the tag is kunstmaan_sitemap.sitemap_generator in the bundle's DI convention). Inside the generator you call the protected addUrl() helper; you never build XML yourself.

// Symfony/Kunstmaan — the intended pattern
class ArticleSitemapGenerator extends AbstractSitemapGenerator
{
    public function __construct(private EntityManagerInterface $em) {}

    public function getUrls(): array
    {
        foreach ($this->em->getRepository(Article::class)->findPublished() as $article) {
            $this->addUrl($article->getAbsoluteUrl(), 0.8, 'weekly');
        }
        return parent::getUrls();
    }
}

Aggregation and rendering. The central sitemap service iterates every registered generator in order, concatenates their URLs, and either renders a template to XML on the fly or writes it to the configured cache file. Keep generators side-effect free and deterministic — ordering of output is registration order, which is fragile, so don't rely on it for anything meaningful.

Static file + cron is the production pattern. Because sitemaps change slowly, the common workflow is: scheduled command regenerates the cached XML (hourly/nightly), a web-server rule or route serves that static file, and sitemap.xml never touches PHP per request. This mirrors what you'd do in Laravel with Schedule::command('sitemap:generate')->hourly() writing to public/sitemap.xml.

Laravel translation of the pattern. Keep the same shape but use Laravel idioms:

// app/Sitemap/SitemapGenerator.php
interface SitemapGenerator { public function urls(): iterable; }

Register implementations in a dedicated SitemapServiceProvider, tag them in a container binding ($this->app->tag([...], 'sitemap.generator')), and resolve them with $this->app->tagged('sitemap.generator') in a GenerateSitemap action class. Then a SitemapController or the spatie/laravel-sitemap builder renders the collection. The result is the same architecture with Symfony-era baggage removed.

Localization / multi-language sites. Kunstmaan nodes are localized, so the bundle's generators typically emit one URL per active locale. If you port this, do the locale loop inside each generator (or in a decorator) so you don't scatter ?lang= logic across controllers. Watch for duplicate canonical URLs across locales — dedupe on (path, locale default).

Sitemap index for large sites. Neither the bundle nor a naive port enforces the 50,000-URL / 50 MB-per-file limits. If you're above a few thousand URLs, wrap generators so each content type produces its own file and emit a <sitemapindex> — do this in the aggregator, not in individual generators.

Gotchas and Tips

  • Abandoned dependency risk. Last release 2014, no security maintenance, Symfony 2.x constraints, old Doctrine API. Do not add this to a new project. Treat the repository as documentation, not a dependency.
  • Cache directory permissions. The static-file path is the single most common failure: generation succeeds in CLI (different user) and the web server can't read/overwrite the file, or the reverse. Align www-data and the cron user, and log the resolved absolute path on startup.
  • Generation is not incremental. Every run rebuilds the whole URL set by hydrating every node. On a large Kunstmaan tree this is slow and memory-heavy; paginate repository queries inside generators (iterate() / batch) rather than findAll().
  • XML escaping and absolute URLs. addUrl() does not guarantee escaping or absolutization. Pass fully-qualified https:// URLs with no trailing-slash ambiguity, and run the output through a sanity check — one bad & in a slug breaks the whole document.
  • priority and changeFreq are largely ignored by Google. Don't spend design time on them; correctness of <loc> and lastmod matters far more.
  • Debugging a missing URL. Order of checks: (1) is the generator service tagged and public enough to be resolved — inspect the container (debug:container --tag=...); (2) does the generator filter out unpublished/hidden nodes; (3) is the sitemap being served from a stale cache file rather than regenerated. That third one wastes the most time; always regenerate before debugging generation logic.
  • Extension points worth knowing. The registered-generator tag (add content types without touching the bundle) and the abstract generator base class (addUrl helper). There is no meaningful event system — don't go looking for one.
  • Serve correct headers. Content-Type: application/xml; charset=utf-8, and consider gzip at the web-server layer rather than in PHP. If you serve the dynamic controller instead of a static file, make sure caching headers don't pin a stale sitemap forever.
  • Verify output like a parser, not a human. Pipe the generated file through an XML validator and a URL-crawler check in CI; eyeballing sitemap.xml will not catch the unescaped ampersand or the duplicate locale entries.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource