livecodes/framework-wrappers

SkillAI & models

Use SDK with React, Vue, Svelte, Solid, Preact, and Web Components. sdkReady callback pattern, reactive props, and framework-specific setup. Load this skill when embedding LiveCodes in a framework application.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the livecodes/framework-wrappers skill

What this skill tells your AI

The instructions your AI receives, as published by live-codes/livecodes in .agents/skills/livecodes/framework-wrappers/SKILL.md and read by ahel’s review.

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

import 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

PropTypeDescription
All EmbedOptionsPass EmbedOptions as props
classNamestringContainer class name
heightstringContainer height
styleobjectContainer styles
sdkReady(sdk: Playground) => voidCallback with SDK instance

React: Reactive Props

function 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

<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

PropTypeDescription
All EmbedOptionsPass EmbedOptions as props
heightstringContainer height

Vue: Events

EventPayload
@sdk-ready(sdk: Playground) => void

Vue: Reactive Props

<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

<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

import 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

import 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

<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
<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:

<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:

<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:

  1. config property (highest — explicit programmatic override)
  2. Children (declarative defaults)
  3. config attribute (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():

<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):

function 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):

function 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):

<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

// 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

# 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 props
  • Playground — SDK Playground interface
  • Config — Configuration type
  • Code — Code object type
  • Language — Language string type

Signals

GitHub stars
1k
Forks
266
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
livecodes-framework-wrappers
Source
github.com/live-codes/livecodes