How to Integrate Yoopta Editor into Your Next.js or React Application
Sh Raj

Sh Raj @sh20raj

About: IamSh

Location:
🔆💖 INDIA💖🔆
Joined:
Jan 9, 2022

How to Integrate Yoopta Editor into Your Next.js or React Application

Publish Date: May 25
5 0

How to Integrate Yoopta Editor into Your Next.js or React Application

Introduction

Sample Repo - https://github.com/SH20RAJ/yoopta-editor-example/tree/74df92fbbb7a9b2c2fb01eabda5f7ff9befcebe4

Rich text editors are an essential part of modern web applications, allowing users to create and edit content with formatted text, images, videos, and other interactive elements. In this tutorial, I'll walk you through integrating the powerful Yoopta editor into your Next.js or React application.

Yoopta is a flexible, customizable rich text editor that provides a variety of plugins for different content types. It's built on the Slate.js framework and offers a great developer experience with its modular architecture.

Prerequisites

  • Basic knowledge of React or Next.js
  • Node.js and npm installed on your machine
  • An existing React or Next.js project

Step 1: Install Core Dependencies

First, let's install the core Yoopta dependencies:

# For React applications
npm install --save --legacy-peer-deps @yoopta/editor slate slate-react

# For Next.js applications with App Router
npm install --save --legacy-peer-deps @yoopta/editor slate@0.102.0 slate-react@0.102.0
Enter fullscreen mode Exit fullscreen mode

Note: For Next.js applications, especially those using the App Router, it's important to use specific versions of slate (0.102.0) and slate-react (0.102.0) to avoid compatibility issues.

Step 2: Install Yoopta Plugins

Yoopta's strength lies in its plugin system. Here's how to install the most commonly used plugins:

npm install --save --legacy-peer-deps \
  @yoopta/paragraph \
  @yoopta/headings \
  @yoopta/blockquote \
  @yoopta/lists \
  @yoopta/image \
  @yoopta/link \
  @yoopta/table \
  @yoopta/code \
  @yoopta/marks \
  @yoopta/divider \
  @yoopta/toolbar \
  @yoopta/action-menu-list
Enter fullscreen mode Exit fullscreen mode

Each plugin adds specific functionality to your editor:

  • paragraph: Basic paragraph formatting
  • headings: Multiple heading levels
  • blockquote: Quote formatting
  • lists: Ordered, unordered, and todo lists
  • image: Image uploads and display
  • link: Hyperlink creation and editing
  • table: Table creation and editing
  • code: Code block formatting
  • marks: Text formatting (bold, italic, etc.)
  • divider: Horizontal dividers
  • toolbar: Floating formatting toolbar
  • action-menu-list: Action menu for inserting content blocks

Step 3: Create the Basic Editor Component

For a Next.js application using the App Router, make sure to add the 'use client' directive at the top of your component file.

Here's a minimal setup for Yoopta Editor:

'use client'; // Only needed for Next.js App Router

import YooptaEditor, { createYooptaEditor } from '@yoopta/editor';
import { useMemo } from 'react';

// Import plugins
import Paragraph from '@yoopta/paragraph';

function SimpleEditor() {
  // Create the editor instance
  const editor = useMemo(() => createYooptaEditor(), []);

  return (
    <div className="editor-container">
      <YooptaEditor
        editor={editor}
        plugins={[Paragraph]}
        defaultValue={[
          {
            type: 'paragraph',
            children: [{ text: 'Start typing here...' }],
          },
        ]}
      />
    </div>
  );
}

export default SimpleEditor;
Enter fullscreen mode Exit fullscreen mode

Step 4: Configure Multiple Plugins

Let's enhance our editor with more plugins:

import YooptaEditor, { createYooptaEditor } from '@yoopta/editor';
import { useMemo, useState } from 'react';

// Import plugins
import Paragraph from '@yoopta/paragraph';
import { HeadingOne, HeadingTwo, HeadingThree } from '@yoopta/headings';
import Blockquote from '@yoopta/blockquote';
import { NumberedList, BulletedList, TodoList } from '@yoopta/lists';
import { Bold, Italic, Underline, Strike, Highlight } from '@yoopta/marks';
import Table from '@yoopta/table';
import Code from '@yoopta/code';
import Divider from '@yoopta/divider';
import Link from '@yoopta/link';

// Define the plugins array
const plugins = [
  Paragraph,
  HeadingOne,
  HeadingTwo,
  HeadingThree,
  Blockquote,
  NumberedList,
  BulletedList,
  TodoList,
  Code,
  Table,
  Link,
  Divider,
];

// Define the text formatting marks
const MARKS = [Bold, Italic, Underline, Strike, Highlight];

function EnhancedEditor() {
  const [value, setValue] = useState([
    {
      type: 'paragraph',
      children: [{ text: 'Start writing with Yoopta Editor!' }],
    },
  ]);

  const editor = useMemo(() => createYooptaEditor(), []);

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

  return (
    <div className="editor-container">
      <YooptaEditor
        editor={editor}
        plugins={plugins}
        marks={MARKS}
        value={value}
        onChange={onChange}
        autoFocus
      />
    </div>
  );
}

export default EnhancedEditor;
Enter fullscreen mode Exit fullscreen mode

Step 5: Add Toolbar and Action Menu

To allow users to easily format text and insert content blocks, let's add the toolbar and action menu:

import ActionMenuList, { DefaultActionMenuRender } from '@yoopta/action-menu-list';
import Toolbar, { DefaultToolbarRender } from '@yoopta/toolbar';
import LinkTool, { DefaultLinkToolRender } from '@yoopta/link-tool';

// Define tools configuration
const TOOLS = {
  ActionMenu: {
    render: DefaultActionMenuRender,
    tool: ActionMenuList,
  },
  Toolbar: {
    render: DefaultToolbarRender,
    tool: Toolbar,
  },
  LinkTool: {
    render: DefaultLinkToolRender,
    tool: LinkTool,
  },
};

