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