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

Trailing Slash Laravel Package

middlewares/trailing-slash

Laravel middleware that normalizes trailing slashes by redirecting URLs to your preferred format, with configurable behavior, query-string preservation, and clean handling of requests that already match.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Canonical URL policy: decide it once, enforce it globally. Product has to pick a single canonical form (/about vs /about/) or accept that analytics, sitemaps, canonical tags, and cache keys will disagree. This package turns that policy decision into a ~10-line configuration instead of a per-route convention nobody follows.
  • SEO/duplicate-content risk mitigation. Two reachable URLs for one page splits link equity and inflates crawl budget. A 301 that preserves query strings is the standard remedy, and it is a cheap, measurable fix we can ship without touching routing or templates.
  • Build vs. buy (and here, buy ≈ vendor). The alternative is a hand-rolled middleware — roughly a day of engineering plus permanent ownership of edge cases (query strings, POST bodies, root /, empty paths, infinite redirect loops, proxies). This is MIT, dependency-free, and small enough to audit fully and fork if abandoned. Vendoring is a legitimate exit ramp.
  • Roadmap scoping for URL/navigation work. If we are planning site migrations, IA changes, slug rewrites, or a legacy-to-new URL map, this belongs in the same epic as the redirect map rather than as a follow-up ticket. It sets the rule; the redirect map handles the exceptions.
  • Use cases worth flagging: legacy CMS migrations, marketing sites with inconsistent editor-entered links, multi-brand/multi-locale sites where path handling drifts, and consolidation after an acquisition where two apps resolve the same content differently.
  • Explicit non-decision: it is not an API contract tool. For JSON/API surfaces, trailing-slash semantics are part of the contract and a global redirect is the wrong lever. Product should scope this to HTML/document routes only.

PM caveat to record before committing: despite the description saying "Laravel," this is a PSR-15 middleware, and Laravel's HTTP kernel is not natively PSR-15. Adopting it in a Laravel app means adding a PSR-15 bridge and owning that integration. That is a real cost, and it changes the build-vs-buy math — for a Laravel-only estate, framework-native middleware or a web-server/CDN rewrite is usually the better call.

When to Consider This Package

Consider it when:

  • The stack is genuinely PSR-7/PSR-15 native (Slim, Mezzio/Laminas, custom PSR-15 pipelines) — here it is a drop-in with no adapter cost.
  • The desired rule is global and uniform, with few or no legitimate per-route exceptions.
  • The team can place it deliberately in the pipeline (before routing, after error handling) and can reason about ordering.
  • Traffic is modest enough that per-request redirects at the app layer are acceptable, or a CDN edge rule is not yet available.
  • We want a dependency-free, auditable, forkable implementation and are comfortable pinning a version with a single maintainer.
  • We need query-string preservation on the redirect without writing it ourselves.

Look elsewhere when:

  • The estate is Laravel-first — prefer a Laravel-native middleware or a reverse-proxy rewrite; do not pay the PSR-15 bridge tax for one redirect rule.
  • Redirects belong at the edge (nginx/Cloudflare/ALB). Doing this in PHP adds latency to every non-canonical request and risks redirect chains behind a proxy that already rewrites.
  • Per-route exceptions are common (e.g., some routes intentionally keep a slash) — a global toggle becomes a source of bugs.
  • Requirements include 308, method preservation, locale-aware rules, A/B or experiment-aware routing, or redirect observability/metrics.
  • The API surface matters — global normalization can silently change semantics for endpoints where /resource and /resource/ differ.
  • Maintenance risk is unacceptable for a tier-1 path. 32 stars and a low health score mean one maintainer; acceptable only because the code is tiny, MIT, and easy to vendor. If we cannot accept that, write 30 lines ourselves.
  • Anything behind auth or stateful POSTs where a 301 is cached by browsers — this needs explicit design review, not a config flag.

How to Pitch It (Stakeholders)

One-liner for execs: A small, free, MIT-licensed component that makes every page exist at exactly one URL — protecting search ranking and cleaning up analytics — at the cost of roughly a day of engineering, not a project.

For engineering: PSR-15 middleware, zero dependencies, ~a few hundred lines, configurable add/remove mode, 301s with query string preserved, MIT so we can vendor or fork. We control placement in the pipeline and can audit the whole thing in an afternoon. If we are not PSR-15 native (i.e., Laravel), the honest recommendation is a bridge or a proxy rule instead — we should say that out loud rather than force the fit.

Framing the trade: the real decision isn't "this package vs. nothing," it's "a documented canonical URL policy owned by someone" vs. "duplicate URLs discovered six months from now in a Search Console report." This is the cheapest possible way to have that policy, provided the stack fits.

Risk posture: low technical risk, moderate supply-chain risk (single maintainer, modest adoption), mitigated by MIT licensing, tiny surface area, and a version pin. Not a tier-1 dependency we should build a strategy on — a utility we adopt, pin, and can replace in an hour.

Success measures: share of pages reachable at exactly one URL; 301 volume and absence of redirect chains/loops; Search Console duplicate-canonical counts trending down; analytics pageviews consolidating on the canonical path.

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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator