Configuration
Connect an OpenAPI file to Astro's content layer and docs routes.
Add the integration
Configure the source file and the URL space for generated API pages in
astro.config.ts:
import { defineConfig } from 'astro/config';import openapi from '@prosefly-pro/astro-openapi';
export default defineConfig({ integrations: [ openapi({ file: './src/openapi/openapi.yaml', base: '/api', operationBase: 'endpoints', groupBy: 'auto', }), ],});The integration watches the OpenAPI file during development and shares its configuration with the loader and generated navigation.
| Option | Purpose | Default |
|---|---|---|
file | Path to the OpenAPI YAML or JSON file | required |
base | Base URL for generated API pages | /api |
operationBase | URL segment before operation pages | endpoints |
groupBy | Strategy for grouping operations | auto |
schemaBudget | Limits for dereferenced schema data | built-in limits |
Most projects need only one OpenAPI file, which is the default configuration
shown above. For multiple documents, configure named sources. Each source can
have its own URL base. Resolved source bases must be unique; because the
default is /api, multiple sources should set distinct base values:
openapi({ sources: { cafe: { file: './src/openapi/cafe.yaml', base: '/api/cafe', }, fruits: { file: './src/openapi/fruits.yaml', base: '/api/fruits', }, },});Create the content collection
Add an OpenAPI collection to src/content.config.ts:
import { defineCollection } from 'astro:content';import { openApiLoader, openApiSchema } from '@prosefly-pro/astro-openapi';
const api = defineCollection({ loader: openApiLoader(), schema: openApiSchema(),});
export const collections = { api };Select a named source when defining each additional collection:
const cafe = defineCollection({ loader: openApiLoader({ source: 'cafe' }), schema: openApiSchema(),});
const fruits = defineCollection({ loader: openApiLoader({ source: 'fruits' }), schema: openApiSchema(),});
export const collections = { cafe, fruits };The loader creates an introduction entry plus operation and webhook entries
from the source document.
Add generated navigation
When using Lotus, load the API navigation into a sidebar section:
import { loadOpenApiDocsNav } from '@prosefly-pro/astro-openapi';
export default { docsNav: [ { label: 'API Reference', items: loadOpenApiDocsNav({ methodBadge: { variant: 'soft' }, }), }, ],};In multi-source mode, pass the same selector to navigation:
loadOpenApiDocsNav({ source: 'cafe', methodBadge: { variant: 'soft' },});With multiple named sources, omitting source reports an error listing the
available names. A configuration with exactly one source selects it
automatically. Direct file options remain available for local overrides, but
file and source cannot be provided together. Every source’s resolved base
must be unique, including the default /api base.
Framework and theme integrations
Framework and theme integrations can consume Astro OpenAPI without requiring a
content collection. Use resolveOpenApiSources() to normalize either the
single-file or named-source configuration, then load each complete reference:
import { loadOpenApiReference, resolveOpenApiSources,} from '@prosefly-pro/astro-openapi';
const configs = resolveOpenApiSources(openApiOptions);const references = await Promise.all( configs.map((config) => loadOpenApiReference({ config }, astroConfig.root), ),);The returned model contains the resolved config, an introduction entry with
its Markdown body, entry-like operations and webhooks, and generated
navigation. Options such as introduction and methodBadge can be supplied
alongside config.
Passing Astro’s config.root makes relative OpenAPI file paths independent of
the current working directory. Astro OpenAPI does not own or inject page routes;
the consuming framework or site remains responsible for routing, layouts,
sidebar composition, search, and rendering.
Route ownership
Astro OpenAPI supplies content entries and navigation data. Your site still owns the route and layout that render those entries.
Last updated Sep 10, 2026