diff --git a/demos/src/GuideNodeViews/Component/React/Component.jsx b/demos/src/GuideNodeViews/Component/React/Component.jsx
new file mode 100644
index 00000000..efe0d9b1
--- /dev/null
+++ b/demos/src/GuideNodeViews/Component/React/Component.jsx
@@ -0,0 +1,22 @@
+import React from 'react'
+import { NodeViewWrapper } from '@tiptap/react'
+
+export default props => {
+ const increase = () => {
+ props.updateAttributes({
+ count: props.node.attrs.count + 1,
+ })
+ }
+
+ return (
+
+ React Component
+
+
+
+
+
+ )
+}
diff --git a/demos/src/GuideNodeViews/Component/React/Extension.js b/demos/src/GuideNodeViews/Component/React/Extension.js
new file mode 100644
index 00000000..36d61318
--- /dev/null
+++ b/demos/src/GuideNodeViews/Component/React/Extension.js
@@ -0,0 +1,35 @@
+import { Node, mergeAttributes } from '@tiptap/core'
+import { ReactNodeViewRenderer } from '@tiptap/react'
+import Component from './Component.jsx'
+
+export default Node.create({
+ name: 'reactComponent',
+
+ group: 'block',
+
+ atom: true,
+
+ addAttributes() {
+ return {
+ count: {
+ default: 0,
+ },
+ }
+ },
+
+ parseHTML() {
+ return [
+ {
+ tag: 'react-component',
+ },
+ ]
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['react-component', mergeAttributes(HTMLAttributes)]
+ },
+
+ addNodeView() {
+ return ReactNodeViewRenderer(Component)
+ },
+})
diff --git a/demos/src/GuideNodeViews/Component/React/index.html b/demos/src/GuideNodeViews/Component/React/index.html
new file mode 100644
index 00000000..a9efc346
--- /dev/null
+++ b/demos/src/GuideNodeViews/Component/React/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/GuideNodeViews/Component/React/index.jsx b/demos/src/GuideNodeViews/Component/React/index.jsx
new file mode 100644
index 00000000..394c78fe
--- /dev/null
+++ b/demos/src/GuideNodeViews/Component/React/index.jsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import { useEditor, EditorContent } from '@tiptap/react'
+import StarterKit from '@tiptap/starter-kit'
+import ReactComponent from './Extension.js'
+import './styles.scss'
+
+export default () => {
+ const editor = useEditor({
+ extensions: [
+ StarterKit,
+ ReactComponent,
+ ],
+ content: `
+
+ This is still the text editor you’re used to, but enriched with node views.
+
+
+
+ Did you see that? That’s a React component. We are really living in the future.
+
+ `,
+ })
+
+ return (
+
+ )
+}
diff --git a/demos/src/GuideNodeViews/Component/React/styles.scss b/demos/src/GuideNodeViews/Component/React/styles.scss
new file mode 100644
index 00000000..93c543c4
--- /dev/null
+++ b/demos/src/GuideNodeViews/Component/React/styles.scss
@@ -0,0 +1,33 @@
+/* Basic editor styles */
+.ProseMirror {
+ > * + * {
+ margin-top: 0.75em;
+ }
+}
+
+.react-component {
+ background: #FAF594;
+ border: 3px solid #0D0D0D;
+ border-radius: 0.5rem;
+ margin: 1rem 0;
+ position: relative;
+
+ .label {
+ margin-left: 1rem;
+ background-color: #0D0D0D;
+ font-size: 0.6rem;
+ letter-spacing: 1px;
+ font-weight: bold;
+ text-transform: uppercase;
+ color: #fff;
+ position: absolute;
+ top: 0;
+ padding: 0.25rem 0.75rem;
+ border-radius: 0 0 0.5rem 0.5rem;
+ }
+
+ .content {
+ margin-top: 1.5rem;
+ padding: 1rem;
+ }
+}
diff --git a/demos/src/GuideNodeViews/Component/Vue/Component.vue b/demos/src/GuideNodeViews/Component/Vue/Component.vue
new file mode 100644
index 00000000..1fe5d072
--- /dev/null
+++ b/demos/src/GuideNodeViews/Component/Vue/Component.vue
@@ -0,0 +1,60 @@
+
+
+ Vue Component
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/GuideNodeViews/Component/Vue/Extension.js b/demos/src/GuideNodeViews/Component/Vue/Extension.js
new file mode 100644
index 00000000..a4f786d3
--- /dev/null
+++ b/demos/src/GuideNodeViews/Component/Vue/Extension.js
@@ -0,0 +1,35 @@
+import { Node, mergeAttributes } from '@tiptap/core'
+import { VueNodeViewRenderer } from '@tiptap/vue-3'
+import Component from './Component.vue'
+
+export default Node.create({
+ name: 'vueComponent',
+
+ group: 'block',
+
+ atom: true,
+
+ addAttributes() {
+ return {
+ count: {
+ default: 0,
+ },
+ }
+ },
+
+ parseHTML() {
+ return [
+ {
+ tag: 'vue-component',
+ },
+ ]
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['vue-component', mergeAttributes(HTMLAttributes)]
+ },
+
+ addNodeView() {
+ return VueNodeViewRenderer(Component)
+ },
+})
diff --git a/demos/src/GuideNodeViews/Component/Vue/index.html b/demos/src/GuideNodeViews/Component/Vue/index.html
new file mode 100644
index 00000000..d451dc01
--- /dev/null
+++ b/demos/src/GuideNodeViews/Component/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/GuideNodeViews/Component/Vue/index.vue b/demos/src/GuideNodeViews/Component/Vue/index.vue
new file mode 100644
index 00000000..3e050e2a
--- /dev/null
+++ b/demos/src/GuideNodeViews/Component/Vue/index.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
diff --git a/demos/src/GuideNodeViews/ComponentContent/React/Component.jsx b/demos/src/GuideNodeViews/ComponentContent/React/Component.jsx
new file mode 100644
index 00000000..efcd93a1
--- /dev/null
+++ b/demos/src/GuideNodeViews/ComponentContent/React/Component.jsx
@@ -0,0 +1,12 @@
+import React from 'react'
+import { NodeViewWrapper, NodeViewContent } from '@tiptap/react'
+
+export default () => {
+ return (
+
+ React Component
+
+
+
+ )
+}
diff --git a/demos/src/GuideNodeViews/ComponentContent/React/Extension.js b/demos/src/GuideNodeViews/ComponentContent/React/Extension.js
new file mode 100644
index 00000000..90a92887
--- /dev/null
+++ b/demos/src/GuideNodeViews/ComponentContent/React/Extension.js
@@ -0,0 +1,27 @@
+import { Node, mergeAttributes } from '@tiptap/core'
+import { ReactNodeViewRenderer } from '@tiptap/react'
+import Component from './Component.jsx'
+
+export default Node.create({
+ name: 'reactComponent',
+
+ group: 'block',
+
+ content: 'inline*',
+
+ parseHTML() {
+ return [
+ {
+ tag: 'react-component',
+ },
+ ]
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['react-component', mergeAttributes(HTMLAttributes), 0]
+ },
+
+ addNodeView() {
+ return ReactNodeViewRenderer(Component)
+ },
+})
diff --git a/demos/src/GuideNodeViews/ComponentContent/React/index.html b/demos/src/GuideNodeViews/ComponentContent/React/index.html
new file mode 100644
index 00000000..9eaa6da9
--- /dev/null
+++ b/demos/src/GuideNodeViews/ComponentContent/React/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/GuideNodeViews/ComponentContent/React/index.jsx b/demos/src/GuideNodeViews/ComponentContent/React/index.jsx
new file mode 100644
index 00000000..ac2e67a2
--- /dev/null
+++ b/demos/src/GuideNodeViews/ComponentContent/React/index.jsx
@@ -0,0 +1,29 @@
+import React from 'react'
+import { useEditor, EditorContent } from '@tiptap/react'
+import StarterKit from '@tiptap/starter-kit'
+import ReactComponent from './Extension.js'
+import './styles.scss'
+
+export default () => {
+ const editor = useEditor({
+ extensions: [
+ StarterKit,
+ ReactComponent,
+ ],
+ content: `
+
+ This is still the text editor you’re used to, but enriched with node views.
+
+
+ This is editable.
+
+
+ Did you see that? That’s a React component. We are really living in the future.
+
+ `,
+ })
+
+ return (
+
+ )
+}
diff --git a/demos/src/GuideNodeViews/ComponentContent/React/styles.scss b/demos/src/GuideNodeViews/ComponentContent/React/styles.scss
new file mode 100644
index 00000000..c61ccbe7
--- /dev/null
+++ b/demos/src/GuideNodeViews/ComponentContent/React/styles.scss
@@ -0,0 +1,36 @@
+/* Basic editor styles */
+.ProseMirror {
+ > * + * {
+ margin-top: 0.75em;
+ }
+}
+
+.react-component-with-content {
+ background: #FAF594;
+ border: 3px solid #0D0D0D;
+ border-radius: 0.5rem;
+ margin: 1rem 0;
+ position: relative;
+
+ .label {
+ margin-left: 1rem;
+ background-color: #0D0D0D;
+ font-size: 0.6rem;
+ letter-spacing: 1px;
+ font-weight: bold;
+ text-transform: uppercase;
+ color: #fff;
+ position: absolute;
+ top: 0;
+ padding: 0.25rem 0.75rem;
+ border-radius: 0 0 0.5rem 0.5rem;
+ }
+
+ .content {
+ margin: 2.5rem 1rem 1rem;
+ padding: 0.5rem;
+ border: 2px dashed #0D0D0D20;
+ border-radius: 0.5rem;
+ }
+}
+
diff --git a/demos/src/GuideNodeViews/ComponentContent/Vue/Component.vue b/demos/src/GuideNodeViews/ComponentContent/Vue/Component.vue
new file mode 100644
index 00000000..89c606ef
--- /dev/null
+++ b/demos/src/GuideNodeViews/ComponentContent/Vue/Component.vue
@@ -0,0 +1,50 @@
+
+
+ Vue Component
+
+
+
+
+
+
+
diff --git a/demos/src/GuideNodeViews/ComponentContent/Vue/Extension.js b/demos/src/GuideNodeViews/ComponentContent/Vue/Extension.js
new file mode 100644
index 00000000..89a991ec
--- /dev/null
+++ b/demos/src/GuideNodeViews/ComponentContent/Vue/Extension.js
@@ -0,0 +1,27 @@
+import { Node, mergeAttributes } from '@tiptap/core'
+import { VueNodeViewRenderer } from '@tiptap/vue-3'
+import Component from './Component.vue'
+
+export default Node.create({
+ name: 'vueComponent',
+
+ group: 'block',
+
+ content: 'inline*',
+
+ parseHTML() {
+ return [
+ {
+ tag: 'vue-component',
+ },
+ ]
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['vue-component', mergeAttributes(HTMLAttributes), 0]
+ },
+
+ addNodeView() {
+ return VueNodeViewRenderer(Component)
+ },
+})
diff --git a/demos/src/GuideNodeViews/ComponentContent/Vue/index.html b/demos/src/GuideNodeViews/ComponentContent/Vue/index.html
new file mode 100644
index 00000000..59488a63
--- /dev/null
+++ b/demos/src/GuideNodeViews/ComponentContent/Vue/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/GuideNodeViews/ComponentContent/Vue/index.vue b/demos/src/GuideNodeViews/ComponentContent/Vue/index.vue
new file mode 100644
index 00000000..6cc6bcb8
--- /dev/null
+++ b/demos/src/GuideNodeViews/ComponentContent/Vue/index.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
diff --git a/docs/examples/interactivity.md b/docs/examples/interactivity.md
index 9e7d71e2..9916ddf5 100644
--- a/docs/examples/interactivity.md
+++ b/docs/examples/interactivity.md
@@ -2,6 +2,6 @@
Thanks to [node views](/guide/node-views) you can add interactivity to your nodes. If you can write it in JavaScript, you can add it to the editor.
-https://embed.tiptap.dev/preview/GuideNodeViews/VueComponent
+https://embed.tiptap.dev/preview/GuideNodeViews/Component
-https://embed.tiptap.dev/preview/GuideNodeViews/VueComponentContent
+https://embed.tiptap.dev/preview/GuideNodeViews/ComponentContent