This skill builds on sdk-embedding and sdk-methods. Read them first for foundational concepts about createPlayground, SDK methods, and configuration.
LiveCodes — Framework SDK Wrappers
LiveCodes provides framework-specific components that wrap the core SDK. Each wrapper handles lifecycle, reactivity, and props.
React
jsximport LiveCodes from 'livecodes/react'; // Basic usage function App() { return <LiveCodes template="react" />; } // With config function App() { const config = { markup: { language: 'markdown', content: '# Hello World' }, }; return <LiveCodes config={config} height="400px" />; } // Access SDK methods via sdkReady function App() { const [playground, setPlayground] = useState(null); const handleRun = async () => { await playground?.run(); }; return ( <> <LiveCodes template="react" sdkReady={setPlayground} /> <button onClick={handleRun}>Run</button> </> ); } // TypeScript import LiveCodes, { type Props } from 'livecodes/react'; const options: Props = { config: { /* ... */ }, height: '500px', }; export default () => <LiveCodes {...options} />;
React: Available Props
| Prop | Type | Description |
|---|---|---|
| All EmbedOptions | — | Pass EmbedOptions as props |
className | string | Container class name |
height | string | Container height |
style | object | Container styles |
sdkReady | (sdk: Playground) => void | Callback with SDK instance |
React: Reactive Props
jsxfunction App() { const [config, setConfig] = useState({ markup: { language: 'html', content: '<h1>Hello</h1>' }, }); // Changing config uses setConfig() - no full reload const switchToMarkdown = () => { setConfig({ markup: { language: 'markdown', content: '# Hello' }, }); }; // Changing other props causes full reload // <LiveCodes template={template} /> // changing template reloads return ( <> <LiveCodes config={config} /> <button onClick={switchToMarkdown}>Switch to Markdown</button> </> ); }
Vue
vue<script setup> import LiveCodes from 'livecodes/vue'; const config = { markup: { language: 'markdown', content: '# Hello World' }, }; let playground; const onReady = (sdk) => { playground = sdk; }; const run = async () => { await playground?.run(); }; </script> <template> <LiveCodes :config="config" @sdk-ready="onReady" /> <button @click="run">Run</button> </template> <!-- With TypeScript --> <script setup lang="ts"> import LiveCodes, { type Props } from 'livecodes/vue'; import type { Playground } from 'livecodes'; const options: Props = { config: { /* ... */ }, }; </script> <template> <LiveCodes v-bind="options" /> </template>
Vue: Available Props
| Prop | Type | Description |
|---|---|---|
| All EmbedOptions | — | Pass EmbedOptions as props |
height | string | Container height |
Vue: Events
| Event | Payload |
|---|---|
@sdk-ready | (sdk: Playground) => void |
Vue: Reactive Props
vue<script setup> import { ref } from 'vue'; import LiveCodes from 'livecodes/vue'; const config = ref({ markup: { language: 'html', content: '<h1>Hello</h1>' }, }); // Uses setConfig() - no reload const switchToMarkdown = () => { config.value = { markup: { language: 'markdown', content: '# Hello' }, }; }; </script> <template> <LiveCodes :config="config" /> <button @click="switchToMarkdown">Switch</button> </template>
Svelte
svelte<script> import LiveCodes from 'livecodes/svelte'; let playground; const config = { markup: { language: 'markdown', content: '# Hello World' }, }; function onReady(sdk) { playground = sdk; } async function run() { await playground?.run(); } </script> <LiveCodes {config} on:sdkReady={onReady} /> <button on:click={run}>Run</button>
Solid
tsximport LiveCodes from 'livecodes/solid'; import { createSignal } from 'solid-js'; function App() { const [playground, setPlayground] = createSignal(null); const config = { markup: { language: 'markdown', content: '# Hello World' }, }; const handleRun = async () => { await playground()?.run(); }; return ( <> <LiveCodes config={config} sdkReady={setPlayground} /> <button onClick={handleRun}>Run</button> </> ); }
Preact
tsximport LiveCodes from 'livecodes/preact'; import { useState } from 'preact/hooks'; function App() { const [playground, setPlayground] = useState(null); const handleRun = async () => { await playground?.run(); }; return ( <> <LiveCodes template="react" sdkReady={setPlayground} /> <button onClick={handleRun}>Run</button> </> ); }
Web Components
html<script src="https://cdn.jsdelivr.net/npm/livecodes/web-components.js"></script> <!-- Basic usage --> <live-codes template="react"></live-codes> <!-- With config property --> <live-codes height="400px"></live-codes> <script> const playground = document.querySelector('live-codes'); playground.config = { markup: { language: 'markdown', content: '# Hello' }, }; </script>
Web Components: Declarative Code via Children
The web component supports providing code declaratively as child elements inside a wrapper <template>. This avoids JavaScript string escaping and enables IDE syntax highlighting.
The outer <template> makes inner <style> and <script> elements inert (no side effects on the embedding page).
Single-Editor Mode
html<live-codes height="400px"> <template> <template lang="html"> <h1>Hello World</h1> <p>Welcome to <strong>LiveCodes</strong></p> </template> <style lang="scss"> body { font-family: sans-serif; h1 { color: royalblue; } } </style> <script lang="ts"> console.log('Hello from TypeScript!'); </script> </template> </live-codes>
If lang is omitted, defaults are html, css, and javascript.
Active Editor
Use the active boolean attribute to set the initially focused editor:
html<live-codes> <template> <template lang="html"><h1>Hello</h1></template> <script lang="ts" active> console.log('focused'); </script> </template> </live-codes>
Config and Params Attributes
Use config and params HTML attributes as JSON strings for non-code settings:
html<live-codes config='{"processors": ["tailwindcss"]}' params='{"console": "open"}'> <template> <template lang="html"><h1 class="text-3xl">Hello</h1></template> </template> </live-codes>
Merge Precedence
When combining children, config attribute, and config property:
configproperty (highest — explicit programmatic override)- Children (declarative defaults)
configattribute (lowest — inline JSON settings)
Same for params: attribute is merged with property, property wins for overlapping keys.
Reactivity
Children content is reactive. Changing content inside the wrapper <template> programmatically triggers setConfig():
html<live-codes id="demo"> <template> <style lang="css"> h1 { color: blue; } </style> </template> </live-codes> <script> function changeColor() { const wrapper = document.querySelector('#demo > template'); wrapper.content.querySelector('style').textContent = 'h1 { color: red; }'; // MutationObserver detects this → setConfig() called } </script>
Common Mistakes
HIGH Not using sdkReady to access SDK in frameworks
Wrong (React):
jsxfunction App() { // No way to get SDK reference return <LiveCodes template="react" />; } function handleRun() { // Where's playground? Can't access SDK methods playground.run(); // Error: playground is undefined }
Correct (React):
jsxfunction App() { const [playground, setPlayground] = useState(null); const handleRun = async () => { await playground?.run(); }; return ( <> <LiveCodes template="react" sdkReady={setPlayground} /> <button onClick={handleRun}>Run</button> </> ); }
Correct (Vue):
vue<script setup> import LiveCodes from 'livecodes/vue'; import { ref } from 'vue'; const playground = ref(null); const onReady = (sdk) => { playground.value = sdk; }; </script> <template> <LiveCodes template="vue" @sdk-ready="onReady" /> </template>
The SDK is only available after the playground initializes. Use sdkReady (React), @sdk-ready (Vue), or on:sdkReady (Svelte) to get a reference.
Source: docs/docs/sdk/react.mdx, docs/docs/sdk/vue.mdx — sdkReady section
MEDIUM Changing non-config props causes full reload
jsx// React - config changes use setConfig (no reload) const [config, setConfig] = useState(initialConfig); setConfig(newConfig); // Efficient update, no iframe reload // React - other prop changes cause full reload const [template, setTemplate] = useState('react'); setTemplate('vue'); // Destroys and recreates iframe
Changing config prop uses SDK's setConfig() method under the hood — efficient. Changing other props (template, params, loading) destroys and recreates the iframe.
If you need reactive changes, prefer updating config over changing other props.
Source: docs/docs/sdk/react.mdx — Reactive Props section
Framework Installation
bash# React npm install livecodes import LiveCodes from 'livecodes/react'; # Vue 3 npm install livecodes import LiveCodes from 'livecodes/vue'; # Svelte npm install livecodes import LiveCodes from 'livecodes/svelte'; # Solid npm install livecodes import LiveCodes from 'livecodes/solid'; # Preact npm install livecodes import LiveCodes from 'livecodes/preact'; # Web Components (CDN) <script src="https://cdn.jsdelivr.net/npm/livecodes/web-components.js"></script>
Exported Types
All frameworks export:
Props— EmbedOptions plus framework-specific propsPlayground— SDK Playground interfaceConfig— Configuration typeCode— Code object typeLanguage— Language string type


