React

    React Rich Text Editor

    Scribe Editor is the lightweight, zero-dependency WYSIWYG editor for React. Under 50KB gzipped, simple useEffect integration, floating toolbar, and full TypeScript support. Works with Next.js, Remix, and Vite out of the box.

    $npm install scribejs-editor
    < 50KB
    Gzipped bundle
    0
    Runtime dependencies
    1 hook
    To integrate

    Why use Scribe in your React app?

    Under 50KB gzipped

    Zero runtime dependencies. No ProseMirror, no Quill core, no extra bloat. Your React bundle stays lean.

    Simple imperative API

    Call editor.bold(), editor.heading(2), editor.link(url). No command strings, no chain API, no schema model.

    Works with Next.js & Remix

    One dynamic import with ssr: false and Scribe is live. No special adapters or hydration hacks needed.

    Built-in XSS sanitization

    Safe paste handling from Word and Google Docs out of the box. No extra sanitization library required.

    Basic React Integration

    Initialize Scribe inside a useEffect and clean up on unmount. No wrappers, no context providers — just a ref and an effect.

    import { useRef, useEffect } from 'react';
    import { Scribe } from 'scribejs-editor';
    import 'scribejs-editor/dist/scribe.css';
    
    export function RichTextEditor({ value, onChange }) {
      const editorRef = useRef(null);
      const instanceRef = useRef(null);
    
      useEffect(() => {
        if (!editorRef.current) return;
    
        instanceRef.current = Scribe.init(editorRef.current, {
          placeholder: 'Start writing...',
          onChange: (html) => onChange?.(html),
        });
    
        return () => instanceRef.current?.destroy();
      }, []);
    
      return <div ref={editorRef} dangerouslySetInnerHTML={{ __html: value }} />;
    }

    Custom Toolbar & Imperative API

    Build your own toolbar by calling editor methods directly. Floating toolbar, fixed toolbar, or no toolbar — your choice.

    import { useRef, useEffect, useCallback } from 'react';
    import { Scribe } from 'scribejs-editor';
    
    export function Editor({ defaultValue, onChange }) {
      const editorRef = useRef(null);
      const instanceRef = useRef(null);
    
      useEffect(() => {
        instanceRef.current = Scribe.init(editorRef.current, {
          toolbar: 'floating',   // or 'fixed' | 'none'
          placeholder: 'Write something...',
          onChange,
        });
        return () => instanceRef.current?.destroy();
      }, []);
    
      // Expose formatting via ref or callback
      const bold   = useCallback(() => instanceRef.current?.bold(), []);
      const italic = useCallback(() => instanceRef.current?.italic(), []);
      const save   = useCallback(() => instanceRef.current?.getHTML(), []);
    
      return (
        <div>
          <div className="toolbar">
            <button onClick={bold}>Bold</button>
            <button onClick={italic}>Italic</button>
            <button onClick={save}>Save</button>
          </div>
          <div ref={editorRef} defaultValue={defaultValue} />
        </div>
      );
    }

    Next.js Integration

    Scribe is DOM-only — use dynamic() with { ssr: false } to skip server rendering.

    // Next.js — disable SSR for the editor component
    import dynamic from 'next/dynamic';
    
    const RichTextEditor = dynamic(
      () => import('@/components/RichTextEditor'),
      { ssr: false }   // Scribe needs the DOM — skip server render
    );
    
    export default function Page() {
      return <RichTextEditor onChange={(html) => console.log(html)} />;
    }

    Everything you need, nothing you don't

    Bold, italic, underline, strikethrough
    Headings H1–H6
    Ordered & unordered lists
    Links with inline editing
    Floating toolbar on selection
    Fixed toolbar mode
    Paste safe from Word & Google Docs
    Built-in XSS sanitization
    Iframe editing support
    Plugin system for extensibility
    Full TypeScript types included
    MIT license — free forever

    Add a rich text editor to React in minutes.

    No license keys. No CDN links. No account. Just npm install scribejs-editor and go.

    React + Scribe — common questions

    What is the best lightweight rich text editor for React?

    Scribe Editor is one of the most lightweight React rich text editors available at under 50KB gzipped with zero runtime dependencies. It integrates with a simple useEffect hook, supports floating and fixed toolbar modes, and works with Next.js (ssr: false), Remix, and Vite.

    How do I add a rich text editor to a React app?

    Install scribejs-editor with npm, create a useEffect that calls Scribe.init(ref.current) on mount and editor.destroy() on unmount. The editor will render a floating toolbar when text is selected and exposes direct methods like editor.bold(), editor.italic(), and editor.getHTML().

    Does Scribe Editor work with Next.js?

    Yes. Since Scribe requires the browser DOM, wrap your editor component in Next.js dynamic() with ssr: false. This prevents the editor from running during server-side rendering and hydrates it correctly on the client.

    Is Scribe Editor a good alternative to Tiptap for React?

    Yes. Scribe is 3x smaller than Tiptap (50KB vs 150KB+), requires no ProseMirror knowledge, and has a simpler API — editor.bold() vs editor.chain().focus().toggleBold().run(). If you don't need custom document schemas or real-time collaboration, Scribe is a better fit for most React apps.