editorcn packages are available as a shadcn registry, allowing you to install the source code directly into your project using the shadcn CLI. This is the recommended way to install editorcn packages — it copies the editor source straight into your project so you have full control over styling and behavior, rather than depending on a published node_modules package.
If you'd rather install from npm instead, see npm vs registry below for the tradeoffs.
Setup
Add the editorcn registry to your components.json:
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"registries": {
"@editorcn": "https://editorcn.vercel.app/r/{name}.json"
}
}Available packages
| Package | Command |
|---|---|
| @editorcn/editor | npx shadcn@latest add @editorcn/editor |
| @editorcn/block-editor | npx shadcn@latest add @editorcn/block-editor |
Usage
After installation, the editor source files are in your project at components/editor/ (or components/block-editor/ for the block editor).
1. Import styles
Import the editor styles alongside your shadcn globals:
// Your shadcn globals
import "@/app/globals.css";
// Editor component styles
import "@/components/editor/style.css";For the block editor:
import "@/components/block-editor/style.css";2. Install peer dependencies
The @tiptap/* packages are peer dependencies. The shadcn CLI will prompt you to install any it detects as missing, but you can also add them yourself:
$ pnpm add @tiptap/react @tiptap/pm @tiptap/starter-kit @tiptap/extension-link @tiptap/extension-underline
See the Editor or Block Editor docs for the full list of extensions.
3. Use the components
Rich text editor:
"use client";
import { useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Placeholder from "@tiptap/extension-placeholder";
import { RichTextEditor, Link } from "@/components/editor";
function MyEditor() {
const editor = useEditor({
immediatelyRender: false,
extensions: [
StarterKit,
Link,
Placeholder.configure({ placeholder: "Start typing..." }),
],
});
return (
<RichTextEditor editor={editor}>
<RichTextEditor.Toolbar sticky>
<RichTextEditor.ControlsGroup>
<RichTextEditor.Bold />
<RichTextEditor.Italic />
<RichTextEditor.Underline />
</RichTextEditor.ControlsGroup>
</RichTextEditor.Toolbar>
<RichTextEditor.Content />
</RichTextEditor>
);
}Block editor:
"use client";
import { useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Placeholder from "@tiptap/extension-placeholder";
import {
BlockEditor,
SlashCommand,
defaultSlashCommandItems,
getSlashCommandSuggestion,
} from "@/components/block-editor";
function MyBlockEditor() {
const editor = useEditor({
immediatelyRender: false,
extensions: [
StarterKit.configure({ heading: { levels: [1, 2, 3] } }),
Placeholder.configure({ placeholder: "Type / for commands..." }),
SlashCommand.configure({
suggestion: getSlashCommandSuggestion(defaultSlashCommandItems),
}),
],
});
return <BlockEditor editor={editor} />;
}For the full API reference, props, and customization options, see the Editor and Block Editor pages.
How it works
The registry is served as static JSON files from https://editorcn.vercel.app/r/:
registry.json— catalog listing all available packages with metadataeditor.json— item schema for the toolbar editor (42 files, 21 dependencies)block-editor.json— item schema for the block editor (38 files, 29 dependencies)
When you run shadcn add @editorcn/editor, the CLI:
- Fetches
https://editorcn.vercel.app/r/editor.json - Reads the
filesarray to know which source files to install - Copies each file's
contentinto your project at the configured paths - Installs all
dependenciesinto your project
npm vs registry
| npm | Registry (recommended) | |
|---|---|---|
| Install location | node_modules | Your project source |
| Customizable | No (published dist) | Yes (edit the source) |
| Versioning | Semver via npm | Latest from source |
| Peer dependency handling | Manual install | CLI prompts for missing ones |
| Use case | Quick setup, no source edits needed | Full control over styling and behavior |
Use the registry unless you have a specific reason to prefer a versioned npm dependency (for example, pinning to an exact release in a monorepo with strict dependency management).
Source
The registry is built from the same source as the npm packages. See scripts/build-registry.mjs for the build script.