Svelte Rich Text Editor
Scribe Editor is the lightweight, zero-dependency WYSIWYG editor for Svelte and SvelteKit. Under 50KB, minimal boilerplate with onMount, reactive bind:value, and a full feature set — in a framework with almost no native WYSIWYG options.
The Svelte rich text editor gap
Most popular WYSIWYG editors (Tiptap, Lexical, Slate) are built for React. Their Svelte wrappers are often community-maintained, lagging in features, or incomplete. Scribe is built framework-agnostic from the ground up — Svelte is a first-class citizen.
- Scribe: works natively in Svelte with standard lifecycle functions
- No React peer dependency, no framework shims, no unofficial ports
- Compatible with Svelte 4, Svelte 5, and SvelteKit
Svelte Component
A complete, reusable Svelte component with reactive value binding and exported formatting methods.
<!-- ScribeEditor.svelte -->
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { Scribe, type EditorInstance } from 'scribejs-editor';
import 'scribejs-editor/dist/scribe.css';
export let value = '';
export let placeholder = 'Start writing...';
let editorEl: HTMLElement;
let editor: EditorInstance | null = null;
onMount(() => {
editorEl.innerHTML = value;
editor = Scribe.init(editorEl, {
placeholder,
onChange: (html) => { value = html; },
});
});
onDestroy(() => editor?.destroy());
// Exported methods — call via bind:this
export const bold = () => editor?.bold();
export const italic = () => editor?.italic();
export const getHTML = () => editor?.getHTML() ?? '';
</script>
<div bind:this={editorEl} class="scribe-content" />Using the Component
Use bind:this to access imperative methods and bind:value for two-way content binding.
<!-- App.svelte -->
<script lang="ts">
import ScribeEditor from './ScribeEditor.svelte';
let editorRef: ScribeEditor;
let content = '<p>Hello from Svelte!</p>';
</script>
<!-- Bind the component instance for imperative access -->
<button on:click={() => editorRef.bold()}>Bold</button>
<button on:click={() => editorRef.italic()}>Italic</button>
<button on:click={() => console.log(editorRef.getHTML())}>Save</button>
<ScribeEditor
bind:this={editorRef}
bind:value={content}
placeholder="Start writing..."
/>
<p>Live preview:</p>
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
<div>{@html content}</div>SvelteKit SSR Setup
Dynamic import inside onMount keeps Scribe out of the SvelteKit SSR bundle entirely.
<!-- SvelteKit — disable SSR per-page or wrap in browser check -->
<script lang="ts">
import { browser } from '$app/environment';
import { onMount, onDestroy } from 'svelte';
let editorEl: HTMLElement;
let editor: any = null;
onMount(async () => {
if (!browser) return;
// Dynamic import keeps Scribe out of the SSR bundle
const { Scribe } = await import('scribejs-editor');
editor = Scribe.init(editorEl, { toolbar: 'floating' });
});
onDestroy(() => editor?.destroy());
</script>
<div bind:this={editorEl} />Feature highlights
Minimal boilerplate
onMount + onDestroy — that's the entire lifecycle. No wrappers, no stores, no context. Just Svelte the way it's meant to be.
bind:value reactive binding
Update your Svelte reactive variable directly from onChange. Use bind:this for imperative bold(), italic(), getHTML() access.
SvelteKit compatible
Dynamic import inside onMount keeps Scribe out of the SSR bundle. No window is not defined errors.
Lightest option for Svelte
Under 50KB gzipped. Most other WYSIWYG editors are React-first — Scribe is truly framework-agnostic.
Complete out of the box
The WYSIWYG editor Svelte deserves.
Framework-agnostic by design, lightweight by default. The best rich text editor choice for Svelte projects.
Svelte + Scribe — common questions
What is the best rich text editor for Svelte?
Scribe Editor is one of the best lightweight WYSIWYG editors for Svelte. It integrates with onMount and onDestroy lifecycle functions, under 50KB gzipped with zero dependencies, supports bind:value for reactive binding and bind:this for imperative API access. It works with both Svelte and SvelteKit.
How do I add a rich text editor to a Svelte component?
Create a Svelte component with a bound element reference (bind:this={editorEl}). In onMount, call Scribe.init(editorEl, options). Pass an onChange callback to sync the editor content with a reactive variable. In onDestroy, call editor.destroy() to clean up.
Does Scribe Editor work with SvelteKit?
Yes. In SvelteKit, import Scribe dynamically inside onMount using await import('scribejs-editor'). This ensures the library is never imported during server-side rendering, which avoids window is not defined errors. You can also check the browser flag from $app/environment before initializing.
Are there many rich text editor options for Svelte?
The Svelte ecosystem has far fewer native WYSIWYG options compared to React. Most popular editors (Tiptap, Lexical, Slate) are React-first with limited or community-maintained Svelte wrappers. Scribe Editor is framework-agnostic from the ground up, making it one of the most reliable choices for Svelte projects.
Also compare Scribe with:
Use Scribe in your framework: