Skip to main content
The LiveCodes SDK can be used in Svelte applications. While there isn’t a dedicated Svelte component, the vanilla JavaScript SDK integrates seamlessly with Svelte’s reactive system.

Installation

Install the livecodes package:
npm install livecodes

Basic Usage

Use the createPlayground function in Svelte’s lifecycle:
<script>
import { onMount } from 'svelte';
import { createPlayground } from 'livecodes';

let container;
let playground;

onMount(async () => {
  playground = await createPlayground(container, {
    config: {
      markup: {
        language: 'html',
        content: '<h1>Hello from Svelte!</h1>',
      },
    },
  });
});
</script>

<div bind:this={container}></div>

Complete Example

<script>
import { onMount, onDestroy } from 'svelte';
import { createPlayground } from 'livecodes';

let container;
let playground;

const config = {
  markup: {
    language: 'html',
    content: '<h1>Hello, World!</h1>',
  },
  style: {
    language: 'css',
    content: 'h1 { color: #ff3e00; font-family: sans-serif; }',
  },
  script: {
    language: 'javascript',
    content: 'console.log("Hello from LiveCodes!");',
  },
};

onMount(async () => {
  playground = await createPlayground(container, { config });
});

onDestroy(() => {
  playground?.destroy();
});
</script>

<div bind:this={container} class="playground" />

<style>
.playground {
  height: 500px;
  border: 1px solid #ddd;
  border-radius: 8px;
}
</style>

With Template

<script>
import { onMount, onDestroy } from 'svelte';
import { createPlayground } from 'livecodes';

export let template = 'svelte';

let container;
let playground;

onMount(async () => {
  playground = await createPlayground(container, { template });
});

onDestroy(() => {
  playground?.destroy();
});
</script>

<div bind:this={container} class="playground" />

<style>
.playground {
  height: 600px;
}
</style>

Interactive Controls

<script>
import { onMount, onDestroy } from 'svelte';
import { createPlayground } from 'livecodes';

let container;
let playground;

const handleRun = async () => {
  await playground?.run();
};

const handleFormat = async () => {
  await playground?.format();
};

const handleGetCode = async () => {
  const code = await playground?.getCode();
  console.log('Current code:', code);
};

onMount(async () => {
  playground = await createPlayground(container, {
    template: 'javascript',
  });
});

onDestroy(() => {
  playground?.destroy();
});
</script>

<div class="container">
  <div class="controls">
    <button on:click={handleRun}>Run</button>
    <button on:click={handleFormat}>Format</button>
    <button on:click={handleGetCode}>Get Code</button>
  </div>
  
  <div bind:this={container} class="playground" />
</div>

<style>
.controls {
  margin-bottom: 1rem;
  display: flex;
  gap: 0.5rem;
}

button {
  padding: 0.5rem 1rem;
  border: 1px solid #ff3e00;
  background: white;
  color: #ff3e00;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background: #ff3e00;
  color: white;
}

.playground {
  height: 400px;
}
</style>

Watching Events

<script>
import { onMount, onDestroy } from 'svelte';
import { createPlayground } from 'livecodes';

let container;
let playground;
let logs = [];
let watchers = [];

onMount(async () => {
  playground = await createPlayground(container, {
    template: 'javascript',
  });

  // Watch console output
  const consoleWatcher = playground.watch('console', ({ method, args }) => {
    logs = [...logs, { method, args, timestamp: Date.now() }];
  });

  // Watch code changes
  const codeWatcher = playground.watch('code', ({ code }) => {
    console.log('Code changed:', code.script.content);
  });

  watchers = [consoleWatcher, codeWatcher];
});

onDestroy(() => {
  watchers.forEach(w => w.remove());
  playground?.destroy();
});
</script>

