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 needswindow, so with server-side rendering import it on the client only. - Pass attributes as strings, as in HTML:
render-style="view",allow-try="false".
React and Next.js
Section titled “React and Next.js”Import RapiDoc in an effect, so it runs only in the browser. In the Next.js App Router, mark the file 'use client'.
'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
Section titled “TypeScript”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:
/// <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.
Vue and Nuxt
Section titled “Vue and Nuxt”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-'), }, }, }), ],});export default defineNuxtConfig({ vue: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('rapi-'), }, },});For attribute checking in templates (with Volar), add the types once, for example in src/rapidoc.d.ts:
/// <reference types="rapidoc/vue" />Then import RapiDoc when the component mounts:
<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>Angular
Section titled “Angular”Add CUSTOM_ELEMENTS_SCHEMA to the component (or its module) and import RapiDoc:
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.
Svelte, Astro and plain bundlers
Section titled “Svelte, Astro and plain bundlers”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.
Server frameworks
Section titled “Server frameworks”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/honoimport { 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.
Express and Fastify
Section titled “Express and Fastify”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' }));import Fastify from 'fastify';import { rapidoc } from '@rapidoc/fastify';
const fastify = Fastify();
await fastify.register(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.
FastAPI
Section titled “FastAPI”pip install rapidocfrom fastapi import FastAPIfrom 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.
ASP.NET Core
Section titled “ASP.NET Core”dotnet add package RapiDoc.AspNetCoreusing 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-goimport 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.
Documentation sites
Section titled “Documentation sites”Starlight
Section titled “Starlight”@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/starlightimport { 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
Section titled “VitePress”VitePress has no plugin system, so there are two steps: wrap the config, and put the component on a page.
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' } },);---layout: page---
<script setup>import { RapidocReference } from '@rapidoc/vitepress/client';</script>
<RapidocReference api="pets" />Docusaurus
Section titled “Docusaurus”Three steps: the plugin, a doc page, and the sidebar.
export default { plugins: [['@rapidoc/docusaurus', { apis: { pets: './openapi.yaml' } }]],};---hide_table_of_contents: true---
import RapidocReference from '@rapidoc/docusaurus/client';
<RapidocReference api="pets" />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.