Skip to main content
The LiveCodes SDK provides a first-class React component for embedding playgrounds in React applications.

Installation

Install the livecodes package:
npm install livecodes

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

className
string
CSS class name for the container element.
<LiveCodes className="my-playground" />
style
Record<string, string>
Inline styles for the container element.
<LiveCodes style={{ height: '500px', border: '1px solid #ddd' }} />
height
string
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.
config
Partial<Config> | string
Configuration object or URL to config JSON.
import
string
Resource to import (GitHub, GitLab, gist, etc.).
headless
boolean
default:false
Load in headless mode.
loading
'lazy' | 'click' | 'eager'
default:"lazy"
Loading strategy.
params
object
URL query parameters.
template
string
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

  1. Use sdkReady for SDK access: Store the playground instance in state when you need to call methods.
  2. 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} />;
}
  1. Clean up watchers: Always remove event watchers in cleanup functions.
  2. 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

Build docs developers (and LLMs) love