Prosefly

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:

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.

OptionPurposeDefault
filePath to the OpenAPI YAML or JSON filerequired
baseBase URL for generated API pages/api
operationBaseURL segment before operation pagesendpoints
groupByStrategy for grouping operationsauto
schemaBudgetLimits for dereferenced schema databuilt-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:

astro.config.ts
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:

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:

typescript
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:

typescript
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:

typescript
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:

typescript
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