Scalar Module
Scalar Module
The Scalar Module is a pre-built SvelteKit route handler that serves your OpenAPI schema and renders beautiful interactive API documentation using Scalar .
What is ScalarModule?
ScalarModule provides two endpoints in one:
- OpenAPI JSON - Serves the generated OpenAPI schema
- Scalar UI - Renders interactive documentation
It's designed to be dropped into a dynamic route like src/routes/api-docs/[slug]/+server.ts where the slug parameter determines which endpoint to serve.
Basic Setup
Create a docs route in your SvelteKit app:
// src/routes/api-docs/[slug]/+server.ts
import ScalarModule from 'sveltekit-auto-openapi/scalar-module';
export const { GET, _config } = ScalarModule({
openApiOpts: {
openapi: '3.0.0',
info: {
title: 'My API',
version: '1.0.0',
description: 'My awesome API built with SvelteKit'
},
},
}); That's it! Now you have:
- OpenAPI schema at
/api-docs/openapi.json - Interactive docs at
/api-docs/scalar
How It Works
When a request arrives:
- ScalarModule checks the
slugparameter - If
slug === 'openapi.json':- Imports the virtual module with generated schemas
- Merges with your
openApiOpts - Returns OpenAPI JSON
- If
slug === 'scalar':- Generates HTML with embedded Scalar UI
- Configures Scalar to load schema from
/api-docs/openapi.json - Returns interactive documentation
Configuration Options
ScalarModule accepts an options object with these properties:
disableOpenApi
- Type:
boolean - Default:
false
Disables the OpenAPI JSON endpoint.
ScalarModule({
disableOpenApi: true, // No /api-docs/openapi.json
}) Use case: When you want to serve the Scalar UI but provide the OpenAPI schema from elsewhere.
openApiPath
- Type:
string - Default:
"openapi.json"
The slug value that serves the OpenAPI schema.
ScalarModule({
openApiPath: 'schema.json', // Serve at /api-docs/schema.json
}) showDetailedDocsSchema
- Type:
boolean - Default:
false
Includes detailed validation metadata in the schema (makes it larger).
ScalarModule({
showDetailedDocsSchema: true,
}) When enabled, the schema includes:
- Detailed error messages
- Validation keywords
- Internal metadata
Trade-off: More detailed schema but larger payload size.
skipDocsValidation
- Type:
boolean - Default:
true
Skips runtime validation of the generated OpenAPI schema against the OpenAPI spec.
ScalarModule({
showDetailedDocsSchema: true,
skipDocsValidation: false, // Validate schema
}) Use case: Enable in development to catch schema errors, disable in production for performance.
openApiOpts
- Type:
Omit<OpenAPIV3.Document, "paths"> & { paths?: OpenAPIV3.PathsObject } - Default:
{ openapi: "3.0.0", info: { title: "API Documentation", version: "1.0.0" } }
OpenAPI document metadata. The paths are automatically generated by the plugin.
ScalarModule({
openApiOpts: {
openapi: '3.0.0',
info: {
title: 'My API',
version: '2.0.0',
description: 'Detailed API description',
termsOfService: 'https://example.com/terms',
contact: {
name: 'API Support',
email: 'support@example.com',
url: 'https://example.com/support'
},
license: {
name: 'MIT',
url: 'https://opensource.org/licenses/MIT'
}
},
servers: [
{
url: 'https://api.example.com',
description: 'Production server'
},
{
url: 'https://staging-api.example.com',
description: 'Staging server'
},
{
url: 'http://localhost:5173',
description: 'Development server'
}
],
tags: [
{
name: 'users',
description: 'User management endpoints'
},
{
name: 'products',
description: 'Product catalog endpoints'
}
],
externalDocs: {
description: 'Find more info here',
url: 'https://docs.example.com'
}
},
}) mergePaths
- Type:
OpenAPIV3.PathsObject - Default:
undefined
Merge additional paths into the generated schema or override existing ones.
ScalarModule({
mergePaths: {
'/custom/endpoint': {
get: {
summary: 'Custom endpoint',
description: 'Not auto-generated',
responses: {
'200': {
description: 'Success',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
message: { type: 'string' }
}
}
}
}
}
}
}
}
},
}) Use cases:
- Add endpoints not managed by the plugin
- Override auto-generated schemas
- Document external APIs your app proxies
disableScalar
- Type:
boolean - Default:
false
Disables the Scalar documentation UI endpoint.
ScalarModule({
disableScalar: true, // No /api-docs/scalar
}) Use case: When you only want the OpenAPI JSON for other tools (Postman, Insomnia, etc.)
scalarDocPath
- Type:
string - Default:
"scalar"
The slug value that serves the Scalar UI.
ScalarModule({
scalarDocPath: 'docs', // Serve at /api-docs/docs
}) scalarOpts
- Type:
HtmlRenderingConfiguration - Default:
undefined
Options for customizing the Scalar UI. See Scalar documentation for all options.
ScalarModule({
scalarOpts: {
theme: 'purple',
darkMode: true,
layout: 'modern',
hideDownloadButton: false,
hideModels: false,
hideTestRequestButton: false,
},
}) Complete Examples
Minimal Setup
Just the basics:
// src/routes/api-docs/[slug]/+server.ts
import ScalarModule from 'sveltekit-auto-openapi/scalar-module';
export const { GET, _config } = ScalarModule({
openApiOpts: {
info: {
title: 'My API',
version: '1.0.0'
}
}
}); Production Configuration
With full metadata:
// src/routes/api-docs/[slug]/+server.ts
import ScalarModule from 'sveltekit-auto-openapi/scalar-module';
const isProd = import.meta.env.PROD;
export const { GET, _config } = ScalarModule({
openApiOpts: {
openapi: '3.0.0',
info: {
title: 'E-Commerce API',
version: '2.1.0',
description: `
# E-Commerce Platform API
This API provides access to our e-commerce platform's core functionality.
## Authentication
All endpoints require an API key passed in the \`x-api-key\` header.
## Rate Limiting
Requests are limited to 100 per minute per API key.
`,
termsOfService: 'https://example.com/terms',
contact: {
name: 'API Team',
email: 'api@example.com'
},
license: {
name: 'Proprietary',
}
},
servers: isProd ? [
{
url: 'https://api.example.com',
description: 'Production'
}
] : [
{
url: 'http://localhost:5173',
description: 'Development'
},
{
url: 'https://staging-api.example.com',
description: 'Staging'
}
],
tags: [
{ name: 'auth', description: 'Authentication endpoints' },
{ name: 'users', description: 'User management' },
{ name: 'products', description: 'Product catalog' },
{ name: 'orders', description: 'Order processing' },
{ name: 'payments', description: 'Payment processing' }
]
},
scalarOpts: {
theme: 'default',
darkMode: true,
layout: 'modern',
}
}); Custom Paths with Merge
Adding manual endpoints:
// src/routes/api-docs/[slug]/+server.ts
import ScalarModule from 'sveltekit-auto-openapi/scalar-module';
export const { GET, _config } = ScalarModule({
openApiOpts: {
info: {
title: 'My API',
version: '1.0.0'
}
},
mergePaths: {
'/health': {
get: {
summary: 'Health check',
description: 'Returns server health status',
tags: ['system'],
responses: {
'200': {
description: 'Server is healthy',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
status: { type: 'string', enum: ['ok'] },
uptime: { type: 'number' },
timestamp: { type: 'string', format: 'date-time' }
}
}
}
}
}
}
}
},
'/metrics': {
get: {
summary: 'Prometheus metrics',
description: 'Returns application metrics in Prometheus format',
tags: ['system'],
responses: {
'200': {
description: 'Metrics data',
content: {
'text/plain': {
schema: { type: 'string' }
}
}
}
}
}
}
}
}); Environment-Specific Configuration
Different settings per environment:
// src/routes/api-docs/[slug]/+server.ts
import ScalarModule from 'sveltekit-auto-openapi/scalar-module';
const isDev = import.meta.env.DEV;
export const { GET, _config } = ScalarModule({
showDetailedDocsSchema: isDev, // Detailed schemas in dev
skipDocsValidation: !isDev, // Validate in dev only
openApiOpts: {
info: {
title: 'My API',
version: '1.0.0'
},
servers: isDev ? [
{ url: 'http://localhost:5173', description: 'Local' }
] : [
{ url: 'https://api.example.com', description: 'Production' }
]
},
scalarOpts: {
darkMode: isDev, // Dark mode in development
hideDownloadButton: !isDev, // Hide download in production
}
}); Customization
Custom Theme
Scalar supports theming:
scalarOpts: {
theme: 'purple', // 'default', 'alternate', 'moon', 'purple', 'solarized', 'bluePlanet'
darkMode: true,
} Custom Layout
Choose between layouts:
scalarOpts: {
layout: 'modern', // 'modern' or 'classic'
} Hide UI Elements
Control what's visible:
scalarOpts: {
hideDownloadButton: true, // Hide OpenAPI download
hideTestRequestButton: false, // Show "Try it" buttons
hideModels: false, // Show schema models
hideDarkModeToggle: false, // Show dark mode toggle
} Custom CSS
Inject custom styles:
scalarOpts: {
customCss: `
.scalar-api-reference {
--scalar-font: 'Inter', sans-serif;
--scalar-border-radius: 8px;
}
`
} Advanced Usage
Multiple Documentation Routes
Serve different docs for different APIs:
// src/routes/api/v1/docs/[slug]/+server.ts
export const { GET, _config } = ScalarModule({
openApiOpts: {
info: { title: 'API v1', version: '1.0.0' }
}
});
// src/routes/api/v2/docs/[slug]/+server.ts
export const { GET, _config } = ScalarModule({
openApiOpts: {
info: { title: 'API v2', version: '2.0.0' }
}
}); Protected Documentation
Add authentication:
// src/routes/api-docs/[slug]/+server.ts
import ScalarModule from 'sveltekit-auto-openapi/scalar-module';
import { error } from '@sveltejs/kit';
const { GET: scalarGET, _config } = ScalarModule({
openApiOpts: {
info: { title: 'Internal API', version: '1.0.0' }
}
});
export { _config };
export const GET = async (event) => {
// Check authentication
const apiKey = event.request.headers.get('x-api-key');
if (!apiKey || apiKey !== process.env.DOCS_API_KEY) {
error(401, 'Unauthorized');
}
// Serve docs
return scalarGET(event);
}; Custom Response Headers
Add CORS or other headers:
const { GET: scalarGET, _config } = ScalarModule({
// ... config
});
export { _config };
export const GET = async (event) => {
const response = await scalarGET(event);
// Add custom headers
response.headers.set('Access-Control-Allow-Origin', '*');
response.headers.set('Cache-Control', 'public, max-age=3600');
return response;
}; Troubleshooting
Schema not updating
Problem: Changes to routes don't appear in documentation
Solution:
- Restart dev server (virtual module is cached)
- Check HMR is working
- Verify routes are in
src/routes/directory
Scalar UI not rendering
Problem: Blank page at /api-docs/scalar
Solution:
- Check browser console for errors
- Verify OpenAPI JSON is valid at
/api-docs/openapi.json - Try
skipDocsValidation: falseto catch schema errors
404 on documentation routes
Problem: Documentation routes return 404
Solution:
- Check route file is
src/routes/api-docs/[slug]/+server.ts - Verify the
slugparameter is dynamic[slug], not static - Ensure you're using the correct paths (
openapi.jsonandscalarby default)
Scalar showing wrong schema
Problem: Documentation shows outdated schema
Solution:
- Clear browser cache
- Hard refresh (Ctrl+Shift+R)
- Check
openapi.jsondirectly to verify it's updated
Related Documentation
- Plugin Configuration - Configure schema generation
- Route Configuration - Define route schemas
- Virtual Modules - Access schemas programmatically
- Scalar Documentation - Official Scalar docs for advanced customization