@rizalibnu/sandpack-embedder
v1.6.4
Published
A universal HTML-based Sandpack runtime — dynamically inject interactive code editors and previews into any HTML document.
Maintainers
Readme
Sandpack Embedder
Turn code snippets generated by a CMS editor into live Sandpack playgrounds.

Want to see Sandpack Embedder in action?
What Sandpack Embedder Does
Sandpack Embedder parses these code snippets and converts them into live Sandpack playgrounds, without needing to modify your CMS core.
It:
- Finds elements containing
<sandpack>-like markup. - Extracts and decodes escaped HTML.
- Parses props like
template="react"andoptions="{'editorHeight':400}". - Creates a live Sandpack React playground inside your CMS-rendered page.
Example
Input (Code snippets from CMS)
<sandpack
template="react"
custom-setup='{
"dependencies": {
"react": "19.2.0",
"react-dom": "19.2.0"
}
}'
>
```js /App.js
export default function App() {
return <h1>Hello world</h1>
}
```
```js /hidden-file.js hidden
console.log("I'm hidden");
```
</sandpack>Output (after running SandpackEmbedder)
💡 Turns into a live playground!
<Sandpack
files={{
"/index.js": `
import "./styles.css";
document.getElementById("app").innerHTML = `
<h1>Hello Sandpack</h1>
`;
`,
"/hidden-file.js": {
code: `console.log("I'm hidden");`,
hidden: true
}
}}
template="react"
customSetup={{
dependencies: {
react: "19.2.0",
"react-dom": "19.2.0"
}
}}
/>Usage
You can use SandpackEmbedder on any web page that includes HTML code blocks.
Simple HTML Integration
<pre><code>// code snippets</code></pre>
<script type="module">
import { SandpackEmbedder } from "https://esm.sh/@rizalibnu/sandpack-embedder";
const sandpack = new SandpackEmbedder({
codeSelector: "pre > code",
playgroundClass: "sandpack-playground",
});
sandpack.load();
</script>Using Import Maps
<script type="importmap">
{
"imports": {
"@rizalibnu/sandpack-embedder": "https://esm.sh/@rizalibnu/sandpack-embedder"
}
}
</script>
<script type="module">
import { SandpackEmbedder } from "@rizalibnu/sandpack-embedder";
</script>Options
You can customize selectors, theme, or even replace the Sandpack component.
export interface SandpackEmbedderOptions {
/** CSS selector used to find code elements containing escaped <Sandpack> markup. Default: 'pre > code' */
codeSelector?: string;
/** CSS class name applied to the mount container created for each playground embed. Default: 'sandpack' */
playgroundClass?: string;
/** Custom Sandpack React components (keyed by name, e.g. "Sandpack"). */
customComponents?: Record<string, Component>;
/** Sandpack initial theme. Default theme by Sandpack Component used when not specified by props. */
theme?: string | SandpackProps['theme'];
/** Custom Sandpack Theme (keyed by name, e.g. "amethyst"). */
customThemes?: Record<string, DeepPartial<SandpackTheme>>;
/**
* Selector or callback that determines where to inject the Sandpack playground.
* - If string → resolved via `closest(selector)` from code block
* - If function → return a DOM element relative to the code block
*
* Default: codeSelector's parentElement
*/
injectTarget?: string | ((codeEl: HTMLElement) => HTMLElement | null);
/** Controls where the mount node is injected relative to injectTarget. Default: 'after' */
injectPosition?: 'before' | 'after' | 'replace' | 'inside';
/** Controls visibility of the original code snippet. Default: 'false' */
showOriginalCode?: boolean;
}Updating Embedder
You can change the Sandpack theme dynamically via:
sandpack.updateTheme("light");Later when DOM updates or navigation changes:
sandpack.refresh();Completely clean up:
sandpack.destroy();Preset Components
Sandpack Embedder includes two built-in presets that let you display only the preview or only the code viewer—perfect for documentation.
These presets wrap your code fences and render a specific Sandpack layout:
<preview> → Preview-only (no editor)
<code-viewer> → Code Viewer only (readonly, no preview)
Use them exactly like your <sandpack> tag, but simplified.
<preview template="react">
// markdown code blocks...
<preview>
<code-viewer template="react" options='{"viewerHeight": 500}'>
// markdown code blocks...
<code-viewer>Advanced
Control where playground is injected
You can let users decide where the live playground is inserted relative to the <code> element:
new SandpackEmbedder({
codeSelector: ".language-sandpack",
injectTarget: ".code-wrapper",
injectPosition: "after", // "after" | "before" | "replace" | "inside"
}).load();Use a function for full control
new SandpackEmbedder({
codeSelector: ".language-sandpack",
injectTarget: (el) => el.closest(".code-wrapper")?.querySelector("pre"),
injectPosition: "inside"
});
Custom Theme Mapping
You can override the theme or add your own:
import { amethyst, aquaBlue } from "@codesandbox/sandpack-themes";
const sandpack = new SandpackEmbedder({
customThemes: { amethyst, aquaBlue, neoCyan },
theme: "amethyst"
}).load();
sandpack.updateTheme("aquaBlue");<sandpack theme="neoCyan">
// markdown code blocks...
</sandpack>Custom Component Mapping
You can override the <sandpack> component or add your own:
<script type="importmap">
{
"imports": {
"@codesandbox/sandpack-react": "https://esm.sh/@codesandbox/[email protected]",
"@rizalibnu/sandpack-embedder": "https://esm.sh/@rizalibnu/sandpack-embedder"
}
}
</script>
<script type="module" src="https://esm.sh/tsx"></script>
<script type="text/babel">
import { SandpackEmbedder } from "@rizalibnu/sandpack-embedder";
import {
SandpackProvider,
SandpackLayout,
SandpackPreview,
SandpackCodeEditor
} from "@codesandbox/sandpack-react";
function CustomSandpack(props) {
return (
<SandpackProvider>
<SandpackLayout>
<SandpackCodeEditor />
<SandpackPreview />
</SandpackLayout>
</SandpackProvider>
)
};
function VuePack(props) {
return <Sandpack {...props} template="vue" />;
}
new SandpackEmbedder({
customComponents: { sandpack: CustomSandpack, vuepack: VuePack },
}).load();
</script>This allows you to use any custom tag like <vuepack> or <playground> as long as it’s mapped in customComponents.
<vuepack>
// markdown code blocks...
</vuepack>Installation
pnpm add @rizalibnu/sandpack-embedder
# or
yarn add @rizalibnu/sandpack-embedder
# or
npm install @rizalibnu/sandpack-embedderStorybook
To explore and test UI behaviors interactively:
pnpm storybookTesting
Run unit tests with Vitest:
pnpm testLicense
MIT © Rizal Ibnu
