Quick start
Get a working Yoopta Editor up and running in under 5 minutes. This guide will walk you through creating a basic editor with essential plugins and text formatting.
Step 1: Install dependencies
If you haven’t already, install the required packages:
npm install slate slate-react slate-dom @yoopta/editor @yoopta/paragraph @yoopta/headings @yoopta/marks
Step 2: Create your first editor
Create a new file Editor.tsx (or .jsx if not using TypeScript):
import { useMemo } from 'react' ;
import YooptaEditor , { createYooptaEditor , type YooptaContentValue } from '@yoopta/editor' ;
import Paragraph from '@yoopta/paragraph' ;
import Headings from '@yoopta/headings' ;
import { Bold , Italic , Underline , Strike , CodeMark , Highlight } from '@yoopta/marks' ;
const PLUGINS = [
Paragraph ,
Headings . HeadingOne ,
Headings . HeadingTwo ,
Headings . HeadingThree ,
];
const MARKS = [ Bold , Italic , Underline , Strike , CodeMark , Highlight ];
export default function Editor () {
const editor = useMemo (
() => createYooptaEditor ({ plugins: PLUGINS , marks: MARKS }),
[]
);
return (
< YooptaEditor
editor = { editor }
placeholder = "Type / to open menu"
style = { { width: 750 , paddingBottom: 100 } }
onChange = { ( value ) => console . log ( 'Content changed:' , value ) }
/>
);
}
Import dependencies
Import the core editor, plugins you want to use, and text formatting marks.
Define plugins and marks
Create arrays of plugins and marks. Note that Headings exports multiple plugins: HeadingOne, HeadingTwo, HeadingThree.
Create editor instance
Use createYooptaEditor() with your plugins and marks. Wrap it in useMemo() to ensure the editor instance is stable across re-renders.
Render YooptaEditor
Render the <YooptaEditor> component with the editor instance. Add a placeholder and handle content changes with onChange.
Step 3: Test your editor
That’s it! You now have a working editor. Try these interactions:
Type text - Start typing to create paragraphs
Use keyboard shortcuts :
Cmd/Ctrl + B for bold
Cmd/Ctrl + I for italic
Cmd/Ctrl + U for underline
Type / - Opens the slash command menu (more on this below)
Press Enter - Creates a new paragraph
Add more plugins
Let’s enhance the editor with more block types:
import { useMemo } from 'react' ;
import YooptaEditor , { createYooptaEditor } from '@yoopta/editor' ;
import Paragraph from '@yoopta/paragraph' ;
import Headings from '@yoopta/headings' ;
import { NumberedList , BulletedList , TodoList } from '@yoopta/lists' ;
import Blockquote from '@yoopta/blockquote' ;
import Code from '@yoopta/code' ;
import Divider from '@yoopta/divider' ;
import { Bold , Italic , Underline , Strike , CodeMark , Highlight } from '@yoopta/marks' ;
const PLUGINS = [
Paragraph ,
Headings . HeadingOne ,
Headings . HeadingTwo ,
Headings . HeadingThree ,
NumberedList ,
BulletedList ,
TodoList ,
Blockquote ,
Code . Code ,
Divider ,
];
const MARKS = [ Bold , Italic , Underline , Strike , CodeMark , Highlight ];
export default function Editor () {
const editor = useMemo (
() => createYooptaEditor ({ plugins: PLUGINS , marks: MARKS }),
[]
);
return (
< YooptaEditor
editor = { editor }
placeholder = "Type / to open menu"
style = { { width: 750 , paddingBottom: 100 } }
autoFocus
/>
);
}
The Code plugin exports two plugins: Code.Code for code blocks and Code.CodeGroup for grouped code blocks with tabs.
Add UI components
For a complete editing experience, add the floating toolbar and slash menu:
Import UI components
import { FloatingToolbar , SlashCommandMenu } from '@yoopta/ui' ;
Add components as children
UI components must be children of <YooptaEditor> so they can access the editor context.
Here’s the complete example with UI components:
import { useMemo } from 'react' ;
import YooptaEditor , { createYooptaEditor } from '@yoopta/editor' ;
import Paragraph from '@yoopta/paragraph' ;
import Headings from '@yoopta/headings' ;
import { NumberedList , BulletedList , TodoList } from '@yoopta/lists' ;
import Blockquote from '@yoopta/blockquote' ;
import Code from '@yoopta/code' ;
import { Bold , Italic , Underline , Strike , CodeMark , Highlight } from '@yoopta/marks' ;
import { FloatingToolbar , SlashCommandMenu } from '@yoopta/ui' ;
const PLUGINS = [
Paragraph ,
Headings . HeadingOne ,
Headings . HeadingTwo ,
Headings . HeadingThree ,
NumberedList ,
BulletedList ,
TodoList ,
Blockquote ,
Code . Code ,
];
const MARKS = [ Bold , Italic , Underline , Strike , CodeMark , Highlight ];
export default function Editor () {
const editor = useMemo (
() => createYooptaEditor ({ plugins: PLUGINS , marks: MARKS }),
[]
);
return (
< YooptaEditor
editor = { editor }
placeholder = "Type / to open menu"
style = { { width: 750 , paddingBottom: 100 } }
autoFocus
>
< FloatingToolbar />
< SlashCommandMenu />
</ YooptaEditor >
);
}
Apply a theme
By default, Yoopta is headless. For pre-styled blocks, apply a theme:
Install theme package
npm install @yoopta/themes-shadcn
Apply theme to all plugins
import { applyTheme } from '@yoopta/themes-shadcn' ;
const editor = useMemo (
() => createYooptaEditor ({
plugins: applyTheme ( PLUGINS ),
marks: MARKS
}),
[]
);
Complete example with theme:
import { useMemo } from 'react' ;
import YooptaEditor , { createYooptaEditor } from '@yoopta/editor' ;
import Paragraph from '@yoopta/paragraph' ;
import Headings from '@yoopta/headings' ;
import Blockquote from '@yoopta/blockquote' ;
import Callout from '@yoopta/callout' ;
import { Bold , Italic , Underline , Strike , CodeMark , Highlight } from '@yoopta/marks' ;
import { applyTheme } from '@yoopta/themes-shadcn' ;
import { FloatingToolbar , SlashCommandMenu } from '@yoopta/ui' ;
const PLUGINS = [
Paragraph ,
Headings . HeadingOne ,
Headings . HeadingTwo ,
Headings . HeadingThree ,
Blockquote ,
Callout ,
];
const MARKS = [ Bold , Italic , Underline , Strike , CodeMark , Highlight ];
export default function Editor () {
const editor = useMemo (
() => createYooptaEditor ({
plugins: applyTheme ( PLUGINS ),
marks: MARKS
}),
[]
);
return (
< YooptaEditor
editor = { editor }
placeholder = "Type / to open menu"
style = { { width: 750 , paddingBottom: 100 } }
autoFocus
>
< FloatingToolbar />
< SlashCommandMenu />
</ YooptaEditor >
);
}
The applyTheme() function applies styled UI to all supported plugins. You can also apply themes to individual plugins using plugin.extend({ elements: ThemeUI }).
Working with content
Get editor content
Access the editor content in the onChange callback or programmatically:
const onChange = ( value : YooptaContentValue ) => {
// Save to state, localStorage, or send to server
console . log ( 'Content:' , value );
localStorage . setItem ( 'editorContent' , JSON . stringify ( value ));
};
// Or get content programmatically
const content = editor . getEditorValue ();
Set initial content
Provide initial content when creating the editor:
const initialValue = {
// Your content structure
};
const editor = useMemo (
() => createYooptaEditor ({
plugins: PLUGINS ,
marks: MARKS ,
value: initialValue ,
}),
[]
);
// Or set content later
useEffect (() => {
const savedContent = localStorage . getItem ( 'editorContent' );
if ( savedContent ) {
editor . setEditorValue ( JSON . parse ( savedContent ));
}
}, [ editor ]);
Export content
Export editor content to different formats:
// Get as HTML
const html = editor . getHTML ();
// Get as Markdown
const markdown = editor . getMarkdown ();
// Get as plain text
const text = editor . getPlainText ();
For export functionality, install @yoopta/exports: npm install @yoopta/exports
Common use cases
With Next.js
With TypeScript
Read-only mode
'use client' ;
import { useMemo } from 'react' ;
import YooptaEditor , { createYooptaEditor } from '@yoopta/editor' ;
import Paragraph from '@yoopta/paragraph' ;
import Headings from '@yoopta/headings' ;
import { Bold , Italic } from '@yoopta/marks' ;
const PLUGINS = [ Paragraph , Headings . HeadingOne , Headings . HeadingTwo ];
const MARKS = [ Bold , Italic ];
export default function EditorPage () {
const editor = useMemo (
() => createYooptaEditor ({ plugins: PLUGINS , marks: MARKS }),
[]
);
return (
< div className = "max-w-4xl mx-auto py-8" >
< YooptaEditor
editor = { editor }
placeholder = "Start typing..."
style = { { width: '100%' } }
autoFocus
/>
</ div >
);
}
Don’t forget to add 'use client' at the top of your file when using Yoopta Editor in Next.js App Router.
import { useMemo } from 'react' ;
import YooptaEditor , {
createYooptaEditor ,
type YooptaContentValue ,
type YooEditor
} from '@yoopta/editor' ;
import Paragraph from '@yoopta/paragraph' ;
import { Bold , Italic } from '@yoopta/marks' ;
interface EditorProps {
initialValue ?: YooptaContentValue ;
onChange ?: ( value : YooptaContentValue ) => void ;
}
export default function Editor ({ initialValue , onChange } : EditorProps ) {
const editor : YooEditor = useMemo (
() => createYooptaEditor ({
plugins: [ Paragraph ],
marks: [ Bold , Italic ],
value: initialValue ,
}),
[]
);
return (
< YooptaEditor
editor = { editor }
onChange = { onChange }
placeholder = "Type something..."
style = { { width: 750 } }
/>
);
}
import { useMemo , useState } from 'react' ;
import YooptaEditor , { createYooptaEditor } from '@yoopta/editor' ;
import Paragraph from '@yoopta/paragraph' ;
export default function Editor () {
const [ readOnly , setReadOnly ] = useState ( false );
const editor = useMemo (
() => createYooptaEditor ({
plugins: [ Paragraph ],
readOnly ,
}),
[ readOnly ]
);
return (
< div >
< button onClick = { () => setReadOnly ( ! readOnly ) } >
{ readOnly ? 'Edit' : 'Preview' }
</ button >
< YooptaEditor
editor = { editor }
style = { { width: 750 } }
/>
</ div >
);
}
Next steps
You now have a working Yoopta Editor! Here’s what to explore next:
Configuration Learn how to configure plugins and customize behavior
Plugins Explore all available plugins and their options
UI components Add toolbars, menus, and other UI components
API reference Dive into the editor API and programmatic control
Full example
Here’s a complete, production-ready example with all features:
'use client' ;
import { useMemo , useEffect } from 'react' ;
import YooptaEditor , { createYooptaEditor , type YooptaContentValue } from '@yoopta/editor' ;
import Paragraph from '@yoopta/paragraph' ;
import Headings from '@yoopta/headings' ;
import { NumberedList , BulletedList , TodoList } from '@yoopta/lists' ;
import Blockquote from '@yoopta/blockquote' ;
import Callout from '@yoopta/callout' ;
import Code from '@yoopta/code' ;
import Link from '@yoopta/link' ;
import Divider from '@yoopta/divider' ;
import { Bold , Italic , Underline , Strike , CodeMark , Highlight } from '@yoopta/marks' ;
import { applyTheme } from '@yoopta/themes-shadcn' ;
import { FloatingToolbar , SlashCommandMenu , FloatingBlockActions , SelectionBox } from '@yoopta/ui' ;
const PLUGINS = [
Paragraph ,
Headings . HeadingOne ,
Headings . HeadingTwo ,
Headings . HeadingThree ,
NumberedList ,
BulletedList ,
TodoList ,
Blockquote ,
Callout ,
Code . Code ,
Link ,
Divider ,
];
const MARKS = [ Bold , Italic , Underline , Strike , CodeMark , Highlight ];
export default function Editor () {
const editor = useMemo (
() => createYooptaEditor ({
plugins: applyTheme ( PLUGINS ),
marks: MARKS
}),
[]
);
useEffect (() => {
// Load saved content from localStorage
const savedContent = localStorage . getItem ( 'editorContent' );
if ( savedContent ) {
editor . setEditorValue ( JSON . parse ( savedContent ));
}
}, [ editor ]);
const handleChange = ( value : YooptaContentValue ) => {
// Save content to localStorage
localStorage . setItem ( 'editorContent' , JSON . stringify ( value ));
};
return (
< div className = "max-w-4xl mx-auto py-8 px-4" >
< YooptaEditor
editor = { editor }
placeholder = "Type / to open menu, or start typing..."
style = { { width: '100%' , paddingBottom: 100 } }
onChange = { handleChange }
autoFocus
>
< FloatingToolbar />
< SlashCommandMenu />
< FloatingBlockActions />
< SelectionBox />
</ YooptaEditor >
</ div >
);
}
Check out the full-setup example on the Yoopta website to see all features in action, including drag-and-drop, mentions, and more.