Skip to main content
The LiveCodes SDK provides a native Vue 3 component for embedding playgrounds in Vue applications.

Installation

Install the livecodes package:
npm install livecodes

Import

Import the Vue component:
<script setup>
import LiveCodes from 'livecodes/vue';
</script>
For TypeScript users:
<script setup lang="ts">
import LiveCodes from 'livecodes/vue';
import type { Props } from 'livecodes/vue';
</script>

Basic Usage

<script setup>
import LiveCodes from 'livecodes/vue';

const config = {
  markup: {
    language: 'html',
    content: '<h1>Hello from Vue!</h1>',
  },
};
</script>

<template>
  <LiveCodes :config="config" />
</template>

Props

The Vue component accepts all EmbedOptions as props, plus Vue-specific props.

Component-Specific Props

height
string
Height of the playground container.
<LiveCodes height="600px" />

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.
<LiveCodes :config="config" />
import
string
Resource to import (GitHub, GitLab, gist, etc.).
<LiveCodes import="https://github.com/username/repo" />
headless
boolean
default:false
Load in headless mode.
<LiveCodes :headless="true" />
loading
'lazy' | 'click' | 'eager'
default:"lazy"
Loading strategy.
<LiveCodes loading="eager" />
params
object
URL query parameters.
<LiveCodes :params="{ title: 'My Project' }" />
template
string
Starter template to load.
<LiveCodes template="vue" />

Events

sdkReady

Emitted when the playground initializes. Receives the Playground SDK instance.
<script setup>
import { ref } from 'vue';
import LiveCodes from 'livecodes/vue';

const playground = ref(null);

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

<template>
  <LiveCodes 
    template="javascript" 
    @sdk-ready="handleSdkReady"
  />
</template>

Examples

With Template

<script setup>
import LiveCodes from 'livecodes/vue';
</script>

<template>
  <LiveCodes template="vue" />
</template>

With Custom Config

<script setup>
import LiveCodes from 'livecodes/vue';

const config = {
  markup: {
    language: 'markdown',
    content: '# Hello World\n\nThis is a **LiveCodes** playground in Vue.',
  },
  style: {
    language: 'css',
    content: 'body { font-family: system-ui; padding: 2rem; }',
  },
  script: {
    language: 'javascript',
    content: 'console.log("Hello from JavaScript!");',
  },
  autoupdate: true,
};
</script>

<template>
  <LiveCodes 
    :config="config"
    height="500px"
    class="my-playground"
  />
</template>

<style scoped>
.my-playground {
  border: 2px solid #42b883;
  border-radius: 8px;
}
</style>

Interactive Controls

<script setup>
import { ref } from 'vue';
import LiveCodes from 'livecodes/vue';

const playground = ref(null);

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

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

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

<template>
  <div>
    <div class="controls">
      <button @click="handleRun">Run</button>
      <button @click="handleFormat">Format</button>
      <button @click="handleGetCode">Get Code</button>
    </div>
    
    <LiveCodes
      template="javascript"
      height="400px"
      @sdk-ready="(sdk) => playground = sdk"
    />
  </div>
</template>

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

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

button:hover {
  background: #42b883;
  color: white;
}
</style>

Watching Events

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import LiveCodes from 'livecodes/vue';

const playground = ref(null);
const logs = ref([]);

let watchers = [];

const handleSdkReady = (sdk) => {
  playground.value = sdk;

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

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

  watchers = [consoleWatcher, codeWatcher];
};

onUnmounted(() => {
  watchers.forEach(w => w.remove());
});
</script>

<template>
  <div>
    <LiveCodes
      template="javascript"
      height="300px"
      @sdk-ready="handleSdkReady"
    />
    
    <div class="console-output">
      <h3>Console Output:</h3>
      <ul>
        <li v-for="(log, i) in logs" :key="i">
          {{ log.method }}: {{ JSON.stringify(log.args) }}
        </li>
      </ul>
    </div>
  </div>
</template>

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

Reactive Config

<script setup>
import { ref, computed } from 'vue';
import LiveCodes from 'livecodes/vue';

const language = ref('javascript');
const code = ref('console.log("Hello!");');

const config = computed(() => ({
  script: {
    language: language.value,
    content: code.value,
  },
  autoupdate: true,
}));
</script>

