Sections
@editorcn/editor
@editorcn/block-editor
@editorcn/extensions
@editorcn/static-renderer
Templates are complete editors built from @editorcn/editor. Each one installs as a shadcn block: the CLI adds the template, the editor, and every component and extension it depends on. You own the code after install, so you can change anything. Each template lands in its own folder, components/templates/<name>/, split into small files (types, constants, toolbar, panels and so on) with index.tsx as the entry point.
Templates use Tailwind CSS
The editor and static renderer ship plain CSS and work in any React app.
Templates are styled with Tailwind CSS v4 and built on shadcn/ui components,
so your project needs Tailwind and shadcn/ui. Run npx shadcn@latest init
first if it isn't set up.
Already using Tiptap?
Tiptap packages must all be on the same version. The CLI installs the latest
3.x, so if your project already has @tiptap/* packages on an older 3.x
release, npm stops with an ERESOLVE peer dependency error. Update the
packages you already have first, for example npm install @tiptap/react@latest @tiptap/pm@latest @tiptap/starter-kit@latest, then add the template.
Templates work with shadcn/ui built on either Radix UI or Base UI.
All templates store content as Tiptap JSON (editor.getJSON()) and display it with the Static Renderer, which renders React elements instead of HTML. Content renders on the server, and stored content can't inject scripts. Use generateHTML(json, extensions) from @tiptap/core when you need HTML, for example in emails.
Comment Box
A comment thread with avatars, relative times, emoji reactions, YouTube-style replies and a composer built on the editor. Replies are one level deep and collapse under each comment; replying to a reply adds to the same thread and starts with an @mention. People can copy any comment and delete their own.
Comments
5- MLMaya Lindqvist
The new toolbar feels much lighter. Can we get a table shortcut in the next release?
- DODaniel Ortiz
Agreed. I'd also love
Mod+Shift+Tto insert a 3×3 table so we skip the dialog. - PRPriya Raman
Added it to the roadmap. I'll share a draft by Friday.
SM
CtrlEnter
Installation
$ pnpm dlx shadcn@latest add "https://editorcn.vercel.app/r/comment-box.json"
Usage
Each callback fires after the change shows on screen, so you can save it to your backend. onPost receives the parent comment's id when the new comment is a reply.
import { CommentBox } from "@/components/templates/comment-box";
export const Comments = ({ comments, user }) => (
<CommentBox
currentUser={{ avatar: user.image, id: user.id, name: user.name }}
initialComments={comments}
onPost={(content, parentId) => saveComment({ content, parentId })}
onReact={(id, emoji) => toggleReaction(id, emoji)}
onDelete={(id) => deleteComment(id)}
/>
);Props
| Prop | Type | Description |
|---|---|---|
currentUser | CommentAuthor | The person writing |
initialComments | CommentItem[] | Comments with optional replies |
onPost | function | Gets (content, parentId?) |
onReact | function | Gets (id, emoji) |
onDelete | function | Gets the deleted comment id |
title | string | Header title, default Comments |
placeholder | string | Composer placeholder |
className | string | Outer container classes |
Simple Document Editor
A document page: a breadcrumb header with collaborators, a floating toolbar, and a paper-style page with a large editable title. The toolbar covers text styles, fonts, text and highlight colors, superscript and subscript, lists with indent and outdent, alignment, and an Insert menu for images, tables, quotes, code blocks and dividers. A status bar shows word count, reading time and keyboard shortcuts.
ATNKLN
Installation
$ pnpm dlx shadcn@latest add "https://editorcn.vercel.app/r/simple-document-editor.json"
The CLI also installs the Image Placeholder and Table extensions.
Usage
import { SimpleDocumentEditor } from "@/components/templates/simple-document-editor";
export const Doc = ({ doc }) => (
<SimpleDocumentEditor
initialTitle={doc.title}
initialContent={doc.content}
onChange={(content) => saveDocument(doc.id, content)}
onTitleChange={(title) => renameDocument(doc.id, title)}
onShare={() => openShareDialog(doc.id)}
/>
);Props
| Prop | Type | Description |
|---|---|---|
initialContent | Content | Tiptap JSON or HTML to start with |
initialTitle | string | Title for the breadcrumb and page |
onChange | function | Gets the document as Tiptap JSON |
onTitleChange | function | Gets the new title |
onShare | function | Shows a Share button when set |
collaborators | DocumentCollaborator[] | Avatars in the header |
path | string[] | Breadcrumb segments before the title |
className | string | Outer container classes |