samdark/sitemap
A lightweight sitemap generator for Yii2 applications. Build XML sitemaps and sitemap indexes, add URLs with last-modified, change-frequency, and priority metadata, and write or cache the output. Supports gzip compression and straightforward integration with Yii2 projects.
Architecture fit
samdark/sitemap is a narrow, single-responsibility library: it builds sitemap XML (<urlset>) and sitemap index XML (<sitemapindex>) documents from in-memory collections of URL entries. It is not a Laravel package — there is no service provider, no facade, no publishable config, and no Eloquent/queue/filesystem awareness. That is a deliberate design choice by the author (Alexander Makarov, a Yii core maintainer) and it means the library drops into a Laravel app as a plain Composer dependency behind our own integration layer.Storage facade for writing to local/S3 disks and with Response/streamed responses for serving. There is no impedance mismatch with our request lifecycle.Integration feasibility
composer require samdark/sitemap plus a thin adapter service is a one-day spike. The public surface is small (generator, index generator, sitemap/URL value objects), which means a low-cost wrapper and a low blast radius if we ever swap it out.lastmod, changefreq, priority, and, if needed, hreflang alternates), splitting into ≤50,000-URL / ≤50MB chunks, and emitting a matching index. Budget 3–5 engineer-days for a production-grade implementation including tests, not the 1 day the Composer install implies.storage/app/public/sitemaps/, a route or static file serves /sitemap.xml, and robots.txt references the index. No middleware or runtime dependency on the library in the hot path.Technical risk
lastmod formatting (W3C datetime), XML escaping of query strings and non-ASCII URLs, and whether image/video/news extensions or gzip output are in scope. Anything missing becomes our code, and gzip in particular is usually a wrapper concern rather than a library concern.chunkById and never Model::all().Key questions
ext-dom vs ext-xmlwriter) does the current release require, and does that match our fleet's baseline?lastmod formatting, hreflang xhtml:link alternates, and image/video/news extensions, or is that on us?Stack fit
SitemapBuilder service in app/Support/Sitemap that wraps SitemapGenerator/SitemapIndexGenerator, a set of SitemapSource implementations (one per content type: products, categories, CMS pages, blog posts), and an Artisan command sitemap:generate that orchestrates sources → chunks → files → index.Storage::disk('public')->put(...) or a dedicated sitemaps disk, so local dev and S3 prod behave identically. Serving is a static file behind the CDN — zero PHP in the request path.SitemapWriter), with a single adapter class as the only file importing samdark\sitemap\*. If we later migrate to spatie/laravel-sitemap or a homegrown XMLWriter, the swap is one class.Migration path
/sitemap.xml in routes or as a static file, and add the Sitemap: directive to robots.txt. Two PRs.spatie/laravel-sitemap: run both generators in parallel for a release, diff the output URL sets, then cut over and remove the old package. The migration is mostly about reproducing crawl-frequency and priority heuristics, which Spatie exposes via model methods and we would express as source-level policy.&, naive string concatenation) as a side effect.Compatibility
ext-* requirement in CI — our container image must include the XML extension explicitly rather than relying on a dev machine's defaults.Sequencing
composer.json.SitemapWriter + SitemapBuilder with unit tests covering escaping, lastmod format, and index chunk boundaries at 49,999/50,000/50,001 entries.SitemapSource classes using chunkById, starting with the highest-value content type; add a per-source URL cap and log truncation.robots.txt update, and a smoke test asserting well-formed XML and a reachable index.Maintenance
Support
sitemap:inspect --url= diagnostic early to answer that without engineering time.Scaling
chunkById) are mandatory; with them, peak memory stays flat regardless of corpus size.Cache-Control on the sitemap route and invalidate on regeneration, or content changes will lag crawl discovery by a full cache TTL.Failure modes
lastmod is within 48 hours and alert otherwise.& or invalid UTF-8 byte corrupts the document and Google rejects the whole file. Mitigate with a post-generation well-formedness validation step and sanitization at the source layer.withoutOverlapping() on the scheduled job.Ramp-up
lastmod honesty, priority/changefreq semantics, hreflang) and our source-registration convention. Budget a short written standard for what qualifies for inclusion.How can I help you explore Laravel packages today?