v12.2
New in RapiDoc v11 • Isomorphic Engine

Static Pre-Rendering & SSG

Generate complete, beautifully styled API documentation on the server using Declarative Shadow DOM (DSD) or semantic Light DOM. Achieve zero FOUC, instant First Contentful Paint, and complete search engine indexability across Astro, Next.js, Nuxt, or pure Node.js scripts.

0 msZero-FOUC First Paint
DSD NativeDeclarative Shadow DOM
100% SEOServer Crawlable HTML
Zudoku StyleIsolated Endpoint Cards
Performance & Core Web Vitals

Why Pre-Render on the Server?

Traditional client-only OpenAPI viewers (Swagger UI, standard Web Components, Redoc) force the visitor's browser to execute heavy CPU tasks before anything is visible. RapiDoc static pre-rendering moves this computation to your build server.

Traditional Client-Only Rendering
  • ✕Slow LCP: Browser must fetch 600KB+ JS, download remote YAML/JSON, and dereference complex schemas.
  • ✕FOUC & Blank Screens: Users stare at a blank canvas or spinning loader for 1.5–3 seconds.
  • ✕Poor SEO: Search crawlers that do not execute client JavaScript index an empty shell.
  • ✕No MDX Embedding: Difficult to cleanly embed individual endpoints inside documentation guides.
RapiDoc Static Pre-Rendering (DSD)
  • ✓Instant First Paint: Complete HTML and CSS stream directly from your CDN/edge server.
  • ✓Zero FOUC: Native browser Declarative Shadow DOM renders styles and layout before any JS executes.
  • ✓Full SEO Indexing: Googlebot and AI crawlers index all endpoint paths, parameters, schemas, and descriptions.
  • ✓Seamless Hydration: Client script attaches smoothly to the existing DOM for Try-It and live filtering.
Live Demonstration

Pre-Rendered Endpoint Preview

The endpoint card below was generated at build-time on the server by renderEndpoint() with zero client-side JavaScript execution.

Server Pre-Rendered HTML • GET /shipments/{shipmentId}Zero JS First Paint

Retrieve Shipment Details

get /shipments/{shipmentId}

Returns real-time cargo milestone telemetry, carrier transit status, and customs clearance documents.

Quick Start • Method 1

Pre-Rendering via Node.js or Bun

Generate static .html files in your build pipeline with a single function call. Install the renderer with npm install @rapidoc/prerender; it works in Node.js >= 22 or Bun.

prerender.mjs
// prerender.mjs - Standalone Node.js / Bun script
import fs from 'node:fs';
import { renderRapiDoc } from '@rapidoc/prerender';

// 1. Pre-render the OpenAPI specification into Declarative Shadow DOM
const staticHtml = await renderRapiDoc({
  spec: './specs/petstore.yaml', // file path, remote URL, or JSON/YAML string
  renderStyle: 'read',           // 'read' | 'view' | 'focused'
  theme: 'ember',                // 'ember' | 'carbon' | 'cobalt' | 'jade' | 'indigo' | hex
  colorScheme: 'dark',           // 'dark' | 'light' | 'system'
  outputMode: 'dsd',             // Declarative Shadow DOM (default)
});

// 2. Wrap inside standard HTML boilerplate with optional client bundle
const htmlPage = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>API Reference</title>
  
  <!-- Client bundle enables interactive Try-It console, live search, and tab switching -->
  <script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
</head>
<body style="margin: 0; padding: 0; background: #0f172a;">
  ${staticHtml}
