Skip to content
v12.2
GitHub

Framework Integration

<rapi-doc> is a standard custom element, so it works in any framework without a wrapper. Two rules apply everywhere:

  • Register it in the browser. import 'rapidoc' defines the element and needs window, so with server-side rendering import it on the client only.
  • Pass attributes as strings, as in HTML: render-style="view", allow-try="false".

Import RapiDoc in an effect, so it runs only in the browser. In the Next.js App Router, mark the file 'use client'.

ApiDocs.tsx
'use client';
import { useEffect } from 'react';
export default function ApiDocs() {
useEffect(() => {
import('rapidoc');
}, []);
return (
<rapi-doc
spec-url="https://petstore.swagger.io/v2/swagger.json"
render-style="view"
show-header="false"
style={{ height: '100vh' }}
/>
);
}

The element renders once it is defined; until then the browser shows it as an empty box.

TypeScript doesn’t know <rapi-doc> and reports Property 'rapi-doc' does not exist on type 'JSX.IntrinsicElements'. rapidoc ships the types; reference them once, for example in src/rapidoc.d.ts:

src/rapidoc.d.ts
/// <reference types="rapidoc/react" />

Every attribute is then checked and completed in JSX: render-style="nope" is an error. For a typed ref, import the element’s type:

import type { RapiDocElement } from 'rapidoc';
const ref = useRef<RapiDocElement>(null);
// ref.current?.loadSpec('/openapi.json');

The types need rapidoc 12.2 or later. <rapi-doc-mini> and <rapi-flow> are typed from 12.2.1.

Tell the Vue compiler that tags starting with rapi- are custom elements, not missing Vue components:

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('rapi-'),
},
},
}),
],
});

For attribute checking in templates (with Volar), add the types once, for example in src/rapidoc.d.ts:

src/rapidoc.d.ts
/// <reference types="rapidoc/vue" />

Then import RapiDoc when the component mounts:

ApiDocs.vue
<script setup>
import { onMounted } from 'vue';
onMounted(() => import('rapidoc'));
</script>
<template>
<rapi-doc
spec-url="https://petstore.swagger.io/v2/swagger.json"
render-style="focused"
style="height: 100vh"
></rapi-doc>
</template>

Add CUSTOM_ELEMENTS_SCHEMA to the component (or its module) and import RapiDoc:

api-docs.component.ts
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import 'rapidoc';
@Component({
selector: 'app-api-docs',
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<rapi-doc
spec-url="https://petstore.swagger.io/v2/swagger.json"
render-style="view"
style="height: 100vh"
></rapi-doc>
`,
})
export class ApiDocsComponent {}

With Angular SSR, move the import into afterNextRender so it runs in the browser only.

No configuration is needed. Import rapidoc in a client-side script and use the element in your markup. In Astro, a <script>import 'rapidoc';</script> tag in the page is enough.

A server can serve the API reference itself, next to the API. These packages add the page, the bundle and the OAuth return page to your app, so there is no HTML to write.

npm install @rapidoc/hono
import { Hono } from 'hono';
import { rapidoc } from '@rapidoc/hono';
const app = new Hono();
app.get('/openapi.json', (c) => c.json(openApiDocument));
app.use(rapidoc({ specUrl: '/openapi.json', options: { renderStyle: 'focused' } }));

The reference is at /docs; change it with uiPath. options takes any attribute of <rapi-doc>. On Cloudflare Workers, import from @rapidoc/hono/edge, which loads the bundle from a CDN instead of reading it from disk.

import express from 'express';
import { rapidoc } from '@rapidoc/express';
const app = express();
app.get('/openapi.json', (req, res) => res.json(openApiDocument));
app.use(rapidoc({ specUrl: '/openapi.json' }));

Both serve the reference at /docs and take the same options as the Hono package. Mounted under a prefix (app.use('/api', …), or Fastify’s prefix), the page’s links include it.

pip install rapidoc
from fastapi import FastAPI
from rapidoc.fastapi import setup_rapidoc
app = FastAPI(docs_url=None, redoc_url=None)
setup_rapidoc(app, options={"render_style": "focused"})

The reference is at /docs and reads the app’s own /openapi.json. docs_url=None turns off FastAPI’s Swagger UI, which uses the same path; to keep both, pass ui_path="/reference". For a plain Starlette app, import it from rapidoc.starlette and pass spec_url.

dotnet add package RapiDoc.AspNetCore
using RapiDoc.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapOpenApi();
app.MapRapiDoc(options => options.Attributes["render-style"] = "focused");
app.Run();

The reference is at /docs and reads the document MapOpenApi() serves at /openapi/v1.json. With Swashbuckle or NSwag, set options.SpecUrl to their document. MapRapiDoc returns an endpoint builder, so .RequireAuthorization() protects the reference, and MapRapiDoc("/reference") moves it. Needs .NET 8 or later.

go get github.com/rapi-doc/rapidoc-go
import rapidoc "github.com/rapi-doc/rapidoc-go"
mux := http.NewServeMux()
docs := rapidoc.Handler(rapidoc.Options{
SpecURL: "/openapi.json",
Attributes: map[string]any{"render-style": "focused"},
})
mux.Handle("/docs", docs)
mux.Handle("/docs/", docs)

The reference is at /docs. It is a plain net/http handler with no dependencies, so it also mounts on chi, Gin, Echo and Fiber, and next to Huma, whose /openapi.json it can read; the README has each of them. It does not generate the OpenAPI document: point SpecURL at the one your app serves, or pass the JSON as Spec. Needs Go 1.22 or later.

@rapidoc/starlight adds an API reference page per OpenAPI document to a Starlight site. The page uses Starlight’s layout and themes, and the API’s operations appear in Starlight’s sidebar.

npm install @rapidoc/starlight
astro.config.mjs
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import starlightRapidoc from '@rapidoc/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My docs',
plugins: [starlightRapidoc({ uiPath: '/api', spec: './openapi.yaml' })],
}),
],
});

spec is a file, a URL or an object, read when the site is built. For several APIs pass { apis: [...] }.

VitePress has no plugin system, so there are two steps: wrap the config, and put the component on a page.

.vitepress/config.mjs
import { defineConfig } from 'vitepress';
import { withRapidoc, rapidocSidebar } from '@rapidoc/vitepress';
export default withRapidoc(
defineConfig({
themeConfig: {
sidebar: [{ text: 'Pets API', items: await rapidocSidebar({ spec: './openapi.yaml', uiPath: '/api' }) }],
},
}),
{ apis: { pets: './openapi.yaml' } },
);
api.md
---
layout: page
---
<script setup>
import { RapidocReference } from '@rapidoc/vitepress/client';
</script>
<RapidocReference api="pets" />

Three steps: the plugin, a doc page, and the sidebar.

docusaurus.config.js
export default {
plugins: [['@rapidoc/docusaurus', { apis: { pets: './openapi.yaml' } }]],
};
docs/api.mdx
---
hide_table_of_contents: true
---
import RapidocReference from '@rapidoc/docusaurus/client';
<RapidocReference api="pets" />
sidebars.js
import { rapidocSidebarSync } from '@rapidoc/docusaurus';
export default {
docs: [
{
type: 'category',
label: 'Pets API',
items: rapidocSidebarSync({ spec: './openapi.yaml', uiPath: '/docs/api', docId: 'api' }),
},
],
};

For another framework or site generator, see Build an Integration.