function EditorWithTools() {
  // ...existing code...

  return (
    <div className="editor-container" ref={containerRef}>
      <YooptaEditor
        editor={editor}
        plugins={plugins}
        tools={TOOLS}
        marks={MARKS}
        selectionBoxRoot={containerRef}
        value={value}
        onChange={onChange}
        autoFocus
      />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 6: Add Image and File Upload Support

To handle file uploads, you'll need to extend the image and file plugins with upload handlers:

import Image from '@yoopta/image';
import Video from '@yoopta/video';
import File from '@yoopta/file';

// Define plugins with upload capabilities
const plugins = [
  // ...other plugins,
  Image.extend({
    options: {
      async onUpload(file) {
        // Replace with your actual upload logic
        const data = await uploadToServer(file, 'image');
        return {
          src: data.url,
          alt: 'Image description',
          sizes: {
            width: data.width,
            height: data.height,
          },
        };
      },
    },
  }),
  Video.extend({
    options: {
      onUpload: async (file) => {
        const data = await uploadToServer(file, 'video');
        return {
          src: data.url,
          alt: 'Video description',
          sizes: {
            width: data.width, 
            height: data.height,
          },
        };
      },
      onUploadPoster: async (file) => {
        const image = await uploadToServer(file, 'image');
        return image.url;
      },
    },
  }),
  File.extend({
    options: {
      onUpload: async (file) => {
        const response = await uploadToServer(file, 'file');
        return { 
          src: response.url, 
          format: response.format, 
          name: response.name, 
          size: response.size 
        };
      },
    },
  }),
];

// Example upload function using FormData
async function uploadToServer(file, resourceType) {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('resource_type', resourceType);

  const response = await fetch('/api/upload', {
    method: 'POST',
    body: formData,
  });

  if (!response.ok) {
    throw new Error('Upload failed');
  }

  return response.json();
}
Enter fullscreen mode Exit fullscreen mode

Step 7: Create a Complete Editor Setup

Let's put everything together to create a complete Yoopta Editor implementation:

'use client';

import YooptaEditor, { createYooptaEditor } from '@yoopta/editor';
import { useMemo, useRef, useState } from 'react';

// Import all plugins
import Paragraph from '@yoopta/paragraph';
import { HeadingOne, HeadingTwo, HeadingThree } from '@yoopta/headings';
import Blockquote from '@yoopta/blockquote';
import { NumberedList, BulletedList, TodoList } from '@yoopta/lists';
import { Bold, Italic, CodeMark, Underline, Strike, Highlight } from '@yoopta/marks';
import Table from '@yoopta/table';
import Code from '@yoopta/code';
import Divider from '@yoopta/divider';
import Link from '@yoopta/link';
import Image from '@yoopta/image';
import Video from '@yoopta/video';
import File from '@yoopta/file';
import ActionMenuList, { DefaultActionMenuRender } from '@yoopta/action-menu-list';
import Toolbar, { DefaultToolbarRender } from '@yoopta/toolbar';
import LinkTool, { DefaultLinkToolRender } from '@yoopta/link-tool';

// Define plugins
const plugins = [
  Paragraph,
  Table,
  Divider,
  HeadingOne,
  HeadingTwo,
  HeadingThree,
  Blockquote,
  NumberedList,
  BulletedList,
  TodoList,
  Code,
  Link,
  Image.extend({
    options: {
      async onUpload(file) {
        // Your upload implementation
        const data = await uploadToServer(file, 'image');
        return {
          src: data.url,
          alt: 'Uploaded image',
          sizes: {
            width: data.width,
            height: data.height,
          },
        };
      },
    },
  }),
  Video.extend({
    options: {
      // Video upload implementation
    },
  }),
  File.extend({
    options: {
      // File upload implementation
    },
  }),
];

// Define tools
const TOOLS = {
  ActionMenu: {
    render: DefaultActionMenuRender,
    tool: ActionMenuList,
  },
  Toolbar: {
    render: DefaultToolbarRender,
    tool: Toolbar,
  },
  LinkTool: {
    render: DefaultLinkToolRender,
    tool: LinkTool,
  },
};

// Define text marks
const MARKS = [Bold, Italic, CodeMark, Underline, Strike, Highlight];

function YooptaEditorComponent() {
  // Initial content value
  const [value, setValue] = useState([
    {
      type: 'paragraph',
      children: [{ text: 'Welcome to Yoopta Editor!' }],
    },
  ]);

  const editor = useMemo(() => createYooptaEditor(), []);
  const selectionRef = useRef(null);

  const onChange = (newValue) => {
    setValue(newValue);
    // You can save the content to your backend or local storage here
  };

  return (
    <div 
      className="editor-container"
      ref={selectionRef}
    >
      <YooptaEditor
        editor={editor}
        plugins={plugins}
        tools={TOOLS}
        marks={MARKS}
        selectionBoxRoot={selectionRef}
        value={value}
        onChange={onChange}
        autoFocus
      />
    </div>
  );
}

export default YooptaEditorComponent;
Enter fullscreen mode Exit fullscreen mode

Step 8: Add Some Basic Styling

Yoopta Editor comes with default minimal styling, but you might want to add some custom styles:

/* Add to your CSS file */
.editor-container {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  min-height: 300px;
  background-color: white;
}

.yoopta-editor {
  /* Additional editor styling */
  line-height: 1.6;
  font-size: 16px;
}
Enter fullscreen mode Exit fullscreen mode

Step 9: Persisting Content

To save the editor content, you can use the onChange callback to store the content in a database or localStorage:

function YooptaEditorWithPersistence() {
  // Load initial content from localStorage or use default
  const initialValue = useMemo(() => {
    if (typeof window !== 'undefined') {
      const savedContent = localStorage.getItem('editorContent');
      if (savedContent) {
        try {
          return JSON.parse(savedContent);
        } catch (e) {
          console.error('Failed to parse saved content', e);
        }
      }
    }
    return [
      {
        type: 'paragraph',
        children: [{ text: 'Start writing here...' }],
      },
    ];
  }, []);

  const [value, setValue] = useState(initialValue);

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

    // Save to localStorage
    if (typeof window !== 'undefined') {
      localStorage.setItem('editorContent', JSON.stringify(newValue));
    }

    // Or save to a backend API
    // saveContentToBackend(newValue);
  };

  // ...remaining editor setup
}
Enter fullscreen mode Exit fullscreen mode

Advanced Configuration

Custom Toolbar Items

You can customize the toolbar by creating custom toolbar renders:

const CustomToolbarRender = (props) => {
  const { tools, editorRef } = props;

  return (
    <div className="custom-toolbar">
      {/* Your custom toolbar UI */}
      {tools.map((tool) => (
        <button 
          key={tool.id}
          onClick={() => tool.action(editorRef)}
        >
          {tool.icon}
        </button>
      ))}
    </div>
  );
};

const TOOLS = {
  // ...
  Toolbar: {
    render: CustomToolbarRender,
    tool: Toolbar,
  },
  // ...
};
Enter fullscreen mode Exit fullscreen mode

Custom Plugin Styling

You can extend plugins to customize their appearance:

const plugins = [
  // ...
  Divider.extend({
    elementProps: {
      divider: (props) => ({
        ...props,
        color: '#007aff',
        height: '2px',
      }),
    },
  }),
  // ...
];
Enter fullscreen mode Exit fullscreen mode

Conclusion

Integrating Yoopta Editor into your Next.js or React application provides a powerful content editing experience with minimal effort. The modular architecture allows you to include only the features you need and customize them to match your application's requirements.

With this setup, you can create everything from simple note-taking applications to complex content management systems with rich media support.

For more detailed information, be sure to check out the Yoopta Editor documentation.

Remember to handle file uploads securely and consider implementing proper data validation both on the client and server sides to ensure your editor implementation remains secure.

📚 Additional Resources
Official Documentation: https://yoopta.dev/

GitHub Repository: https://github.com/yoopta-editor/Yoopta-Editor

Live Examples: https://yoopta-editor.vercel.app/examples/withBaseFullSetup

Editor Source Code: https://github.com/yoopta-editor/Yoopta-Editor/blob/master/web/next-example/src/components/examples/withBaseFullSetup/index.tsx

Happy coding!


This article was generated on May 25, 2025, based on Yoopta Editor version 4.9.7.

Comments 0 total

    Add comment