---
title: "Nuxt"
description: "Learn how to set up the Tiptap Editor with Nuxt.js for a dynamic rich text editing experience. Dive into our guide in our docs!"
canonical_url: "https://tiptap.dev/docs/editor/getting-started/install/nuxt"
---

# Nuxt

Learn how to set up the Tiptap Editor with Nuxt.js for a dynamic rich text editing experience. Dive into our guide in our docs!

This guide covers how to integrate Tiptap with your Nuxt 4 project, complete with code examples.

### Requirements

- [Node](https://nodejs.org/en/download/) installed on your machine
- Experience with [Vue](https://vuejs.org/guide/introduction.html)

## Create a project (optional)

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

For the purpose of this guide, start with a fresh Nuxt project called `my-tiptap-project`. The following command sets up everything you need:

```bash
# create a project
npx nuxi@latest init my-tiptap-project

# change directory
cd my-tiptap-project
```

### Install the dependencies

Now let's install Tiptap! For the following example, you'll need the `@tiptap/vue-3` package with a few components, the `@tiptap/pm` package, and `@tiptap/starter-kit`, which has the most common extensions to get started quickly.

```bash
npm install @tiptap/vue-3 @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/](http://localhost:3000/) in your favorite browser. This might be different if you're working with an existing project.

## Integrate Tiptap

To actually start using Tiptap, you'll need to add a new component to your app. Let's call it `TiptapEditor` and put the following example code in `components/TiptapEditor.vue`.

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

Since Nuxt uses server-side rendering (SSR), we set `immediatelyRender: false` to prevent the editor from rendering on the server. The editor requires browser APIs that aren't available during SSR, so this option ensures it only renders on the client after hydration.

```html
<template>
  <EditorContent :editor="editor" />
</template>

<script setup>
  import { useEditor, EditorContent } from '@tiptap/vue-3'
  import StarterKit from '@tiptap/starter-kit'

  const editor = useEditor({
    content: `<p>I'm running Tiptap with Vue.js. 🎉</p>`,
    extensions: [StarterKit],
    // Don't render on the server, only on the client after hydration
    immediatelyRender: false,
  })
</script>
```

### Add it to your app

Now, replace the content of `app/app.vue` with the following code to use our new `TiptapEditor` component:

```html
<template>
  <TiptapEditor />
</template>
```

In Nuxt 4, both components and Vue composables (like `ref` and `watch`) are auto-imported, so you don't need to manually import or register them.

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

### Use v-model (optional)

You're probably used to binding your data with `v-model` in forms. This also possible with Tiptap. Here's a working example component, that you can integrate in your project:

> **Interactive demo:** [VModel](https://embed.tiptap.dev/preview/GuideGettingStarted/VModel)

```html
<template>
  <EditorContent :editor="editor" />
</template>

<script setup>
  import { useEditor, EditorContent } from '@tiptap/vue-3'
  import StarterKit from '@tiptap/starter-kit'

  const emit = defineEmits(['update:modelValue'])
  const props = defineProps({
    modelValue: {
      type: String,
      default: '',
    },
  })

  const editor = useEditor({
    content: props.modelValue,
    extensions: [StarterKit],
    // Don't render on the server, only on the client after hydration
    immediatelyRender: false,
    onUpdate: ({ editor }) => {
      // HTML
      emit('update:modelValue', editor.getHTML())

      // JSON
      // emit('update:modelValue', editor.getJSON())
    },
  })

  watch(
    () => props.modelValue,
    (value) => {
      // HTML
      const isSame = editor.value?.getHTML() === value

      // JSON
      // const isSame = JSON.stringify(editor.value?.getJSON()) === JSON.stringify(value)

      if (isSame) {
        return
      }

      editor.value?.commands.setContent(value, false)
    }
  )
</script>
```

## Next steps

- [Configure your editor](https://tiptap.dev/docs/editor/getting-started/configure.md)
- [Add styles to your editor](https://tiptap.dev/docs/editor/getting-started/style-editor.md)
- [Learn more about Tiptaps concepts](https://tiptap.dev/docs/editor/core-concepts/introduction.md)
- [Learn how to persist the editor state](https://tiptap.dev/docs/editor/core-concepts/persistence.md)
- [Start building your own extensions](https://tiptap.dev/docs/editor/extensions/custom-extensions.md)