<template>
  <div>
    <div class="controls">
      <select v-model="language">
        <option value="javascript">JavaScript</option>
        <option value="typescript">TypeScript</option>
        <option value="python">Python</option>
      </select>
      
      <textarea v-model="code" rows="3" />
    </div>
    
    <LiveCodes :config="config" height="400px" />
  </div>
</template>

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

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

Loading from Config URL

<script setup>
import LiveCodes from 'livecodes/vue';

const configUrl = 'https://example.com/playground-config.json';
</script>

<template>
  <LiveCodes :config="configUrl" height="500px" />
</template>

Multiple Playgrounds

<script setup>
import LiveCodes from 'livecodes/vue';
</script>

<template>
  <div class="playgrounds">
    <div class="playground">
      <h2>React Example</h2>
      <LiveCodes template="react" height="400px" />
    </div>
    
    <div class="playground">
      <h2>Vue Example</h2>
      <LiveCodes template="vue" height="400px" />
    </div>
  </div>
</template>

<style scoped>
.playgrounds {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
  gap: 2rem;
}

.playground h2 {
  margin-bottom: 1rem;
}
</style>

Composition API Example

<script setup>
import { ref, watch } from 'vue';
import LiveCodes from 'livecodes/vue';

const playground = ref(null);
const shareUrl = ref('');
const currentCode = ref('');

const generateShareUrl = async () => {
  if (!playground.value) return;
  shareUrl.value = await playground.value.getShareUrl();
};

const updateCodeDisplay = async () => {
  if (!playground.value) return;
  const code = await playground.value.getCode();
  currentCode.value = code.script.content;
};

const handleSdkReady = (sdk) => {
  playground.value = sdk;
  
  // Watch for code changes
  sdk.watch('code', () => {
    updateCodeDisplay();
  });
};
</script>

<template>
  <div>
    <LiveCodes
      template="javascript"
      height="300px"
      @sdk-ready="handleSdkReady"
    />
    
    <div class="info">
      <button @click="generateShareUrl">Generate Share URL</button>
      <p v-if="shareUrl">Share URL: <a :href="shareUrl" target="_blank">{{ shareUrl }}</a></p>
      <p v-if="currentCode">Current Code Length: {{ currentCode.length }} characters</p>
    </div>
  </div>
</template>

<style scoped>
.info {
  margin-top: 1rem;
  padding: 1rem;
  background: #f9f9f9;
  border-radius: 4px;
}

button {
  margin-bottom: 1rem;
}
</style>

TypeScript Support

The component is fully typed for TypeScript:
<script setup lang="ts">
import { ref } from 'vue';
import LiveCodes from 'livecodes/vue';
import type { Props, Playground, Config } from 'livecodes/vue';

const playground = ref<Playground | null>(null);

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

const handleReady = (sdk: Playground) => {
  playground.value = sdk;
};
</script>

<template>
  <LiveCodes
    :config="config"
    height="500px"
    @sdk-ready="handleReady"
  />
</template>

Styling

Style the component using scoped styles:
<script setup>
import LiveCodes from 'livecodes/vue';
</script>

<template>
  <div class="playground-wrapper">
    <LiveCodes
      class="custom-playground"
      template="vue"
      height="600px"
    />
  </div>
</template>

<style scoped>
.playground-wrapper {
  max-width: 1200px;
  margin: 2rem auto;
  padding: 1rem;
}

.custom-playground {
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}
</style>

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

Best Practices

  1. Use refs for SDK access: Store the playground instance in a ref when you need to call methods.
  2. Use computed for reactive config: Wrap config in computed() for reactive updates.
<script setup>
import { ref, computed } from 'vue';
import LiveCodes from 'livecodes/vue';

const code = ref('console.log("Hello!");');

const config = computed(() => ({
  script: { language: 'javascript', content: code.value },
}));
</script>

<template>
  <LiveCodes :config="config" />
</template>
  1. Clean up watchers: Remove watchers in onUnmounted hook.
  2. Set explicit height: Always specify a height for better UX.

Nuxt Integration

For Nuxt 3, use client-only component:
<template>
  <ClientOnly>
    <LiveCodes template="vue" />
  </ClientOnly>
</template>

<script setup>
import LiveCodes from 'livecodes/vue';
</script>
Or configure in nuxt.config.ts:
export default defineNuxtConfig({
  build: {
    transpile: ['livecodes'],
  },
});

Next Steps

Svelte Usage

Learn about using LiveCodes with Svelte

Methods

Explore available methods

Events

Understand the event system

Types

Browse TypeScript types