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

Laravel Trailing Slash Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Declaring one canonical URL convention (and living with it). Trailing slash or no trailing slash is a product decision, not a code-style preference. This package forces the question into the open — /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.
  • Search-equity consolidation as roadmap hygiene. Canonical tags, sitemaps, pagination links, and 301 hygiene are usually deferred to "later." This gives SEO/content work a concrete implementable mechanism: one declared form for generated URLs plus 301s for off-policy inbound requests. It supports roadmap scoping for sitemap accuracy and canonical-tag correctness, and gives you a defensible answer in crawl-budget and indexing reviews.
  • Migration and legacy inbound-link decisions. If you are moving off a platform with the opposite convention (WordPress-era rewrite rules, static-site directory URLs, older marketing microsites), your backlinks and rankings point at the "wrong" form. The product decision is: redirect permanently, serve both, or accept the loss. This package gives you the "redirect" branch, with query strings preserved so campaign parameters survive.
  • Build-vs-buy framed honestly as adopt-vs-fork. Scope is narrow enough to be a solid afternoon of in-house middleware. The decision is whether you want a maintained, configurable, opinionated surface — global/group/route configuration, redirect behavior, URL-generation integration — or ~50 lines you fully own. With 0 stars, 0 dependents, and a low composite score, the realistic framing is fork-and-own, not depend-and-own.
  • Concrete product use cases to plan against: multi-brand or multi-domain apps sharing one route table; a directory-style policy for web routes alongside API routes that must never redirect; canonical and pagination-link generation that must match the inbound convention; preserving campaign and backlink URLs across relaunches; and test-suite assertions that redirects fire with the correct status code, preserve query strings, and do not fire on POST.
  • Metrics this puts in reach: 301-vs-200 counts on variant URLs, crawl reports showing duplicate-but-variant pages, average redirect-chain depth from legacy inbound links, and canonical/self-URL mismatch rate in rendered pages. Those are the numbers that tell you whether the policy actually holds.

When to Consider This Package

Consider adoption when:

  • You have, or are about to publish, an explicit canonical policy, and route definitions, Blade links, and CMS-pasted URLs are already inconsistent.
  • You do not control the nginx/Apache or CDN layer — platform ownership sits elsewhere — so normalization has to happen in the application.
  • You need URL generation to match the policy, not just inbound redirects. If route(), pagination, and canonical tags keep emitting the off-policy form, you have solved half the problem.
  • You are migrating from a platform with the opposite convention and need inbound backlink preservation without rewriting thousands of templates.
  • You have read the source and are comfortable pinning a commit or vendoring it under your own namespace.

Look elsewhere when:

  • You own the edge. An nginx or CDN rewrite is cheaper, faster, covers non-Laravel paths, and removes per-request PHP overhead. For a single app on a single host, this is the default answer.
  • You are API-only. Programmatic clients gain nothing from redirects; you would be adding latency and 3xx handling they do not expect.
  • You need broader normalization. Case, duplicate slashes, 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.
  • Adoption risk dominates scope. Zero stars, zero dependents, single maintainer, unproven Laravel-version compatibility. For a revenue-critical site, treat it as a reference implementation, not a dependency.
  • Nobody will own it. An abandoned middleware that silently stops redirecting after a framework upgrade is worse than no middleware, because you will not notice until crawl data degrades.

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.

How to Pitch It (Stakeholders)

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.

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