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 14 or higher
  • React version 17.0.2 or higher
  • React DOM version 17.0.2 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:
import { useMemo, useState } from 'react';
import YooptaEditor, { createYooptaEditor } from '@yoopta/editor';
import Paragraph from '@yoopta/paragraph';

const plugins = [Paragraph];

export default function MyEditor() {
  const editor = useMemo(() => createYooptaEditor(), []);
  const [value, setValue] = useState();

  const onChange = (newValue) => {
    setValue(newValue);
  };

  return (
    <div style={{ padding: '20px', maxWidth: '900px', margin: '0 auto' }}>
      <YooptaEditor
        editor={editor}
        plugins={plugins}
        value={value}
        onChange={onChange}
        placeholder="Type something..."
      />
    </div>
  );
}
The editor instance should be created with useMemo to avoid recreating it on every render. The value state stores the editor content, and onChange is called whenever the content 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:
import Paragraph from '@yoopta/paragraph';
import Blockquote from '@yoopta/blockquote';
import Headings from '@yoopta/headings';
import Lists from '@yoopta/lists';
import Code from '@yoopta/code';

const plugins = [
  Paragraph,
  Headings.HeadingOne,
  Headings.HeadingTwo,
  Headings.HeadingThree,
  Blockquote,
  Lists.BulletedList,
  Lists.NumberedList,
  Code,
];

export default function MyEditor() {
  // ... rest of the code
}

Step 4: Add UI Components

UI components enhance the editor with toolbars and action menus. All components are available from @yoopta/ui:
npm install @yoopta/ui
import { Toolbar, useToolbar, ActionMenuList, useActionMenuList } from '@yoopta/ui';

export default function MyEditor() {
  const editor = useMemo(() => createYooptaEditor(), []);
  const [value, setValue] = useState();
  const { isOpen: isToolbarOpen, getRootProps: getToolbarProps } = useToolbar();
  const { isOpen: isActionMenuOpen, getRootProps: getActionMenuProps } = useActionMenuList();

  return (
    <div>
      {isToolbarOpen && <Toolbar {...getToolbarProps()} />}
      {isActionMenuOpen && <ActionMenuList {...getActionMenuProps()} />}
      <YooptaEditor
        editor={editor}
        plugins={plugins}
        value={value}
        onChange={setValue}
        placeholder="Start typing..."
      />
    </div>
  );
}

Step 5: Add Text Formatting (Marks)

Marks provide text formatting options like bold, italic, etc.:
npm install @yoopta/marks
import { Bold, Italic, CodeMark, Underline, Strike, Highlight } from '@yoopta/marks';

const MARKS = [Bold, Italic, CodeMark, Underline, Strike, Highlight];

export default function MyEditor() {
  // ... rest of the code

  return (
    <YooptaEditor
      editor={editor}
      plugins={plugins}
      value={value}
      onChange={setValue}
        marks={MARKS}
      placeholder="Start typing..."
    />
  );
}

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 Headings from '@yoopta/headings';
import Blockquote from '@yoopta/blockquote';
import Lists from '@yoopta/lists';
import Code from '@yoopta/code';

// Apply theme to plugins
// CSS is automatically imported - no need to manually import CSS files!
const plugins = applyTheme([
  Paragraph,
  Headings.HeadingOne,
  Headings.HeadingTwo,
  Headings.HeadingThree,
  Blockquote,
  Lists.BulletedList,
  Lists.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 all the features:
import { useMemo, useState } from 'react';
import YooptaEditor, { createYooptaEditor } from '@yoopta/editor';
import Paragraph from '@yoopta/paragraph';
import Blockquote from '@yoopta/blockquote';
import Headings from '@yoopta/headings';
import Lists from '@yoopta/lists';
import Code from '@yoopta/code';
import { Toolbar, useToolbar, ActionMenuList, useActionMenuList } from '@yoopta/ui';
import { Bold, Italic, CodeMark, Underline, Strike, Highlight } from '@yoopta/marks';
import { applyTheme } from '@yoopta/themes-shadcn';
// CSS is automatically imported - no manual import needed!

// Apply theme to plugins
const plugins = applyTheme([
  Paragraph,
  Headings.HeadingOne,
  Headings.HeadingTwo,
  Headings.HeadingThree,
  Blockquote,
  Lists.BulletedList,
  Lists.NumberedList,
  Code,
]);

const MARKS = [Bold, Italic, CodeMark, Underline, Strike, Highlight];

export default function MyEditor() {
  const editor = useMemo(() => createYooptaEditor(), []);
  const [value, setValue] = useState();
  const { isOpen: isToolbarOpen, getRootProps: getToolbarProps } = useToolbar();
  const { isOpen: isActionMenuOpen, getRootProps: getActionMenuProps } = useActionMenuList();

  const onChange = (newValue) => {
    setValue(newValue);
    // Save to database, localStorage, etc.
    console.log('Editor value:', newValue);
  };

  return (
    <div style={{ padding: '20px', maxWidth: '900px', margin: '0 auto' }}>
      {isToolbarOpen && <Toolbar {...getToolbarProps()} />}
      {isActionMenuOpen && <ActionMenuList {...getActionMenuProps()} />}
      <YooptaEditor
        editor={editor}
        plugins={plugins}
        marks={MARKS}
        value={value}
        onChange={onChange}
        placeholder="Start typing..."
        autoFocus
      />
    </div>
  );
}

Understanding the Editor Value

The value prop and onChange callback work with a YooptaContentValue structure:
type YooptaContentValue = Record<string, YooptaBlockData>;

// Example value:
{
  "block-1": {
    id: "block-1",
    type: "Paragraph",
    value: [
      {
        id: "element-1",
        type: "paragraph",
        children: [{ text: "Hello, world!" }]
      }
    ],
    meta: {
      order: 0,
      depth: 0,
      align: "left"
    }
  }
}
You can:
  • Save the value to your backend/database
  • Load existing content by passing it as the value prop
  • Transform the value for export (HTML, Markdown, etc.)

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!