Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Tiptap rich text editor for React and Next.js. Use when building or modifying rich text editors, @tiptap extensions, StarterKit, collaboration, comments, Content AI, import/export, or Pro extensions in this monorepo.
.claude/skills/asymmetric-al-tiptap/SKILL.md| Model | Eval pass | Runs |
|---|---|---|
| gemini-3.6-flash | 99% | 106 |
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 73% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 29% | 0% |
| case-02 | ✗→✓ | ▲ Improved | -27% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 9% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 9% | 0% |
Guidance for coding agents working with the Tiptap rich text stack in this repository.
Use this skill when:
packages/ui/components/shadcn/rich-text-editor/@tiptap/* packagesDo not use this skill when:
<textarea> or a different editor)react-component-dev) or App Router structure (use nextjs-app-router)packages/ui/components/shadcn/rich-text-editor/ (editor.tsx, extensions.ts, toolbar.tsx)packages/ui/package.json (@tiptap/react, @tiptap/starter-kit, extensions)@asym/ui (deep imports); do not duplicate editor primitives inside apps/*@tiptap/* in a given workspace should use the same semver line. The root package.json may also list @tiptap/* for app-level usage—keep versions consistent with packages/ui when you touch eitherThis repo standardizes on Bun (bun, bunx). Prefer bunx for one-off CLIs; npx remains valid for the open Skills package manager.
| Purpose | Command | | -------------------------------------------------------------------------- | ------------------------------------------------------- | | Install / refresh the upstream Tiptap agent skill in another workspace | npx skills add ueberdosis/tiptap | | Tiptap project CLI (init, add UI pieces, cloud login) | bunx @tiptap/cli@latest (or npx @tiptap/cli@latest) |
When running Tiptap CLI against this monorepo, set the working directory to the package that owns the editor (packages/ui) unless the CLI docs require the app root.
After changing this canonical skill under docs/ai/skills/tiptap/, run:
bashbun run skills:sync
Then commit updates under .cursor/skills/ and .agents/skills/ so CI (bun run skills:verify) stays green.
@tiptap/* versions in the workspace you modifyStarterKit already includes Link and Underline; configure them through StarterKit.configure(...) before adding standalone extensionspro-extensions guide)immediatelyRender: false on useEditor (already done in editor.tsx; preserve when refactoring)useEditor, EditorContent, extensions)BubbleMenu / FloatingMenu from @tiptap/react/menususeEditor defaults shouldRerenderOnTransaction to false; use useEditorState for toolbars or other UI that depends on selection/active-state changes@tiptap/static-renderer (renderToReactElement / renderToHTMLString) over mounting a read-only useEditor instance per itemIf you need to grep upstream source or docs locally, clone (or update) into a git-ignored folder such as .reference/ (see repo .gitignore):
Do not commit these clones.
When implementing these capabilities, open the matching section in tiptap-docs (local clone or https://tiptap.dev/docs):
collaboration/comments/tracked-changes/conversion/content-ai/collaboration/documents/pages/packages/ui/components/shadcn/rich-text-editor/* and trace how extensions and the toolbar map to the document schemapackages/ui (and align root @tiptap/* if those packages are also used at root)immediatelyRender: false for Next.js client editorsuseEditorState for toolbar / bubble-menu state that depends on editor.isActive(...), editor.can(), or editor.getAttributes(...)@tiptap/static-renderer for read-only rendering unless a live editor instance is explicitly requiredbunx turbo run lint --filter=@asym/ui and bunx turbo run typecheck --filter=@asym/uipackages/ui unless an app-only integration is explicitly required@tiptap/* versions aligned in touched workspacesimmediatelyRender: false where applicable)useEditorState when it must track selection or mark changes@tiptap/static-renderer unless a live editor is truly needed@asym/uireferences/upstream.md — attribution and refresh instructionsimmediatelyRender: false and breaking hydration in the App Router@tiptap/* versions across packages@tiptap/static-renderereditor.isActive() directly in render without useEditorState, causing stale toolbar stateapps/* instead of extending @asym/ui| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | fail→pass | 10,668 | 11,127 | +4% | 1 | 1 | 0% | 2,291 | 3,964 | +73% | 0 | 0 | — |
case-01 | fail→pass | 15,421 | 11,789 | -24% | 1 | 1 | 0% | 3,339 | 4,292 | +29% | 0 | 0 | — |
case-02 | fail→pass | 23,666 | 8,930 | -62% | 1 | 1 | 0% | 4,598 | 3,363 | -27% | 0 | 0 | — |
case-04 | pass→pass | 5,967 | 2,866 | -52% | 1 | 1 | 0% | 859 | 2,140 | +149% | 0 | 0 | — |
case-05 | fail→pass | 13,135 | 4,792 | -64% | 1 | 1 | 0% | 2,218 | 2,420 | +9% | 0 | 0 | — |
case-06 | fail→pass | 8,839 | 2,100 | -76% | 1 | 1 | 0% | 1,722 | 1,880 | +9% | 0 | 0 | — |
case-07 | fail→pass | 9,914 | 5,141 | -48% | 1 | 1 | 0% | 1,838 | 2,532 | +38% | 0 | 0 | — |
case-08 | fail→pass | 4,964 | 1,709 | -66% | 1 | 1 | 0% | 768 | 1,922 | +150% | 0 | 0 | — |
case-09 | fail→pass | 10,824 | 1,635 | -85% | 1 | 1 | 0% | 1,704 | 1,883 | +11% | 0 | 0 | — |
case-10 | fail→pass | 10,748 | 2,227 | -79% | 1 | 1 | 0% | 2,018 | 2,032 | +1% | 0 | 0 | — |
case-11 | pass→pass | 9,889 | 2,774 | -72% | 1 | 1 | 0% | 1,602 | 2,086 | +30% | 0 | 0 | — |
case-12 | pass→pass | 5,531 | 18,690 | +238% | 1 | 1 | 0% | 986 | 2,143 | +117% | 0 | 0 | — |
case-18 | pass→pass | 17,306 | 12,451 | -28% | 1 | 1 | 0% | 3,389 | 4,013 | +18% | 0 | 0 | — |
case-13 | pass→pass | 4,607 | 1,866 | -59% | 1 | 1 | 0% | 543 | 1,865 | +243% | 0 | 0 | — |
case-14 | pass→pass | 7,678 | 4,329 | -44% | 1 | 1 | 0% | 1,523 | 2,501 | +64% | 0 | 0 | — |
case-15 | fail→pass | 9,642 | 6,235 | -35% | 1 | 1 | 0% | 1,705 | 2,710 | +59% | 0 | 0 | — |
case-16 | pass→pass | 12,315 | 7,298 | -41% | 1 | 1 | 0% | 2,439 | 3,082 | +26% | 0 | 0 | — |
case-17 | pass→pass | 14,653 | 12,970 | -11% | 1 | 1 | 0% | 2,972 | 4,197 | +41% | 0 | 0 | — |
case-19 | fail→pass | 11,707 | 4,860 | -58% | 1 | 1 | 0% | 1,989 | 2,462 | +24% | 0 | 0 | — |
case-20 | pass→pass | 7,274 | 2,523 | -65% | 1 | 1 | 0% | 1,177 | 2,057 | +75% | 0 | 0 | — |
case-21 | pass→pass | 4,751 | 1,644 | -65% | 1 | 1 | 0% | 753 | 1,840 | +144% | 0 | 0 | — |
case-22 | pass→pass | 15,049 | 6,676 | -56% | 1 | 1 | 0% | 2,633 | 2,787 | +6% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +50 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.