The viewer
Docuccino ships an interactive Scalar API reference and serves it straight from your Laravel app — no external service, no CDN required. It has a built-in try-it-out console, so readers can call your API from the docs.
Routes
Section titled “Routes”With the default viewer.route of /docs/api, three routes are registered per document:
| Route | Serves |
|---|---|
GET /docs/api |
The interactive API reference page. |
GET /docs/api.json |
The generated OpenAPI document. |
GET /docs/api/assets/scalar.js |
The viewer script, served from your app (no external CDN). |
Change the base path with viewer.route, or set it to null to register nothing for that document
(export still works). Setting enabled to false removes the routes for every document at once.
Each document gets its own set, so a second document on /docs/admin is entirely independent — see
multiple documents.
Access control
Section titled “Access control”The viewer is available automatically in your local environment. Anywhere else, it’s closed until you
name a gate:
-
Name a gate ability on the document:
// config/docuccino.php — documents.default.viewer'gate' => 'viewApiDocs', -
Define it in a service provider:
use Illuminate\Support\Facades\Gate;Gate::define('viewApiDocs', fn (?User $user): bool => $user?->isAdmin() ?? false);
The gate guards all three routes — the HTML page, the .json spec and the asset; a denial is a 403.
The browser fetches the script over the same session as the page, so a reader who is allowed in always
gets it.
Type the gate’s user parameter as nullable if you want guests to reach it (a public docs page behind a token check, say); otherwise Laravel refuses the guest before your closure runs.
Middleware
Section titled “Middleware”viewer.middleware is the full stack for all three routes. The default is:
'middleware' => ['web', 'throttle:60,1'],web gives you session state, which a gate on an authenticated user needs. Keep throttle whenever
the spec endpoint is reachable by anyone who isn’t signed in — with source: generate a request
rebuilds the whole document, which is expensive enough to be worth protecting.
Source modes
Section titled “Source modes”viewer.source decides how the served document is produced:
source |
Behavior |
|---|---|
generate |
Rebuilds the document on every request. Fine for local or gated use. |
artifact |
Re-emits the committed export.path — no analysis at request time. Serves an empty document if the file isn’t there. |
cache |
Serves the docuccino:cache-warmed payload; a cold cache falls back to generate and logs a warning. |
For anything public or high-traffic, prefer artifact or cache — see
Deploying to production.
A UIR artifact works as an artifact source too: it’s re-emitted through the OpenAPI emitter on the
way out, so provenance and internal identities never reach the browser.
Serving the asset
Section titled “Serving the asset”By default the Scalar script is bundled with the package and served from your own app, so the viewer works on locked-down networks with no outbound access. It’s a large file that only changes when you upgrade Docuccino, so it’s served with long-lived immutable cache headers and costs a reader one download.
To load it from a CDN instead — trading the offline guarantee for a byte you don’t serve — set
viewer.cdn:
'cdn' => true, // loads Scalar from jsDelivrThe page title comes from the document’s info.title, so the browser tab matches the API rather than
saying “API Documentation”.