Svelte

Learn how to integrate Tiptap with your SvelteKit project using this step-by-sep guide. Alternatively, check out our Svelte text editor example.

Take a shortcut: Svelte REPL with Tiptap

If you want to jump into it right away, here is a Svelte REPL with Tiptap.

Requirements

  • Node installed on your machine
  • Experience with Svelte

Create a project (optional)

If you already have a SvelteKit project, that's fine too. Just skip this step.

For the purpose of this guide, start with a fresh SvelteKit project called my-tiptap-project. The following commands set up everything we need. It asks a lot of questions, but select your preferred options or use the defaults.

npm create svelte@latest my-tiptap-project
cd my-tiptap-project
npm install
npm run dev

Install dependencies

Now that we're done with boilerplate, let's install Tiptap! For the following example you'll need the @tiptap/core package, with a few components, @tiptap/pm, and @tiptap/starter-kit, which includes the most common extensions to get started quickly.

npm install @tiptap/core @tiptap/pm @tiptap/starter-kit

If you followed steps 1 and 2, you can now start your project with npm run dev and open http://localhost:3000/ in your favorite browser. This might be different if you're working with an existing project.

Integrate Tiptap

To start using Tiptap, you'll need to add a new component to your app. Let's call it Tiptap and add the following example code in src/lib/Tiptap.svelte.

This is the fastest way to get Tiptap up and running with SvelteKit. It will give you a very basic version of Tiptap, without any buttons. No worries, you will be able to add more functionality soon.

<script>
	import { onMount, onDestroy } from 'svelte';
	import { Editor } from '@tiptap/core';
	import StarterKit from '@tiptap/starter-kit';

	let element;
	let editor;

	onMount(() => {
		editor = new Editor({
			element: element,
			extensions: [StarterKit],
			content: '<p>Hello World! 🌍️ </p>',
			onTransaction: () => {
				// force re-render so `editor.isActive` works as expected
				editor = editor;
			},
		});
	});

	onDestroy(() => {
		if (editor) {
			editor.destroy();
		}
	});
</script>

{#if editor}
	<button
		on:click={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
		class:active={editor.isActive('heading', { level: 1 })}
	>
		H1
	</button>
	<button
		on:click={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
		class:active={editor.isActive('heading', { level: 2 })}
	>
		H2
	</button>
	<button
		on:click={() => editor.chain().focus().setParagraph().run()}
		class:active={editor.isActive('paragraph')}
	>
		P
	</button>
{/if}

<div bind:this={element} />

<style>
	button.active {
		background: black;
		color: white;
	}
</style>

Add it to your app

Now, let's replace the content of src/routes/+page.svelte with the following example code to use our new Tiptap component in our app.

<script>
  import Tiptap from '$lib/Tiptap.svelte'
</script>

<main>
  <Tiptap />
</main>

Tiptap should now be visible in your browser. Time to give yourself a pat on the back! :)