Set up collaborative Tiptap editing in Bubble with WhoIsTyping
Connect your Bubble editor to WhoIsTyping, then verify that two different signed-in app users receive each other's edits. The editor comes from the Rich text editor (Tiptap.dev) plugin; WhoIsTyping provides the hosted collaboration service.
Tested October 8, 2026 with released plugin 4.14.0: native Bubble token generation, two distinct authenticated test users, edits in both directions, moving remote carets, refresh/reconnect, recovery after all peers closed, a malformed-token control and a same-user control. This was a small fictional development fixture, not customer-success evidence or a performance benchmark. Reopen recovery is an observed result, not a durable-storage SLA or full security audit. Selection highlighting was not separately tested.
Before you start
You need:
- A Bubble development app with the released plugin version used by this recipe. Testing is a different version; do not substitute it for this recipe.
- An authorized WhoIsTyping project with available capacity, its Document Server ID and its Document Server Secret. Reuse an existing project where appropriate and obtain its details through your authorized project-access route.
- Two different fictional test users and a safe app login flow. Bubble user identity is separate from the developer's WhoIsTyping account.
- A decision about your app's trust model. Document name is routing, not a document permission. Do not assume WhoIsTyping enforces document-specific token grants or read-only claims. Restrict who can obtain a project token through your app and review the design before using it with mutually untrusted users.
This recipe uses static Doc Server ID. Version 4.14.0 does not expose the source/Testing field called Doc Server ID (dynamic).
1. Configure the private development secret
In Plugins → Rich text editor, locate Custom collab document server secret. Use its private development override for your authorized test project's Document Server Secret. Do not overwrite the live key just to run a development test.
The setting is shared across the app's development pages: check whether other test demos depend on it before changing it. The editor's project-ID field does not automatically select a different signing secret. Your configured project ID and private secret must belong to the same project.
Keep the secret in the server-side plugin setting only—not page text, custom browser JavaScript, URLs, logs, screenshots or support posts. Generated JWTs must also stay out of logs and screenshots. The acceptance fixture found no secret in the inspected client configuration surfaces; that observation is not a whole-app security certification.
2. Add the test editor
Create a dedicated development page and add one Tiptap element. Choose one disposable fictional document name, such as collab-example-001, and use it for both test users.
| Setting | Value |
|---|---|
| Enable collaboration? | yes |
| Provider | custom |
| Custom - URL | wss://collab.whoistyping.wtf |
| Doc Server ID | Your project's Document Server ID—not your Bubble app ID |
| Document name | The same fictional document name in both sessions |
| JWT key | A transient text custom state populated by the successful token workflow |
| user_name | A display name associated with the signed-in test user |
| cursor_color | Your chosen cursor colour; distinct colours can help distinguish participants |
| File uploads enabled | no for this minimal test |
Use the host alone. In this released Bubble plugin recipe, the plugin adds the project path. Do not append it a second time.
Leave autobinding off for the collaborative document. Synchronization is not a confirmed save to a Bubble Thing; add any database-copy or webhook handling as a separate step after collaboration works.
3. Mint a token only after the user is authenticated
Create a text custom state for the token. Use Page is loaded → only when Current User is logged in when the user is already signed in before opening the page. If your login completes later, trigger the workflow after successful login instead of minting an anonymous token at page load.
- Run generate auth token.
- Set Which document server secret to use to Custom explicitly rather than Tiptap Cloud.
- Set Document names (comma-separated) to this one fictional document name.
- Set the action's Doc Server ID to the same project's Document Server ID used by the element. It is not your Bubble app ID.
- Set User ID (sub) to Current User's unique id.
- Set Expiration (seconds) explicitly. The acceptance fixture used 300 seconds; mint fresh native tokens for reconnect rather than reusing expired ones. The fixture did not test an expired-token control or forced disconnection at expiry. Do not assume expiration forcibly ends an already-connected session.
- Add a Set state action only when Result of step …'s returned_an_error is no AND Result of step …'s auth token is not empty.
-
Set the transient text state to Result of step … (generate auth token)'s auth token. Bind that state to the editor's JWT key. Select the text
auth tokenoutput, noterror.
If the initial mint fails, do not populate the token state; show only a sanitized failure category. If renewal fails, the success-only state update does not clear an earlier token or disconnect an existing session. Do not reuse a stale token for a new connection. A Connect / renew button can repeat the same authenticated workflow for recovery.
Checkpoint: confirm that the collaboration connection is connected and synced. An editor-ready state or a generated token alone is not evidence that the hosted provider admitted the session.
4. Verify two users, in both directions
Use genuinely isolated authenticated sessions for fictional users Rowan and Jules. Two tabs sharing login cookies are normally the same user and do not establish this result. For a developer-only test, Bubble's development-data Run as mechanism can authenticate newly created fixture users without a signup/email flow; never use existing customer accounts as fixtures. This is a development test mechanism, not a production login design.
- Open the same page, project and fictional document in both sessions. Confirm both are connected and synced.
- With real clicks and typing, Rowan enters a harmless fictional sentence. Jules should see it without reloading.
- Jules enters another sentence. Rowan should see that edit without reloading.
- Test presence separately: move a caret in one editor and check that the corresponding remote caret/label moves in the other. Cursor visibility alone does not prove text synchronization.
- Refresh one session. Wait for authenticated-user readiness and successful native token generation again. Confirm reconnection, recovered fictional content and a new edit arriving in the other editor.
- In a dedicated development control, bind a fixed fictional malformed token. It must not count as admitted/synced; the tested released plugin disconnected and removed the editor while retrying. Stop the control deliberately and restore the normal native workflow rather than retrying indefinitely. A disconnected state alone does not diagnose the server's rejection reason.
- Open a same-user pair of tabs only as a negative control: they must not count as two authenticated participants. A local automated presence demo is also not hosted two-user proof.
- Close both sessions, then reopen the same document in an authenticated test session with a freshly generated token. Check whether the fictional edits are recovered. The fixture passed this check; it does not establish a storage SLA or retention guarantee.
Expected result: both distinct authenticated users receive each other's edits in the same document, and the reconnect check succeeds. Record cursor behavior separately. Use only your authorized disposable fixture; no customer content is needed.
Troubleshooting
| Symptom | Check |
|---|---|
| Token action fails | Custom source selected; matching private development secret/project ID; authenticated identity ready |
| Token exists but no admission |
Host-only URL, correct project ID, successful auth token
output binding, token expiration and connection/sync status
|
| Admitted but edits do not arrive | Same project/document and genuinely separate sessions; confirm an applied remote edit, not just participant counts |
| Text arrives but no cursor |
Released user_name
and cursor_color
bindings; compare actual caret movement separately
|
| Refresh/reconnect fails | Identity resolved before mint; fresh successful native token bound before reconnect |
| Bubble database copy is missing | Diagnose separate save/webhook ownership; synchronization is not a database acknowledgement |
For support, share the plugin version, test environment and a redacted failure category. Never send secret values, JWTs, user IDs, customer document names/content or raw customer logs.
Ready to evaluate hosted collaboration for your Bubble editor? Start with WhoIsTyping and validate your own authorized shared-edit workflow. Registration, project creation and presence alone are not proof of successful collaboration.