This example uses the Tiptap 3 documentation and an existing Vue 3 project. It covers a local edit buffer and deliberate replacement; your application still supplies the real save endpoint and its response handling. Vue integration, content representations
Add the editor to the existing Vue project
Install the documented packages, keeping their major versions aligned:
npm install @tiptap/vue-3@3 @tiptap/pm@3 @tiptap/starter-kit@3
The following single-file component adapts those APIs to an original collection notice. It provides an edit area, a bold control, and a button that captures the current HTML into a local output field:
<script setup>
import { ref } from 'vue'
import { EditorContent, useEditor } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
const capturedHtml = ref('')
const editor = useEditor({
extensions: [StarterKit],
content: '<p>Collect your badge at the side desk.</p>',
})
function capture() {
if (!editor.value) return
capturedHtml.value = editor.value.getHTML()
}
</script>
<template>
<section aria-label="Collection notice editor">
<button
type="button"
:disabled="!editor"
@click="editor?.chain().focus().toggleBold().run()"
>Bold</button>
<EditorContent :editor="editor" />
<button type="button" :disabled="!editor" @click="capture">
Capture current HTML
</button>
<h2>Local HTML capture</h2>
<pre>{{ capturedHtml }}</pre>
</section>
</template>
<style scoped>
pre { white-space: pre-wrap; overflow-wrap: anywhere; }
</style>
EditorContent renders the editing surface. The pre displays the captured string as text through Vue interpolation, so an author can inspect tags. It does not render a second editable copy of the notice. Add the application's intended editor styling; Tiptap is a headless editor rather than a finished toolbar design.
This is an integration fragment to run in your Vue application. The capture button takes a local snapshot. Its label deliberately does not claim a server save.
Choose a storage representation before wiring Save
For a CMS that stores HTML fragments, capture editor.value.getHTML() inside the real save handler and send that value through the application's existing persistence route. For a Tiptap document store, retrieve getJSON() instead. The output guide documents both representations and restoring them as editor content.
Choose one authoritative stored representation and keep the relevant extension configuration with it. A JSON object from Tiptap is a structured editor document; it is different from an arbitrary object extracted from an HTML page.
After a successful save response, reopen that record and inspect its words and supported formatting. A response that only echoes the submitted payload is not proof that a later fetch will return it.
Replace loaded content without creating an update loop
When an API response intentionally replaces the current notice, the Tiptap 3 command accepts an options object:
editor.value.commands.setContent(loadedHtml, {
emitUpdate: false
})
Run that only after the editor exists and after deciding that replacement is appropriate. For example, switching from one record to another should first resolve any unsaved changes to the current record.
Tiptap 3 defaults emitUpdate to true, a change from version 2. Suppressing that update event can prevent a load operation from reentering a listener that handles user changes. The command also renders only content permitted by the configured schema. setContent options
Avoid a broad watcher that calls setContent every time the same document's state changes. The editor already owns a live editing state. Continually replacing that document can disturb the author's work and obscure which change should be saved.
Check the actual authoring sequence
With the collection fixture, select “side desk,” apply Bold, and capture the current HTML. Confirm the words remain intact and the selected phrase has emphasis. Change the desk instruction and capture again; the second output should contain the new wording.
Then exercise the real save and reopen flow. If the stored words are right but the layout differs, check the reader stylesheet. If content disappears while loading, check the enabled schema and extensions. Vue in a standalone HTML page covers a separate approach; the .vue component above belongs in the project's build process.
Treat user-authored rich text as untrusted input at the application's display boundary. Define the permitted content and enforce the application's rendering policy before showing stored HTML to other readers. Finish by reopening the saved notice in its actual reader view, where the collection instruction must remain clear after the editing session ends.