The LiveCodes SDK provides a first-class React component for embedding playgrounds in React applications.
Installation
Install the livecodes package:
Import
Import the React component:
import LiveCodes from 'livecodes/react';
For TypeScript users:
import LiveCodes from 'livecodes/react';
import type { Props } from 'livecodes/react';
Basic Usage
import LiveCodes from 'livecodes/react';
export default function App() {
return (
<LiveCodes
config={{
markup: {
language: 'html',
content: '<h1>Hello from React!</h1>',
},
}}
/>
);
}
Props
The React component accepts all EmbedOptions as props, plus additional React-specific props.
Component-Specific Props
CSS class name for the container element.<LiveCodes className="my-playground" />
Inline styles for the container element.<LiveCodes style={{ height: '500px', border: '1px solid #ddd' }} />
Height of the playground container.<LiveCodes height="600px" />
sdkReady
(sdk: Playground) => void
Callback function called when the SDK is ready.<LiveCodes
sdkReady={(playground) => {
console.log('Playground ready!', playground);
}}
/>
Embed Options Props
appUrl
string
default:"https://livecodes.io"
URL of the LiveCodes app.
Configuration object or URL to config JSON.
Resource to import (GitHub, GitLab, gist, etc.).
loading
'lazy' | 'click' | 'eager'
default:"lazy"
Loading strategy.
Starter template to load.
Examples
With Template
import LiveCodes from 'livecodes/react';
export function ReactPlayground() {
return <LiveCodes template="react" />;
}
With Custom Config
import LiveCodes from 'livecodes/react';
const config = {
markup: {
language: 'markdown',
content: '# Hello World\n\nThis is a **LiveCodes** playground.',
},
style: {
language: 'css',
content: 'body { font-family: system-ui; padding: 2rem; }',
},
script: {
language: 'javascript',
content: 'console.log("Hello from JavaScript!");',
},
autoupdate: true,
};
export function MyPlayground() {
return (
<LiveCodes
config={config}
height="500px"
className="my-custom-playground"
/>
);
}
With SDK Ready Callback
import { useState } from 'react';
import LiveCodes from 'livecodes/react';
export function InteractivePlayground() {
const [playground, setPlayground] = useState(null);
const handleRun = async () => {
if (playground) {
await playground.run();
}
};
const handleFormat = async () => {
if (playground) {
await playground.format();
}
};
return (
<div>
<div style={{ marginBottom: '1rem' }}>
<button onClick={handleRun}>Run</button>
<button onClick={handleFormat}>Format</button>
</div>
<LiveCodes
template="javascript"
sdkReady={(sdk) => setPlayground(sdk)}
height="400px"
/>
</div>
);
}
Watching Events
import { useEffect, useState } from 'react';
import LiveCodes from 'livecodes/react';
export function EventWatcher() {
const [playground, setPlayground] = useState(null);
const [logs, setLogs] = useState([]);
useEffect(() => {
if (!playground) return;
// Watch console output
const consoleWatcher = playground.watch('console', ({ method, args }) => {
setLogs((prev) => [...prev, { method, args }]);
});
// Watch code changes
const codeWatcher = playground.watch('code', ({ code }) => {
console.log('Code changed:', code);
});
// Cleanup
return () => {
consoleWatcher.remove();
codeWatcher.remove();
};
}, [playground]);
return (
<div>
<LiveCodes
template="javascript"
sdkReady={setPlayground}
height="300px"
/>
<div style={{ marginTop: '1rem' }}>
<h3>Console Output:</h3>
<ul>
{logs.map((log, i) => (
<li key={i}>
{log.method}: {JSON.stringify(log.args)}
</li>
))}
</ul>
</div>
</div>
);
}
Dynamic Config Updates
import { useState } from 'react';
import LiveCodes from 'livecodes/react';
export function DynamicPlayground() {
const [language, setLanguage] = useState('javascript');
const config = {
script: {
language,
content: language === 'javascript'
? 'console.log("Hello from JS!");'
: 'console.log("Hello from TS!");',
},
};
return (
<div>
<select value={language} onChange={(e) => setLanguage(e.target.value)}>
<option value="javascript">JavaScript</option>
<option value="typescript">TypeScript</option>
</select>
<LiveCodes config={config} height="400px" />
</div>
);
}
Importing from GitHub
import LiveCodes from 'livecodes/react';
export function GithubImport() {
return (
<LiveCodes
import="https://github.com/username/repo"
height="500px"
/>
);
}
Multiple Playgrounds
import LiveCodes from 'livecodes/react';
export function MultiplePlaygrounds() {
return (
<div style={{ display: 'flex', gap: '1rem' }}>
<LiveCodes
template="react"
height="400px"
style={{ flex: 1 }}
/>
<LiveCodes
template="vue"
height="400px"
style={{ flex: 1 }}
/>
</div>
);
}
TypeScript Support
The component is fully typed for TypeScript:
import LiveCodes from 'livecodes/react';
import type { Props, Playground, Config } from 'livecodes/react';
const config: Partial<Config> = {
markup: {
language: 'html',
content: '<h1>TypeScript Support</h1>',
},
};
function TypedPlayground() {
const handleReady = (playground: Playground) => {
console.log('Playground ready!');
};
return (
<LiveCodes
config={config}
sdkReady={handleReady}
height="500px"
/>
);
}
Styling
Style the playground container:
import LiveCodes from 'livecodes/react';
import './playground.css';
export function StyledPlayground() {
return (
<LiveCodes
className="custom-playground"
style={{
height: '600px',
borderRadius: '8px',
boxShadow: '0 4px 6px rgba(0,0,0,0.1)',
}}
template="react"
/>
);
}
/* playground.css */
.custom-playground {
max-width: 1200px;
margin: 2rem auto;
}
Component Lifecycle
The component handles lifecycle automatically:
- Mount: Creates the playground when component mounts
- Update: Updates config when props change
- Unmount: Destroys the playground and cleans up event listeners
Best Practices
-
Use
sdkReady for SDK access: Store the playground instance in state when you need to call methods.
-
Memoize config objects: Use
useMemo for config objects to prevent unnecessary re-renders.
import { useMemo } from 'react';
import LiveCodes from 'livecodes/react';
function OptimizedPlayground({ code }) {
const config = useMemo(() => ({
script: { language: 'javascript', content: code },
}), [code]);
return <LiveCodes config={config} />;
}
-
Clean up watchers: Always remove event watchers in cleanup functions.
-
Set explicit height: Always specify a height for better UX.
Next.js Integration
For Next.js, use dynamic import to avoid SSR issues:
import dynamic from 'next/dynamic';
const LiveCodes = dynamic(() => import('livecodes/react'), {
ssr: false,
loading: () => <div>Loading playground...</div>,
});
export default function Page() {
return <LiveCodes template="react" />;
}
Next Steps
Vue Component
Learn about the Vue component
Methods
Explore available methods
Events
Understand the event system
Types
Browse TypeScript types