Skip to main content
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:
npm install @yoopta/ui
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!