Skip to content

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.

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.

The viewer is available automatically in your local environment. Anywhere else, it’s closed until you name a gate:

  1. Name a gate ability on the document:

    // config/docuccino.php — documents.default.viewer
    'gate' => 'viewApiDocs',
  2. 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.

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.

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.

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 jsDelivr

The page title comes from the document’s info.title, so the browser tab matches the API rather than saying “API Documentation”.