<div>
  <div bind:this={container} class="playground" />
  
  <div class="console-output">
    <h3>Console Output:</h3>
    <ul>
      {#each logs as log (log.timestamp)}
        <li>{log.method}: {JSON.stringify(log.args)}</li>
      {/each}
    </ul>
  </div>
</div>

<style>
.playground {
  height: 300px;
  margin-bottom: 1rem;
}

.console-output {
  padding: 1rem;
  background: #f5f5f5;
  border-radius: 4px;
}
</style>

Reactive Configuration

<script>
import { onMount, onDestroy } from 'svelte';
import { createPlayground } from 'livecodes';

let container;
let playground;
let language = 'javascript';
let code = 'console.log("Hello!");';

$: if (playground) {
  updateConfig();
}

const updateConfig = async () => {
  if (!playground) return;
  
  await playground.setConfig({
    script: {
      language,
      content: code,
    },
  });
};

onMount(async () => {
  playground = await createPlayground(container, {
    config: {
      script: { language, content: code },
    },
  });
});

onDestroy(() => {
  playground?.destroy();
});
</script>

<div class="container">
  <div class="controls">
    <select bind:value={language}>
      <option value="javascript">JavaScript</option>
      <option value="typescript">TypeScript</option>
      <option value="python">Python</option>
    </select>
    
    <textarea bind:value={code} rows="3" />
  </div>
  
  <div bind:this={container} class="playground" />
</div>

<style>
.controls {
  margin-bottom: 1rem;
}

textarea {
  width: 100%;
  padding: 0.5rem;
  font-family: monospace;
  margin-top: 0.5rem;
}

.playground {
  height: 400px;
}
</style>

Creating a Reusable Component

Create a reusable LiveCodes.svelte component:
<!-- LiveCodes.svelte -->
<script>
import { onMount, onDestroy } from 'svelte';
import { createPlayground } from 'livecodes';

export let config = undefined;
export let template = undefined;
export let loading = 'lazy';
export let height = '500px';
export let onReady = undefined;

let container;
let playground;

onMount(async () => {
  playground = await createPlayground(container, {
    config,
    template,
    loading,
  });
  
  if (onReady) {
    onReady(playground);
  }
});

onDestroy(() => {
  playground?.destroy();
});
</script>

<div 
  bind:this={container} 
  class="livecodes-container"
  style="height: {height}"
/>

<style>
.livecodes-container {
  width: 100%;
  border: 1px solid #ddd;
  border-radius: 8px;
}
</style>
Then use it:
<script>
import LiveCodes from './LiveCodes.svelte';

const config = {
  markup: {
    language: 'html',
    content: '<h1>Reusable Component</h1>',
  },
};

const handleReady = (playground) => {
  console.log('Playground is ready!', playground);
};
</script>

<LiveCodes 
  {config}
  height="600px"
  onReady={handleReady}
/>

TypeScript Support

For TypeScript, create a .svelte file with TypeScript in the script tag:
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { createPlayground } from 'livecodes';
import type { Playground, Config } from 'livecodes';

let container: HTMLDivElement;
let playground: Playground | undefined;

const config: Partial<Config> = {
  markup: {
    language: 'html',
    content: '<h1>TypeScript Support</h1>',
  },
};

onMount(async () => {
  playground = await createPlayground(container, { config });
});

onDestroy(() => {
  playground?.destroy();
});
</script>

<div bind:this={container} class="playground" />

<style>
.playground {
  height: 500px;
}
</style>

SvelteKit Integration

For SvelteKit, ensure the SDK loads only on the client:
<script>
import { onMount, onDestroy } from 'svelte';
import { browser } from '$app/environment';

let container;
let playground;

onMount(async () => {
  if (browser) {
    const { createPlayground } = await import('livecodes');
    
    playground = await createPlayground(container, {
      template: 'svelte',
    });
  }
});

onDestroy(() => {
  playground?.destroy();
});
</script>

<div bind:this={container} class="playground" />

<style>
.playground {
  height: 600px;
}
</style>
Or use a client-only wrapper:
<!-- +page.svelte -->
<script>
import Playground from './Playground.svelte';
</script>

{#if browser}
  <Playground />
{/if}

Props Pattern

Create a component that accepts props:
<script>
import { onMount, onDestroy } from 'svelte';
import { createPlayground } from 'livecodes';

export let appUrl = undefined;
export let config = undefined;
export let template = undefined;
export let loading = 'lazy';
export let headless = false;
export let height = '500px';

let container;
let playground;

$: options = {
  appUrl,
  config,
  template,
  loading,
  headless,
};

onMount(async () => {
  playground = await createPlayground(container, options);
});

onDestroy(() => {
  playground?.destroy();
});
</script>

<div 
  bind:this={container} 
  style="height: {height}"
  class="playground"
/>

Best Practices

  1. Always destroy: Call playground.destroy() in onDestroy to clean up.
  2. Use bind:this: Bind the container element for direct reference.
  3. Check browser environment: In SvelteKit, ensure code runs only on client.
  4. Handle async properly: Use await when calling playground methods.
  5. Remove watchers: Clean up event watchers in onDestroy.

Common Patterns

Loading State

<script>
import { onMount, onDestroy } from 'svelte';
import { createPlayground } from 'livecodes';

let container;
let playground;
let loading = true;

onMount(async () => {
  playground = await createPlayground(container, {
    template: 'svelte',
  });
  loading = false;
});

onDestroy(() => {
  playground?.destroy();
});
</script>

{#if loading}
  <div class="loading">Loading playground...</div>
{/if}

<div bind:this={container} class="playground" class:hidden={loading} />

<style>
.hidden {
  display: none;
}

.loading {
  height: 500px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f5f5;
}
</style>

Error Handling

<script>
import { onMount, onDestroy } from 'svelte';
import { createPlayground } from 'livecodes';

let container;
let playground;
let error = null;

onMount(async () => {
  try {
    playground = await createPlayground(container, {
      template: 'svelte',
    });
  } catch (err) {
    error = err.message;
    console.error('Failed to create playground:', err);
  }
});

onDestroy(() => {
  playground?.destroy();
});
</script>

{#if error}
  <div class="error">
    Error: {error}
  </div>
{:else}
  <div bind:this={container} class="playground" />
{/if}

Next Steps

Methods

Explore all available SDK methods

Events

Learn about the event system

Types

Browse TypeScript type definitions

Getting Started

Back to getting started guide

Build docs developers (and LLMs) love