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 Stoplight Elements Laravel Package

juststeveking/laravel-stoplight-elements

Laravel Stoplight Elements provides a simple way to render beautiful, interactive API documentation in your Laravel apps using the Stoplight Elements UI, with minimal setup and Blade integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and confirm the floor. composer require juststeveking/laravel-stoplight-elements — the 3.0.1 release widened support to Laravel 12.x, so verify your composer.json PHP floor before assuming fit. If the app is pinned below Laravel 11, this package buys you nothing yet.

Read the config before you write any code. Publish it and open the resulting file first; it is the whole API surface of this package:

php artisan vendor:publish --provider="JustSteveKing\StoplightElements\StoplightElementsServiceProvider"

(Publish tags are worth confirming with php artisan vendor:publish and reading the provider — the tag names are not the part of this package you should be guessing at.) In the config you are looking for four things, in this order of importance:

  1. Route toggle and path — is the docs route registered automatically, and at what URI? Change /docs if it collides with anything.
  2. Spec source — a local path or a remote URL. This is the only input that actually matters.
  3. Route middleware — whether the docs page is public by default, and where to add auth for internal APIs.
  4. Route domain — the 3.0.1 custom-domain option. Read the diff (PR #12) to see exactly what it changes before promising a branded portal to anyone.

Drop a spec in the repo. Put openapi.yaml (or .json) somewhere versioned — resources/openapi/ is a sane default — and point the config at it. If the package expects a web-reachable path rather than a filesystem path, you will need a small route or a public/ placement; check which the config intends before debugging a 404 you caused yourself.

First use case: one internal API, one route, behind auth. Add auth (or your internal middleware group) to the docs route, point the config at your existing spec, hit /docs, and confirm the sidebar renders tags and at least one endpoint expands. That is the entire v1. Anything beyond that is polish.

Verify it isn't a false positive. A 200 from the route proves the Blade view rendered, not that the docs work. Open devtools and confirm the Elements bundle loaded and the spec fetch succeeded. See Gotchas — this is the single most common way this package appears broken.

Implementation Patterns

Route-mounted reference (the default). One config, one route, one spec. Best for a single-service app where docs are a page, not a project. Keep the whole thing declarative — do not build a controller around it unless you have to.

Embedded Blade component. The package's real value is the Blade integration, so use it as one: mount the <x-stoplight-elements …>-style component inside an existing authenticated layout rather than using the auto-registered route. This gets you your app's nav, footer, auth, and styling for free, and keeps docs from looking like a bolted-on third-party page. Verify the component name and prop signature from the package's view/component class — that is the one place where copy-pasting from a README of a different version will bite you.

Multiple specs / internal catalog. For several services, the pattern that ages best is: one spec file per service in the repo, one route each, driven from a small array in config or a dedicated routes file. Do not try to concatenate specs — $ref resolution across merged documents is where you will lose a day. If you need a landing page, build a trivial index view that links to each route; that is cheaper than any merge tooling.

Serve the spec through a route, not public/. For anything not fully public, keep the OpenAPI file out of the webroot and expose it via a route with the same middleware as the docs page. The browser fetches the spec client-side, so the spec endpoint — not just the HTML — must be reachable and appropriately guarded. Getting this half-right is how internal endpoint inventories leak.

Remote spec URL. Supported, and useful when the spec is published from a separate pipeline or an API gateway. The trade-off: the browser, not your server, fetches it, so CORS on the spec host becomes your problem, and you have introduced a third-party uptime dependency into a page that was supposed to be self-contained. Prefer a local file unless there is a specific reason.

Custom domain (3.0.1). Set the domain in config, point DNS at the app, and make sure your web server / CDN serves the docs route on that host. Remember the spec fetch also needs to work from that origin — if your spec route is domain-constrained too, both must agree. Front it with a CDN; the docs page is static-ish and there is no reason to hit PHP for it on every view beyond the initial render.

CI: two cheap checks, both worth it. First, validate the spec itself (spectral lint or your OpenAPI tool of choice) — a malformed spec is a silent failure at runtime. Second, a smoke test that hits the docs route and asserts the expected markers plus a 200 on the spec URL. This catches route-cache and middleware regressions that a "deploy succeeded" signal will not.

Versioning. If you ship API versions, keep openapi/v1.yaml and openapi/v2.yaml side by side and give each a route. This package has no version-management UI; the filesystem is your version manager, and that is fine.

Gotchas and Tips

Rendering is client-side, so server logs lie. Elements is a JS web component. A blank docs page is almost never a Laravel error — it is a CSP block, an unreachable CDN, a failed spec fetch, or an invalid spec. Add explicit instrumentation for this: a CI smoke test, plus a console check on the first deploy to each environment.

CSP is the number one cause of blank pages. You need the Elements bundle host allowed in script-src (and likely style-src / font-src), and the spec origin in connect-src. If you run a strict CSP in production but not locally, this will work everywhere except where it matters.

Spec fetch failures are invisible. Confirm the browser can reach the spec URL as the end user, not just as curl from your laptop. Auth middleware on the spec route that returns a redirect to a login page produces a confusing parse error rather than a 401 — the fetch "succeeded" with HTML.

YAML gotchas. Tabs, unquoted colons in descriptions, and $refs pointing at sibling files that are not reachable over HTTP. If your spec is split across files with relative $refs, either bundle it at build time or host the whole tree. Single-file specs are the path of least resistance.

Swagger 2.0 is supported but stop there. If the spec is 2.0, converting to 3.x once is a better investment than straddling both — tooling, validation, and Elements' own feature coverage all lean 3.x.

Config and route caching. In a cached production environment, config changes need php artisan config:clear / a redeploy, and the docs route needs route:cache rebuilt. This accounts for a large share of "I changed the spec path and nothing happened."

Try-it-out sends real requests from the user's browser. That means CORS on your API, and it means an authenticated endpoint will fail unless the user is already authenticated against the API's own auth. For internal docs this is often a feature; for public docs, decide deliberately which endpoints are marked try-it-out and make sure no destructive endpoint is a single click away.

Publish and own the view. Customize branding by publishing views, and commit the published view to your repo. This is what makes the dependency reversible — when you swap renderers later, you keep the design intent. Same reasoning applies to the spec itself: it is your artifact, the package is only a presentation layer.

Pin ^3.0 and diarize a review. Single maintainer, 44 stars, zero published dependents. The Laravel 12 fix arrived as a patch, which tells you to expect a maintenance release at each future Laravel major. Add this package to the framework-upgrade runbook now, while it costs nothing, rather than discovering it mid-migration.

Do not let the word "documentation" oversell it. This renders an API reference. It has no quickstarts, guides, tutorials, or versioned prose. If a stakeholder expects a narrative developer portal, the gap surfaces at launch review — call it an "API reference" from the first conversation.

Large specs hurt. Multi-megabyte specs make first paint noticeably slow. If you are there, split by tag into separate docs pages or trim descriptions; the renderer is not the bottleneck, the payload is.

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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle