A browser-based REPL for Svelte 5 that runs entirely in the browser — no server, no bundler required.
svelte-repl provides an interactive editor for Svelte 5 components with live preview and console output. The Svelte compiler runs directly in the browser, making the REPL completely self-contained and deployable as static HTML — no backend, no build step at runtime.
I originally built svelte-repl to give my students a possibility to tinker around with Svelte 5 in their browsers - GDPR-compliant and without having to install anything. But, perhaps, other people may find this little tool useful as well.
<iframe>console.log, warn, error, info, and dir output is forwarded from the iframe, with an unread-message badge on the Console tabinitial-code parameterThe REPL runs Svelte 5 in runes mode without a bundler. Only Svelte 5 syntax is supported. The most important difference from Svelte 4 is event handling:
on:click={handler} → onclick={handler}on:input, on:focus, on:blur, … → oninput, onfocus, onblur, …createEventDispatcher → callback propsbeforeUpdate / afterUpdate → $effectRule of thumb: replace every
on:eventnamewithoneventname(remove the colon). Everything else — transitions,{#if},{#each},{#await},bind:value,bind:this— remains unchanged.
The following Svelte packages are available in user code (all bundled into svelte-runtime.js):
svelte: mount, onMount, onDestroy, getContext, setContext, tick, …svelte/store: writable, readable, readonly, fromStore, toStoresvelte/transition: fade, fly, slide, scale, draw, crossfadesvelte/animate: flipsvelte/motion: tweened, springsvelte/easing: all easing functionssvelte/reactivity: SvelteMap, SvelteSet, SvelteURL, …svelte/events: onsvelte/legacy is intentionally excluded — it is not needed in runes mode.
initial-code — initial editor content, encoded as deflate-raw + base64url (see below); defaults to a minimal templatename — key suffix for the localStorage backup key (see below); backup is disabled when absentbackup-prefix — prefix for the localStorage backup key; backup is disabled when emptyconsole-char-limit — maximum characters shown per console value; default: 10000console-line-limit — maximum number of console lines kept in the Console tab; default: 500focus-on — initial active tab; one of code (default), preview, or console; other values are ignoredinitial-codeThe initial-code value is a URL-safe base64 string of the deflate-raw compressed source. To generate it from JavaScript:
async function encodeForURL (Code) {
const encodedText = new TextEncoder().encode(Code)
const Stream = new Blob([encodedText]).stream()
.pipeThrough(new CompressionStream('deflate-raw'))
const compressedCode = await new Response(Stream).arrayBuffer()
return btoa(String.fromCharCode(...new Uint8Array(compressedCode)))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
}
Example URL:
https://example.com/repl/?initial-code=<encoded-svelte-code>
When backup-prefix is set, the editor content is automatically saved to and restored from localStorage['{backup-prefix}-{name}']. This switch had to be provided because of the GDPR
Example:
https://example.com/repl/?backup-prefix=my-app&name=my-project
With this URL, the REPL saves and restores code via localStorage['my-app-my-project']. Backup is disabled when backup-prefix is absent or empty.
Prerequisites: Node.js ≥ 18, npm
npm install
npm run build:assets
This runs build-runtime.mjs and build-compiler.mjs via Rollup, producing:
src/assets/svelte-runtime.js — the Svelte 5 runtime as a self-contained ESM modulesrc/assets/svelte-compiler.js — the Svelte 5 compiler bundled for browser useThese two files must exist before running dev or build. Re-run build:assets after upgrading the svelte package version.
npm run dev
Vite serves the app with hot module replacement. The two asset files are served directly from src/assets/ during development.
npm run build
Output goes to dist/. The result is a fully static site — just serve the dist/ folder from any web server or CDN. No server-side logic is required.
npm run preview