</body>
</html>`;

// 3. Save to disk
fs.writeFileSync('./dist/api.html', htmlPage, 'utf-8');
console.log('API Reference pre-rendered successfully to dist/api.html');
Framework Integration • Method 2

Pre-Rendering in Astro

Astro's zero-JS-by-default architecture is the perfect companion for RapiDoc's isomorphic renderer. Use renderRapiDoc inside your frontmatter.

src/pages/api.astro
---
// src/pages/api.astro - Astro SSG Page
import { renderRapiDoc } from '@rapidoc/prerender';

// Executed at BUILD TIME on the server
const preRenderedDoc = await renderRapiDoc({
  spec: './public/specs/petstore.json',
  renderStyle: 'read',
  theme: 'ember',
  colorScheme: 'dark',
});
---

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Petstore API Reference</title>

    <!-- Client bundle hydrates the pre-rendered shadow DOM with zero FOUC -->
    <script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
  </head>
  <body style="margin: 0; padding: 0;">
    <!-- Injects server-rendered Declarative Shadow DOM -->
    <Fragment set:html={preRenderedDoc} />
  </body>
</html>
Framework Integration • Method 3

Pre-Rendering in Next.js & Nuxt

Render API documentation inside React Server Components or Nuxt SSR routes with Incremental Static Regeneration (ISR).

app/api-reference/page.tsx
// app/api-reference/page.tsx - Next.js App Router (React Server Component)
import { renderRapiDoc } from '@rapidoc/prerender';
import Script from 'next/script';

export const revalidate = 3600; // ISR: Re-cache once per hour

export default async function ApiReferencePage() {
  const staticDocHtml = await renderRapiDoc({
    spec: 'https://api.example.com/openapi.json',
    renderStyle: 'read',
    theme: 'ember',
    colorScheme: 'dark',
  });

  return (
    <main style={{ minHeight: '100vh', margin: 0, padding: 0 }}>
      {/* Client-side hydration for Try-It console & filter */}
      <Script
        type="module"
        src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"
        strategy="lazyOnload"
      />
      <div dangerouslySetInnerHTML={{ __html: staticDocHtml }} />
    </main>
  );
}
Portal Architecture • Method 4

Isolated Endpoints & Schemas for MDX Guides

Building a custom developer portal like Zudoku or Cosmo Cargo? Use renderEndpoint() and renderSchema() to embed isolated operations directly into Markdown and MDX articles.

portal-renderer.js
// MDX / Developer Portal Endpoint Embedding (Zudoku / Cosmo Cargo Style)
import { renderEndpoint, renderSchema } from '@rapidoc/prerender';

// Pre-render a single endpoint card inside a guide article
export const shipmentEndpointHtml = await renderEndpoint({
  spec: './specs/logistics.yaml',
  path: '/v1/shipments/{shipmentId}',
  method: 'get',
  theme: 'ember',
  colorScheme: 'dark',
  allowTry: false, // Static documentation view
});

// Pre-render a standalone JSON Schema model
export const schemaHtml = await renderSchema({
  spec: './specs/logistics.yaml',
  schema: 'ShipmentResponse',
  style: 'table', // 'table' or 'tree'
  theme: 'ember',
});
Under the Hood

How Declarative Shadow DOM (DSD) Operates

Declarative Shadow DOM allows standard HTML to declare encapsulated shadow roots without calling element.attachShadow() via JavaScript.

declarative-shadow-dom.html
<!-- Declarative Shadow DOM output from renderRapiDoc({ outputMode: 'dsd' }) -->
<rapi-doc theme="ember" color-scheme="dark" render-style="read" layout="column">
  <!-- Native browser Declarative Shadow DOM -->
  <template shadowrootmode="open">
    <style>
      /* Complete scoped design tokens, layout, typography, and method badges */
      :host { all: initial; display: flex; ... }
    </style>
    
    <!-- Complete pre-rendered HTML DOM: navbar, tag groups, endpoints, schemas -->
    <div id="the-main-body" class="body">
      <nav class="nav-bar"> ... </nav>
      <main class="main-content">
        <section class="m-endpoint regular-font get expanded"> ... </section>
      </main>
    </div>
  </template>
</rapi-doc>
💡
Need Light DOM instead of Shadow DOM?

If your project uses a CSS framework (like Tailwind or Bootstrap) that needs to style RapiDoc's internal elements directly, specify outputMode: 'html' or 'light'. RapiDoc will emit a standard semantic <div class="rapidoc-prerender-container"> instead of a custom element.

API Reference

renderRapiDoc() Configuration Options

Complete options dictionary accepted by renderRapiDoc().

OptionTypeDefaultDescription
specstring | object(required)Path to local file (.json/.yaml), remote HTTPS URL, raw YAML/JSON string, or pre-parsed spec object.
renderStyle'read' | 'view' | 'focused''read'Layout style: continuous document ("read"), collapsible accordions ("view"), or single-endpoint sidebar ("focused").
themestring'ember'Brand color preset ("ember", "carbon", "cobalt", "jade", "indigo") or custom hex code.
colorScheme'dark' | 'light' | 'system''dark'Active color scheme applied to background, cards, text, and method badges.
outputMode'dsd' | 'html' | 'light''dsd'Container format: Declarative Shadow DOM with native browser hydration ("dsd") or scoped Light DOM div ("html").
includeStylesbooleantrueWhether to inline the complete bundled CSS styles directly within the pre-rendered container.
schemaStyle'table' | 'tree''table'Default display style for JSON Schemas and parameter objects.
schemaExpandLevelnumber99999Initial expansion depth for nested schemas.
allowTrybooleantrueWhether to include the interactive request execution console markup.
allowSearchbooleantrueWhether the sidebar search and filter input is included.
Ready to Explore?

Build Your Next-Gen API Portal Today

Explore 3-tier navigation with x-tagGroups, customize themes with design tokens, or embed interactive consoles into blogs.