Embed
Dory can open a hosted documentation site in a slide-out iframe. The host application chooses the starting documentation route and can navigate the iframe when its own context changes. Dory keeps its search and page navigation inside the iframe.
Allow the host origin#
For a host on another origin, add its exact origin to the documentation site's dory.json and rebuild:
JSON
{
"embed": {
"security": {
"allowedOrigins": ["https://app.example.com"]
}
}
}
Use an origin without a path or trailing slash. Dory's preview server allows framing from these origins. If you serve the static build with another web server, configure its Content-Security-Policy frame-ancestors directive for the same origins and do not send X-Frame-Options: SAMEORIGIN on embeddable pages. Keep the list limited to applications you control.
Add the widget#
Load the embed.js file from the hosted docs, then initialize DoryDocs. The script derives the docs URL from its own address, including a /docs base path when present.
HTML
<button id="docs-help" type="button">Help</button>
<script src="https://docs.example.com/embed.js"></script>
<script>
window.DoryDocs.init({
trigger: '#docs-help',
position: 'right',
width: 560,
theme: 'inherit',
initialPath: '/getting-started',
onNavigate(path) {
console.log('Reader opened', path);
},
});
</script>
The widget loads when the reader opens it. theme: 'inherit' uses the host's light or dark theme on first open. Call setTheme when the host theme changes.
Open the page that matches the app#
Map application routes or selected objects to documentation routes in the host. For example:
JavaScript
window.DoryDocs.open('/apps/overview');
window.DoryDocs.navigate('/apps/building-a-transform');
window.DoryDocs.setTheme('dark');
open(path) opens the widget at a route. navigate(path) changes its current page. close(), toggle(), isOpen(), and destroy() manage the widget. A route change inside the iframe calls onNavigate(path) in the host. Messaging checks both the iframe window and the docs origin; the docs only send messages to an origin listed in embed.security.allowedOrigins or their own origin.
| Option | Default | Purpose |
|---|---|---|
position | right | left, right, or bottom |
width | 500 | Width in pixels or a CSS width for side panels |
height | 100vh | Height of a bottom panel |
theme | inherit | inherit, light, or dark |
initialPath | / | Route shown on first open |
trigger | — | CSS selector or element to open the widget |
showOverlay | true | Dim the host behind the widget |
closeOnEscape | true | Close when Escape is pressed |
closeOnOverlayClick | true | Close when the overlay is clicked |
The embed displays published documentation. It does not store or edit MDX, and it does not pass host credentials into the iframe. Keep private documentation behind your own authenticated hosting layer. To create docs from an application, generate MDX and dory.json, run dory build, and publish the resulting site.
Sandboxed runtime styles#
Hosts that render app-owned MDX through dory-runtime.js must include CSS contents in the runtime's load message. The runtime never reads stylesheet paths or fetches imports. It accepts only the files listed in config.styles, in that order.
A trusted Node build or service can prepare the payload from a documentation directory:
JavaScript
import { prepareEmbeddedStylesheets } from '@clidey/dory/bin/dist/embedded-styles.js';
const stylesheets = prepareEmbeddedStylesheets(['./custom.css'], docsDirectory);
This helper validates the full local dependency graph, inlines imports, converts approved raster and font assets to data URLs, and validates the resulting CSS. It preserves import media queries, layers, and supports conditions. Circular imports and excessive expansion are rejected. Pass the resulting array through the existing host bridge:
JavaScript
iframe.contentWindow.postMessage({
...documentationPayload,
__dory_docs: true,
type: 'load',
config: { ...siteConfig, styles: ['./custom.css'] },
stylesheets,
}, '*');
Keep the runtime in an iframe with sandbox="allow-scripts", without allow-same-origin. The host must verify incoming messages originate from that iframe. The runtime verifies messages originate from its parent. Each update replaces the previous custom styles, and omitting styles removes them.
The runtime injects validated CSS through style.textContent. It rejects network URLs, CSS imports, escaped syntax, unknown resource functions, and SVG or HTML data URLs. Payloads are limited to 16 stylesheets, 256 KB per file, and 1 MB total. Supported self-contained CSS includes theme rules, media queries, gradients, and approved base64 raster/font URLs. If styles are invalid or missing, rendering fails closed instead of fetching an alternative resource. No broader network or iframe permissions are required.
Was this page helpful?