Skip to content
sdocs

Embedded in Vite & SvelteKit

Mount sdocs inside your existing Vite or SvelteKit app as a route, rather than running a separate server.

1. Add the Vite plugin

// vite.config.js
import { sveltekit } from '@sveltejs/kit/vite';
import { sdocsPlugin } from 'sdocs/vite';

export default {
  plugins: [
    sveltekit(),
    sdocsPlugin({
      include: ['./src/lib/**/*.sdoc'],
      css: './src/styles/global.css',
    }),
  ],
};

The plugin reads the same sdocs.config.js if present; options passed here override it. In embedded mode only include and css matter — UI options like title and sections are props on the Explorer component (below), and port/open apply only to the standalone CLI.

The plugin:

  • Discovers .sdoc files and parses them
  • Exposes them as the virtual:sdocs module
  • Watches for file changes and triggers a full reload
  • Adds a middleware endpoint for syntax highlighting

2. Create a page that mounts the Explorer

<!-- src/routes/docs/+page.svelte -->
<script>
  import Explorer from 'sdocs/explorer';
  import { docs, cssNames, axes, scale, pageModules } from 'virtual:sdocs';
</script>

<Explorer
  {docs}
  {cssNames}
  {axes}
  {scale}
  {pageModules}
  title="My Design System"
  sections={[{ slug: 'components', title: 'Components', order: ['Button'] }]}
/>

Important

pageModules is not optional. A [DOC] or [PAGE] body compiles to its own component and is loaded through that map, so an Explorer mounted without it renders every one of those pages blank, with no error.

Your docs are now available at whatever route you mounted the page on (e.g. /docs).

3. Virtual module type declaration (TypeScript)

// src/app.d.ts
declare module 'virtual:sdocs' {
  import type { AxisConfig, DocEntry, ScaleConfig } from 'sdocs';
  export const docs: DocEntry[];
  export const cssNames: string[];
  export const axes: Required<AxisConfig>[];
  export const scale: Required<ScaleConfig> | null;
  export const pageModules: Record<string, () => Promise<{ default: unknown }>>;
  export default docs;
}

Explorer props

The Explorer component from sdocs/explorer accepts:

PropTypeDescription
docsDocEntry[]All discovered doc entries. Comes from virtual:sdocs.
cssNamesstring[]Stylesheet names if using named CSS. Comes from virtual:sdocs.
pageModulesRecord<string, () => Promise<…>>Required for [DOC]/[PAGE] pages. Their bodies compile to components loaded through this map; without it they render blank. Comes from virtual:sdocs.
scaleScaleConfig | nullThe scale slider. Comes from virtual:sdocs.
axesAxisConfig[]Customization axes — the top bar's dropdowns. Comes from virtual:sdocs.
titlestringHeader title text. Default: 'sdocs'.
logostring | falseHeader logo: 'sdocs' for the built-in mascot (default), an image URL, or false to hide.
previewBasestringURL prefix for preview pages when the app deploys under a sub-path. In SvelteKit, pass base from $app/paths. Default: ''.
devbooleanTurns on the in-page note editor (dev only — Save posts to a route the dev server alone mounts). Pass import.meta.env.DEV.
sectionsSectionEntry[]Declared sections in top-bar order ({ slug, title?, order? }, or { type: 'divider' } for a rule between tabs), same shape as the config key. See sidebar.
homestringRoute path of the landing page, like the config home.
routing'history' | 'hash'URL style. Embedded default: 'hash' — it works under any host routing. Only switch to 'history' if the host serves a fallback for doc routes.
basePathstringPath prefix for history-mode routes (the host sub-path the Explorer is mounted on). Default: ''.

See types for DocEntry.

Production builds

When the host app is built for production, the plugin emits each preview as a static page under previews/ in the build output, and virtual:sdocs points the preview iframes there — embedded docs work in the deployed app, not just in dev. Your css stylesheets are bundled into the preview pages as well.

Note that prerendering is a standalone sdocs build feature: an embedded Explorer renders client-side, and static HTML for crawlers is the host framework's job (SvelteKit prerendering, for example).

When the app deploys under a sub-path (GitHub Pages, for example), pass the path to the Explorer component so preview URLs resolve — in SvelteKit:

<script>
  import { base } from '$app/paths';
</script>

<Explorer {docs} {cssNames} previewBase={base} />

Plain Vite apps that set base in their Vite config need nothing extra — the plugin picks it up automatically.

virtual:sdocs

The plugin exposes a virtual module containing all discovered docs. Import from it anywhere in your app:

import { docs, cssNames, axes, scale } from 'virtual:sdocs';
  • docs: DocEntry[] — flat array of all discovered doc entries
  • cssNames: string[] — names of available stylesheets (empty if using single or no CSS)
  • scale: ScaleConfig | null — the configured scale slider, or null
  • axes: AxisConfig[] — the configured customization axes, normalized (empty if none)

See also