wotz/laravel-swagger-ui
Laravel Swagger UI exposes your OpenAPI v3 JSON or YAML file through a built-in Swagger UI at /swagger, automatically using the current environment’s base URL. Install via Composer, publish the config, and customize paths, versions, access gates, and OAuth2 settings.
What it actually is. A thin presentation layer: it registers a route, gates access, serves the Swagger UI static bundle, and rewrites fields in an OpenAPI v3 JSON/YAML document (server URL, OAuth2 endpoints, URL variables) so the "Try it out" console points at the current environment. It does not generate or validate OpenAPI documents. That distinction is the single most important thing to socialize — stakeholders who hear "Swagger package" often assume spec generation is included (it isn't; pair it with Scramble, Scribe, or hand-maintained specs).
Architecture fit. Excellent fit for a standard Laravel app. Composer-installed, auto-discovered service provider, an install command that publishes config/swagger-ui.php and app/Providers/SwaggerUiServiceProvider.php, one route (/swagger by default), no database, no queue, no migrations, no persistent state. It sits at the edge of the request lifecycle and introduces no coupling into domain code. For teams already on Laravel 11/12/13, this is a same-day integration for a single engineer.
Integration feasibility. Low effort, low ambiguity. Config surface is well-bounded: path, versions map, modify_file, server_url + server_variables, OAuth block, middleware array, page title, custom CSS, validator URL. The versions map is the standout feature for a product with a versioned API — one UI, multiple spec files, one gate. External-URL specs (added 0.5.0) let us point at a spec published by a separate docs pipeline, which decouples the viewer from our release train.
Technical risk.
client_secret in the browser config. The README shows pre-filling OAuth2 client ID and secret into the Swagger UI auth panel. Even scoped, shipping a secret to a browser is an anti-pattern; treat it as public-client/PKCE only and refuse the secret path in review.auth:api + the gate, with optional Passport OAuth routes. Useful, but it converts a read-only docs page into a machine-callable interface over your API description. Do not enable it as a side effect of upgrading; treat it as a separate, security-reviewed decision.Key questions to answer before we commit.
mcp.enabled => false and revisit deliberately.Stack fit. Ideal for Laravel 11/12/13 on PHP 8.3/8.4. No constraints on database, cache, or queue drivers. Works identically in local, CI, staging, and prod — the only behavioral fork is the gate.
Prerequisites to sequence first. Decide the spec source. Options: (a) generated at build time by Scramble/Scribe and committed to resources/swagger/, (b) generated in CI and published to a static URL and referenced via the versions map, (c) hand-authored. Option (b) gives the cleanest separation: the viewer package never blocks a release, and spec generation failures surface in CI, not in a broken /swagger page.
Migration path. There's nothing to migrate from unless we already run l5-swagger or dedoc/scramble's built-in UI. In that case, run both side-by-side behind different paths for one sprint, diff the rendered specs, then retire the old route. Because the package is a viewer only, retaining the existing generator avoids a docs regression.
Compatibility checklist. Confirm: Laravel major → package major mapping (2.x line for Laravel 11+); reverse-proxy behavior with modify_file => true; APP_URL correctness in every environment, since server-URL rewriting derives from it; middleware array set to at minimum web plus our auth stack in non-local; no route collision on the configured path.
Sequencing (proposed).
client_secret is not populated, confirm /swagger and the spec route both 404/403 anonymously in staging.modify_file => true, validate multi-version routing, exercise OAuth2 auth from the UI, verify behind the CDN/proxy.auth:api token lifecycle.Rollback. Trivial: remove the route via config or drop the dependency; nothing else in the app references it. This is the strongest argument for adopting — the exit cost is effectively zero.
Maintenance. Low but non-zero. Two ongoing duties: (1) track the upstream major line against our Laravel upgrade cadence — expect a breaking release roughly once per framework major; (2) keep the OpenAPI source honest, which is the actual recurring cost and is entirely on us, not on the package. Pin to a minor (^2.1) and let a bot open PRs for patches, with a human gate on any major.
Support and ownership. Assign a named owner on the platform/API team. Vendor support doesn't exist beyond GitHub issues; the security channel is a personal email. For a 280-star package with zero dependents, assume self-support and budget the fork option. Ensure the license (MIT) and attribution are captured in our dependency register — MIT is unproblematic.
Scaling. Effectively a static page plus a file served per request. Negligible CPU and memory; no shared state; horizontally scales with the app tier without special handling. The only cost lever worth attention is caching the served spec and the bundled assets at the CDN, and avoiding per-request file parsing on high-traffic hosts — the spec route is internal-facing, so volume should be low anyway.
Failure modes and blast radius. All failures are cosmetic or access-related, none data-corrupting:
Ramp-up. Very low. An engineer unfamiliar with the codebase needs roughly two to four hours to install, read the config, and understand the gate. A reviewer needs less. Document the gate policy and the "spec is generated elsewhere" fact in the service README so the next person doesn't rediscover it.
Verdict. Adopt, with conditions: viewer-only scope (generator owned separately), MCP explicitly off until a separate review, non-local access gated by an auditable policy enforced in CI, and a scheduled review at each Laravel major. The low score and zero-dependent count reflect modest ecosystem traction, not instability — and the near-zero integration and exit cost make this a low-consequence decision.
How can I help you explore Laravel packages today?