Skip to content

Commit

Permalink
TiptapCollab blog post series: WIP 2
Browse files Browse the repository at this point in the history
  • Loading branch information
janthurau committed May 14, 2023
1 parent e2f79e9 commit 6e420b6
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 28 deletions.
5 changes: 5 additions & 0 deletions demos/src/Posts/1-2-tiptap/Vue/Note.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ watch(props, () => modelValueProxy.value = props.note.content)
const editor = useEditor({
content: props.note.content,
editorProps: {
attributes: {
class: 'm-2 p-2 border border-black rounded-lg',
},
},
extensions: [
StarterKit,
],
Expand Down
2 changes: 2 additions & 0 deletions demos/src/Posts/1-2-tiptap/Vue/index.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<script setup lang="ts">
import './styles.css'
import Note from './Note.vue'
import { TNote } from './types'
Expand Down
3 changes: 3 additions & 0 deletions demos/src/Posts/1-2-tiptap/Vue/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
5 changes: 5 additions & 0 deletions demos/src/Posts/1-3-yjs/Vue/Note.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ const doc = new Y.Doc()
const editor = useEditor({
content: props.note.defaultContent,
editorProps: {
attributes: {
class: 'm-2 p-2 border border-black rounded-lg',
},
},
extensions: [
StarterKit.configure({
history: false, // important because history will now be handled by Y.js
Expand Down
2 changes: 2 additions & 0 deletions demos/src/Posts/1-3-yjs/Vue/index.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<script setup lang="ts">
import './styles.css'
import Note from './Note.vue'
import { TNote } from './types'
Expand Down
3 changes: 3 additions & 0 deletions demos/src/Posts/1-3-yjs/Vue/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
21 changes: 10 additions & 11 deletions demos/src/Posts/1-4-collab/Vue/Note.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { TiptapCollabProvider } from '@hocuspocus/provider'
import { Collaboration } from '@tiptap/extension-collaboration'
import StarterKit from '@tiptap/starter-kit'
import { EditorContent, useEditor } from '@tiptap/vue-3'
import { fromBase64 } from 'lib0/buffer'
import { onMounted, onUnmounted } from 'vue'
import * as Y from 'yjs'
Expand All @@ -14,16 +13,7 @@ const props = defineProps<{ note: TNote }>()
let provider: TiptapCollabProvider | undefined
const createDocFromBase64 = (base64Update: string) => {
const doc = new Y.Doc()
Y.applyUpdate(doc, fromBase64(base64Update))
return doc
}
// usually, you'd just do `new Y.Doc()` here. We are doing some magic to make sure you can just switch to your APP and you have the same document
const doc = createDocFromBase64(props.note.documentBase64)
const doc = new Y.Doc()
onMounted(() => {
provider = new TiptapCollabProvider({
Expand All @@ -37,6 +27,15 @@ onMounted(() => {
onUnmounted(() => provider?.destroy())
const editor = useEditor({
// make sure that you don't use `content` property anymore!
// If you want to add default content, feel free to just write text to the tiptap editor (i.e. editor.setContent (https://tiptap.dev/api/commands/set-content), but make sure that
// you do this only once per document, otherwise the content will
// be added again, and again, and again ..
editorProps: {
attributes: {
class: 'm-2 p-2 border border-black rounded-lg',
},
},
extensions: [
StarterKit.configure({
history: false, // important because history will now be handled by Y.js
Expand Down
6 changes: 4 additions & 2 deletions demos/src/Posts/1-4-collab/Vue/index.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<script setup lang="ts">
import './styles.css'
import Note from './Note.vue'
import { TNote } from './types'
const notes: TNote[] = [
{ id: 'note-1', documentBase64: 'AgHaj462BgCE4If+hAIbEHJhbmRvbSBub3RlIHRleHQG4If+hAIABwEHZGVmYXVsdAMJcGFyYWdyYXBoBwDgh/6EAgAGBADgh/6EAgEFc29tZSCE4If+hAIGD3RvdGFsbHkgcmFuZG9tIIHgh/6EAhUChOCH/oQCFwRub3RlAeCH/oQCAQcV' },
{ id: 'note-2', documentBase64: 'AgHiy6OpCACE4If+hAIbF3JlYWxseSByYW5kb20gbm90ZSB0ZXh0BuCH/oQCAAcBB2RlZmF1bHQDCXBhcmFncmFwaAcA4If+hAIABgQA4If+hAIBBXNvbWUghOCH/oQCBg90b3RhbGx5IHJhbmRvbSCB4If+hAIVAoTgh/6EAhcEbm90ZQHgh/6EAgEHFQ==' },
{ id: 'note-1' },
{ id: 'note-2' },
]
</script>
Expand Down
3 changes: 3 additions & 0 deletions demos/src/Posts/1-4-collab/Vue/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
1 change: 0 additions & 1 deletion demos/src/Posts/1-4-collab/Vue/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export type TNote = {
id: string;
documentBase64: string;
};
28 changes: 14 additions & 14 deletions docs/posts/1.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
Hi there!

Welcome to the first post of a series of blog posts about collaboration in Tiptap using TiptapCollab. This series will start covering the basics, and cover more specific use-cases in the next posts. For today, we’ll start moving from a simple textarea box to a fully collaborative Tiptap editor instance.
**Welcome** to the first post of a series of blog posts about collaboration in Tiptap using TiptapCollab. This series will start covering the basics, and expand to more specific use cases in the next posts. For today, we’ll start moving from a simple textarea box to a fully collaborative Tiptap editor instance.

Imagine that you are building a simple sticky note app, where a user can create notes. Just like Apple Notes, but with better collaboration.

So you have like a textarea and a button 'create new note'. Depending on your framework (Vue, React, ..), the code probably looks similar to this:
(for simplicity, we haven't added the 'new note' logic here)
So let's say you have a few textareas. Depending on your framework (Vue, React, ..), the code probably looks similar to this:

<tiptap-demo name="Posts/1-1-textarea"></tiptap-demo>

Expand All @@ -19,9 +16,9 @@ npm install @tiptap/vue-3 @tiptap/pm @tiptap/starter-kit

<tiptap-demo name="Posts/1-2-tiptap"></tiptap-demo>

Now your Note component has a fully functional Tiptap editor instance! The user can now format their text (see https://tiptap.dev/guide/menus on how to add a menu bar, in our example you can make text bold using cmd+b). But what about collaboration?
Now your Note component has a fully functional Tiptap editor instance! The user can now format their text (see https://tiptap.dev/guide/menus on how to add a menu bar, in our example, you can make text bold using cmd+b). But what about collaboration?

To enable collaboration, you need to add the Collaboration extension to your editor instance. This extension allows multiple users to edit the same document simultaneously, with changes being synced in real-time.
To enable collaboration, you need to add the Collaboration extension to your editor instance. This extension allows multiple users to edit the same document simultaneously, with changes being synced in realtime.


To add the Collaboration extension to your editor instance, you first need to install the `@tiptap/extension-collaboration` package:
Expand All @@ -36,15 +33,17 @@ Then, you can import the `Collaboration` extension and add it to your editor ext

ok, so what have we done?

We just added the collaboration extension as well as the technology behind it, Yjs. Basically instead of text we are passing the Y.Doc which basically takes care of merging changes. But so far, there is no collaboration...
We just added the collaboration extension as well as the technology behind it, Yjs. Instead of raw text we are passing the Y.Doc which basically takes care of merging changes. But so far, there is no collaboration...

To enable real-time collaboration, we need to connect the Y.Doc with the HocuspocusProvider. The HocuspocusProvider is a package that provides a simple way to synchronize Y.Doc's across different clients.

To enable real-time collaboration, we need to connect Yjs with the HocuspocusProvider. The HocuspocusProvider is a package that provides a simple way to share Yjs documents across different clients. It sets up a Yjs room and connects all participants to that room.
To start using HocuspocusProvider, we need to create a new instance of the HocuspocusProvider class and pass our Y.Doc. We also need to provide a document name.

To start using HocuspocusProvider, we need to create a new instance of the HocuspocusProvider class and pass it our Yjs document. We also need to provide a document name to connect all participants.
To get started, let's sign up for a Tiptap Pro account, which comes with a free licence of Tiptap Collab:

To get started, let's sign up for a Tiptap Pro account, which comes with a free licence for Tiptap Collab: https://tiptap.dev/pricing
!!tiptap-collab-cta

After you signed up, go to tiptap.dev/pro and click "Join the Beta". Just follow the instructions and you'll be set up within a few minutes.
After you signed up, click on "Join the Beta". Just follow the instructions and you'll be set up within a few minutes.

Your app ID is shown in the collab admin interface: https://collab.tiptap.dev/ - just copy that and also already get the JWT from the settings area. It's valid for two hours, so more than enough for our quick test. We'll cover generating JWTs using your secret later..

Expand All @@ -59,6 +58,7 @@ Let's now create the TiptapCollabProvider to finally get syncing:

<tiptap-demo name="Posts/1-4-collab"></tiptap-demo>

And that's it! With these changes, our Tiptap note-taking application is now fully collaborative. Notes will get synced to other users in real-time.
And that's it! With these changes, our Tiptap note-taking application is now fully collaborative. Notes will get synced to other users in realtime.


Of course, this is just the beginning of what is possible with TiptapCollab and Hocuspocus. In future articles, we'll explore more advanced use cases, such as permissions, presence indicators, and more. Stay tuned!
We've only scratched the surface of what TiptapCollab and Hocuspocus can do. Keep an eye out for future articles where we'll delve into more complex scenarios like permissions, presence indicators, and beyond. Don't miss out!

0 comments on commit 6e420b6

Please sign in to comment.