This guide will walk you through creating your first Yoopta Editor with a few plugins and tools.
Prerequisites
Before you begin, make sure you have:
- Node.js version 18 or higher
- React version 18 or higher
- React DOM version 18 or higher
Step 1: Installation
Install the core editor and required dependencies:
npm install slate slate-react slate-dom @yoopta/editor @yoopta/paragraph
slate and slate-react are peer dependencies required by Yoopta Editor.
Step 2: Basic Editor
Create a simple editor component. The editor is created with createYooptaEditor({ plugins, marks });
import { useMemo, useEffect } from 'react';
import YooptaEditor, { createYooptaEditor } from '@yoopta/editor';
import Paragraph from '@yoopta/paragraph';
import { Bold, Italic, Underline } from '@yoopta/marks';
const plugins = [Paragraph];
const marks = [Bold, Italic, Underline];
export default function MyEditor() {
const editor = useMemo(() => createYooptaEditor({ plugins, marks }), []);
useEffect(() => {
// Set initial content (or load from API/localStorage)
editor.setEditorValue({});
}, [editor]);
const onChange = (value) => {
// Save to backend, localStorage, etc.
console.log('Content:', value);
};
return (
<div style={{ padding: '20px', maxWidth: '900px', margin: '0 auto' }}>
<YooptaEditor editor={editor} onChange={onChange} placeholder="Type something..." />
</div>
);
}
The editor instance should be created with useMemo so it is not recreated on every render.
Plugins and marks are passed to createYooptaEditor, not to YooptaEditor. Use
editor.setEditorValue() for initial or loaded content and onChange to react to changes.
Step 3: Add More Plugins
Install additional plugins for richer content:
npm install @yoopta/blockquote @yoopta/headings @yoopta/lists @yoopta/code
Update your editor — pass the extended plugin list to createYooptaEditor:
import Paragraph from '@yoopta/paragraph';
import Blockquote from '@yoopta/blockquote';
import { HeadingOne, HeadingTwo, HeadingThree } from '@yoopta/headings';
import { BulletedList, NumberedList, TodoList } from '@yoopta/lists';
import Code from '@yoopta/code';
const plugins = [
Paragraph,
HeadingOne,
HeadingTwo,
HeadingThree,
Blockquote,
BulletedList,
NumberedList,
TodoList,
Code,
];
export default function MyEditor() {
const editor = useMemo(() => createYooptaEditor({ plugins, marks }), []);
// ...
}
Step 4: Add UI Components
UI components (toolbar, slash menu, floating block actions) are added as children of YooptaEditor. Install @yoopta/ui and use the compound components:
import { FloatingToolbar, FloatingBlockActions, SlashCommandMenu } from '@yoopta/ui';
export default function MyEditor() {
const editor = useMemo(() => createYooptaEditor({ plugins, marks }), []);
return (
<div style={{ padding: '20px', maxWidth: '900px', margin: '0 auto' }}>
<YooptaEditor
editor={editor}
onChange={(value) => console.log(value)}
placeholder="Type / to open menu...">
<FloatingToolbar />
<FloatingBlockActions />
<SlashCommandMenu />
</YooptaEditor>
</div>
);
}
For drag-and-drop reordering, wrap with BlockDndContext and use renderBlock with SortableBlock. See UI overview and Block DnD for details.
Step 5: Add Text Formatting (Marks)
Marks provide text formatting (bold, italic, etc.). Pass them to createYooptaEditor:
npm install @yoopta/marks
import { Bold, Italic, CodeMark, Underline, Strike, Highlight } from '@yoopta/marks';
const marks = [Bold, Italic, CodeMark, Underline, Strike, Highlight];
const editor = useMemo(() => createYooptaEditor({ plugins, marks }), []);
The toolbar (e.g. FloatingToolbar) uses these marks for formatting. No need to pass marks to YooptaEditor.
Step 6: Apply a Theme (Optional)
For a beautiful, ready-made design, apply a theme:
npm install @yoopta/themes-shadcn
import { applyTheme } from '@yoopta/themes-shadcn';
import Paragraph from '@yoopta/paragraph';
import { HeadingOne, HeadingTwo, HeadingThree } from '@yoopta/headings';
import Blockquote from '@yoopta/blockquote';
import { BulletedList, NumberedList } from '@yoopta/lists';
import Code from '@yoopta/code';
// Apply theme to plugins; CSS is imported automatically
const plugins = applyTheme([
Paragraph,
HeadingOne,
HeadingTwo,
HeadingThree,
Blockquote,
BulletedList,
NumberedList,
Code,
]);
Themes automatically apply styled components to your plugins. CSS styles are automatically imported when you import the theme package, so you don’t need to manually import any CSS files.You can still customize individual elements if needed.
Complete Example
Here’s a complete editor with plugins, marks, theme, and UI components:
import { useMemo, useEffect } from 'react';
import YooptaEditor, { createYooptaEditor } from '@yoopta/editor';
import Paragraph from '@yoopta/paragraph';
import Blockquote from '@yoopta/blockquote';
import { HeadingOne, HeadingTwo, HeadingThree } from '@yoopta/headings';
import { BulletedList, NumberedList } from '@yoopta/lists';
import Code from '@yoopta/code';
import { FloatingToolbar, FloatingBlockActions, SlashCommandMenu } from '@yoopta/ui';
import { Bold, Italic, CodeMark, Underline, Strike, Highlight } from '@yoopta/marks';
import { applyTheme } from '@yoopta/themes-shadcn';
const plugins = applyTheme([
Paragraph,
HeadingOne,
HeadingTwo,
HeadingThree,
Blockquote,
BulletedList,
NumberedList,
Code,
]);
const marks = [Bold, Italic, CodeMark, Underline, Strike, Highlight];
export default function MyEditor() {
const editor = useMemo(() => createYooptaEditor({ plugins, marks }), []);
useEffect(() => {
// Load initial content (or leave empty)
editor.setEditorValue({});
}, [editor]);
const onChange = (value) => {
// Save to database, localStorage, etc.
console.log('Editor value:', value);
};
return (
<div style={{ padding: '20px', maxWidth: '900px', margin: '0 auto' }}>
<YooptaEditor
editor={editor}
onChange={onChange}
placeholder="Type / to open menu..."
autoFocus>
<FloatingToolbar />
<FloatingBlockActions />
<SlashCommandMenu />
</YooptaEditor>
</div>
);
}
Understanding the Editor Value
Content is managed via the editor instance. Use editor.getEditorValue() to read and editor.setEditorValue(data) to set content. The onChange callback receives the same YooptaContentValue when the user edits:
type YooptaContentValue = Record<string, YooptaBlockData>;
// Example value (from getEditorValue() or onChange):
{
"block-1": {
id: "block-1",
type: "Paragraph",
value: [
{
id: "element-1",
type: "paragraph",
children: [{ text: "Hello, world!" }],
props: { nodeType: "block" }
}
],
meta: { order: 0, depth: 0, align: "left" }
}
}
You can:
- Save — in
onChange, persist the value to your backend or localStorage
- Load — in
useEffect, call editor.setEditorValue(data) with loaded content
- Export — use
editor.getHTML(value), editor.getMarkdown(value), editor.getPlainText(value) for different formats
Keyboard Shortcuts
Yoopta Editor comes with built-in keyboard shortcuts:
/ - Open slash command menu (block insertion)
Cmd/Ctrl + B - Bold text
Cmd/Ctrl + I - Italic text
Cmd/Ctrl + U - Underline text
Cmd/Ctrl + K - Insert link
Tab - Increase block indent
Shift + Tab - Decrease block indent
Backspace - Delete selected blocks
Cmd/Ctrl + A - Select all blocks
Next Steps
Check out our live examples to see what’s possible with Yoopta
Editor!