backstage/laravel-trailing-slash
A Laravel package for controlling trailing slash behavior on your application's routes, letting you normalize, redirect, or enforce trailing slashes consistently. Keeps URLs canonical, avoids duplicate-content issues, and helps prevent mismatched redirects with simple, configurable middleware.
/pricing and /pricing/ are two indexable URLs for one page — and then makes the chosen answer enforceable globally, per route group, or per route. Without an explicit policy, each engineer and each CMS paste makes the call implicitly, which is exactly how duplicate-content debt accumulates.Consider adoption when:
route(), pagination, and canonical tags keep emitting the off-policy form, you have solved half the problem.Look elsewhere when:
index.php in the path, tracking-parameter stripping, host canonicalization — this package is one rule. You want a fuller canonicalization strategy, not a single narrow package.Recommended first step either way: a time-boxed spike. Read the source, confirm supported Laravel/PHP versions, and write tests for 301-vs-308 semantics, query-string preservation, non-GET behavior, signed-URL interaction, and route:cache/Octane compatibility. Pass, and you fork it. Fail, and you write ~40 lines of middleware plus a URL-generator hook yourself.
For executives. This is small, low-cost technical plumbing that closes a well-known SEO leak: the same page getting indexed under two URLs. It is not a feature — it is a correctness and hygiene fix that protects existing search equity and prevents a self-inflicted ranking problem during any site migration. Cost is measured in hours to a couple of days, not sprints, and there is no infrastructure, database, or vendor-contract surface. One caveat stated plainly: the package itself is essentially unproven in the wild (no community adoption, no third-party production use), so the recommendation is to adopt the approach and vendor the code under our own namespace rather than take on an unmaintained dependency. Net: low cost, low risk, modest but real upside in protected organic performance.
For engineering. One configurable middleware plus URL-generation behavior that enforces a single trailing-slash convention and issues redirects for off-policy requests. It replaces ad-hoc rtrim calls scattered across controllers and templates with one declared policy, configurable globally, per route group, or per route, preserving query strings and fragments and composing with named routes and the route() helper. It is small enough to audit in an afternoon and small enough to own: read it, fork it, and add regression tests for status code choice (301 for GET/HEAD, 308 — or no redirect — for non-idempotent methods), query-string preservation, signed-URL handling (a path rewrite invalidates ValidateSignature and yields 403s on password-reset links), route:cache/config:cache/Octane behavior, and trusted-proxy handling so redirect targets are not built from an untrusted host header. Treat it as a reference implementation; if the source's test posture is thin, vendor it into app/ with MIT attribution and isolate it behind a thin CanonicalUrl service and a single middleware, so the next Laravel major fails loudly in CI rather than silently in crawl data. If you already terminate at nginx or a CDN, do it there instead and skip the per-request cost.
How can I help you explore Laravel packages today?