swagger-api/swagger-ui
Swagger UI renders interactive API documentation from your OpenAPI/Swagger spec. Let developers and consumers explore endpoints, try requests, and see schemas without backend implementation. Available as npm modules (swagger-ui, swagger-ui-dist) and Docker image.
Install via npm (for frontend integration):
npm install swagger-ui-dist --save
Or use the standalone dist files from releases.
Publish OpenAPI/Swagger Spec:
swagger.json or openapi.yaml file (use packages like darkaonline/l5-swagger or zircote/swagger-php).public/docs/swagger.json or serve it via an API route (e.g., route('api.swagger')).Basic HTML Integration (in resources/views/docs.blade.php):
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="{{ asset('vendor/swagger-ui-dist/swagger-ui.css') }}">
</head>
<body>
<div id="swagger-ui"></div>
<script src="{{ asset('vendor/swagger-ui-dist/swagger-ui-bundle.js') }}"></script>
<script>
const ui = SwaggerUIBundle({
url: "{{ route('api.swagger') }}",
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
});
</script>
</body>
</html>
Route Access:
Route::get('/docs', function () {
return view('docs');
})->name('docs');
Route::get('/api/swagger', function () {
return response()->json(file_get_contents(storage_path('app/swagger.json')));
})->name('api.swagger');
url: "{{ route('api.swagger') }}?version={{ config('app.version') }}",
ui.initOAuth({
clientId: "{{ config('services.swagger.client_id') }}",
appName: "Laravel API Docs",
scopes: "read write",
usePkceWithAuthorizationCodeGrant: true,
});
SecurityDefinitions section to your Swagger spec:
securityDefinitions:
Bearer:
type: apiKey
name: Authorization
in: header
Then configure Swagger UI to pre-fill the header:
ui.preauthorizeApiKey('Authorization', 'Bearer {{ auth()->token() }}');
resources/sass/swagger.scss:
// Target Swagger UI classes
.topbar-wrapper {
background-color: #2d3748;
}
mix.sass('resources/sass/swagger.scss', 'public/css');
SwaggerUIBundle.plugins.SwaggerUIStandalonePreset.injectStylesheet(
'https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css'
);
SwaggerUIBundle.plugins.SwaggerUIStandalonePreset.addRequestInterceptor((request) => {
console.log('API Call:', request);
return request;
});
Route::prefix('v1')->group(function () {
// v1 routes
});
Route::prefix('v2')->group(function () {
// v2 routes
});
url: "{{ route('api.swagger') }}?version=v1",
app/Http/Middleware/Cors.php):
protected $allowedMethods = ['*'];
protected $allowedOrigins = ['http://localhost:8000', 'https://your-ui-domain.com'];
Route::get('/proxy/{path}', function ($path) {
return response()->streamDownload(function () {
$ch = curl_init("https://api.example.com/{$path}");
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
}, "response.json");
});
Cookie or Authorization may be stripped by browsers.securityDefinitions in Swagger to document auth headers.query or header parameters with in: cookie (but note browser limitations).clientSecret in frontend JS exposes it.usePkceWithAuthorizationCodeGrant: true to avoid client secrets./docs#/pets/getPetById).Route::get('/docs/pets/{id}', function ($id) {
return view('docs', ['initialUrl' => "pets/getPetById/{$id}"]);
})->name('docs.pets');
url: "{{ route('api.swagger') }}",
initialValue: "{{ $initialUrl ?? '' }}",
Route::get('/api/swagger', function () {
return Cache::remember('swagger-spec', now()->addHours(1), function () {
return response()->json(file_get_contents(storage_path('app/swagger.json')));
});
});
F12) to inspect Swagger UI errors.package.json:
"scarfSettings": { "enabled": false }
// vite.config.js
export default {
build: {
assetsDir: 'assets',
outDir: 'public/dist',
},
};
<script>
const swaggerConfig = @json([
'clientId' => env('SWAGGER_CLIENT_ID'),
'url' => route('api.swagger'),
]);
</script>
SwaggerUIBundle.plugins.SwaggerUIStandalonePreset.addButton({
className: 'copy-curl',
label: 'Copy as cURL',
onClick: (ui) => {
const curl = ui.getOperationCurl();
navigator.clipboard.writeText(curl);
ui.addNotification('Copied to clipboard!');
},
});
How can I help you explore Laravel packages today?