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.
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
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.
Also compare Scribe with:
Use Scribe in your framework: