background-symbol
release-notes-vector
DocsGetting Started

Eddyter documentation

A powerful, configurable rich text editor built on Lexical with AI capabilities and API key authentication.

Last updated:

Compatibility

Eddyter supports React 18.2+ and React 19.x. Works with Next.js, Vite, Create React App, and any React framework.

Getting Started

Integrate Eddyter into your React application in 10 minutes.

React Version Support

Check the compatibility banner above for supported versions. Supports Next.js (App & Pages), Vite, and Webpack based projects.
1

Installation

Install the core package via your preferred manager:

terminal
npm install eddyter

Or with yarn / pnpm:

yarn add eddyter
# or
pnpm add eddyter
2

Style Integration

Import the required CSS in your root file:

app/layout.tsx or App.tsx
import 'eddyter/style.css';

Important

The stylesheet is required for proper rendering of tables, toolbars, and all editor components. Missing styles will cause visual issues.
3

Get your API key

Sign up and get your API key from the dashboard:

  1. Create an account at eddyter.com
  2. Navigate to License Keys in your dashboard
  3. Copy your API key

Free Trial

New accounts get 2 weeks of free premium access with all AI features enabled!
4

Add the editor to your app

Implement the editor with your API key:

components/Editor.tsx
import React from 'react';
import {
  ConfigurableEditorWithAuth,
  EditorProvider,
  defaultEditorConfig
} from 'eddyter';
import 'eddyter/style.css';

export default function Editor() {
  const apiKey = process.env.NEXT_PUBLIC_EDITOR_API_KEY!;

  // Current logged-in user for comments feature
  const currentUser = {
    id: 'user-123',
    name: 'John Doe',
    email: 'john@example.com',
    avatar: 'https://example.com/avatar.jpg' // optional
  };

  const handleContentChange = (html: string) => {
    console.log('Editor content:', html);
    // Save to state, database, etc.
  };

  return (
    <EditorProvider
      defaultFontFamilies={defaultEditorConfig.defaultFontFamilies}
      currentUser={currentUser}
    >
      <ConfigurableEditorWithAuth
        apiKey={apiKey}
        onChange={handleContentChange}
        initialContent="<p>Start writing...</p>"
        mentionUserList={['Alice', 'Bob', 'Charlie']}
        onAuthSuccess={() => console.log('Editor ready!')}
        onAuthError={(error) => console.error('Auth failed:', error)}
      />
    </EditorProvider>
  );
}

Environment Variable

Store your API key in environment variables. Never commit API keys to version control.

Video on Integrating with AI

Authentication

Standard API key verification to enable premium features and AI capabilities.

How it works

  1. Pass your API key to the apiKey prop
  2. The editor validates the key against our server
  3. Features are enabled based on your subscription plan
  4. onAuthSuccess fires when validation succeeds
  5. onAuthError fires if validation fails

Custom verification (optional)

You can provide your own verification function if you need to validate keys through your backend:

components/Editor.tsx
<ConfigurableEditorWithAuth
  apiKey={apiKey}
  customVerifyKey={async (key) => {
    const response = await fetch('/api/verify-editor-key', {
      method: 'POST',
      body: JSON.stringify({ key })
    });
    const data = await response.json();
    return {
      success: data.valid,
      message: data.message
    };
  }}
/>

Features

A comprehensive toolset for modern content creation, from basic formatting to advanced AI generation.

Classic Formatting

Basic Formatting

Bold, italic, underline, strikethrough, subscript, superscript

Text Colors

Text color and background highlight with color picker

Font Controls

20+ font families with adjustable font sizes and line height

Text Alignment

Left, center, right, and justify alignment

Lists and Structure

Bulleted Lists

Custom bullet styles with proper nesting

Numbered Lists

Decimal, alpha, and roman numeral formats

Checklists

Interactive checkboxes with strikethrough

Headings

H1-H6 heading levels

Tables

Table Operations

Insert/delete rows and columns, merge cells

Cell Resizing

Drag to resize columns and rows

Header Styling

Distinct header row styling

Context Menu

Right-click menu for quick actions

Media Support

Images

Drag-drop upload with 8-point resize handles

Videos

YouTube/Vimeo embed with responsive players

File Attachments

Upload and attach downloadable files

Link Management

Insert links with floating editor and preview

AI PowerPremium

Smart Chat

In-editor AI assistant for research, drafting, and creative ideas.

Smart Autocomplete

Predictive text suggestions as you type.

Refinement

Instantly improve tone, fix grammar, or change content length.

Gen-AI Images

Create custom visuals from text prompts inside your document.

Configuration

TailorEvery aspect of the editor to fit your application's specific needs.

Toolbar Configuration

Configure toolbar behavior with the toolbar prop. In sticky mode you can set offset and zIndex. In static mode those values are ignored.

Example: toolbar below a 64 px header
<ConfigurableEditorWithAuth
  apiKey="your-api-key"
  toolbar={{ mode: "sticky", offset: 64, zIndex: 1200 }}
/>

Defaults: { mode: "sticky", offset: 20, zIndex: 1000 }.

In static mode, the editor automatically defaults to amaxHeight of 600px. You only need to pass theeditor prop if you wish to override this default.

Static mode with content scroll
<ConfigurableEditorWithAuth
  apiKey="your-api-key"
  toolbar={{ mode: "static" }}
  // editor={{ maxHeight: 400 }} // Optional: overrides 600px default
/>

Keyboard Shortcuts

Speed up your workflow with standard keyboard shortcuts.

Text Formatting

BoldCtrl/Cmd + B
ItalicCtrl/Cmd + I
UnderlineCtrl/Cmd + U

General

UndoCtrl/Cmd + Z
RedoCtrl/Cmd + Y
Select AllCtrl/Cmd + A
PasteCtrl/Cmd + V

Slash Commands

Type / at the start of a line to access the quick formatting menu.

API Reference

<EditorProvider>

Provides context and configuration for the editor. Must wrap the editor component to enable all features.

PropTypeDescription
childrenReactNodeThe wrapped content.
defaultFontFamiliesstring[]Override default font list.
currentUserCurrentUserUser info for comments.
apiKeystringAPI key for read-only mode.

<ConfigurableEditorWithAuth>

The core editor component with built-in subscription verification and AI service integration.

PropTypeReqDescription
apiKeystringYesYour Eddyter license key. Authenticates the editor against the server and unlocks tier-based features.
initialContentstringNoInitial HTML loaded into the editor on first render.
onChange(html: string) => voidNoCalled ~300 ms after content changes (debounced). Receives the current HTML.
onAuthSuccess() => voidNoFires once the API key is verified and the editor is ready.
onAuthError(error: string) => voidNoFires when API key verification fails. Receives the error message.
customVerifyKey(apiKey: string) => Promise<ApiResponse>NoProvide your own verifier (e.g. proxy through your backend) instead of the default endpoint.
mode"edit" | "preview"NoRender the full editor ("edit", default) or a read-only preview with link previews ("preview").
containerClassNamestringNoClass applied to the outer wrapper container.
contentClassNamestringNoClass applied specifically to the editor's writable content area.
onPreviewClick() => voidNoFires when the user clicks inside preview mode — typically used to switch to edit mode.
darkModeboolean | undefinedNotrue forces dark, false forces light, undefined (default) auto-detects from the host app's <html>/<body> dark class.
toolbar{ mode?: "sticky" | "static"; offset?: number; zIndex?: number }NoToolbar behaviour config. Defaults to { mode: "sticky", offset: 20, zIndex: 1000 }.
editor{ maxHeight?: string | number }NoContainer options. maxHeight only applies when toolbar.mode = "static" — caps the editable area's height.
defaultFontFamiliesstring[]NoOverride the font picker list. Defaults to the 24 fonts in defaultEditorConfig.defaultFontFamilies.
mentionUserListstring[]NoUsernames available to the @mentions autocomplete.
classNamestringNoClass on the outer wrapper element.

Code Examples

Basic Editor

components/BasicEditor.tsx
import { ConfigurableEditorWithAuth, EditorProvider } from 'eddyter';
import 'eddyter/style.css';

export default function BasicEditor() {
  return (
    <EditorProvider>
      <ConfigurableEditorWithAuth
        apiKey="your-api-key"
        onAuthSuccess={() => console.log('Ready!')}
      />
    </EditorProvider>
  );
}

State Management

components/EditorWithState.tsx
import { useState } from 'react';
import { ConfigurableEditorWithAuth, EditorProvider } from 'eddyter';
import 'eddyter/style.css';

export default function EditorWithState() {
  const [content, setContent] = useState('<p>Start writing...</p>');

  return (
    <EditorProvider>
      <ConfigurableEditorWithAuth
        apiKey="your-api-key"
        initialContent={content}
        onChange={setContent}
      />
    </EditorProvider>
  );
}

Layout Recipes

Editor Fit to Page

Create a Notion-style, edge-to-edge layout where the toolbar sticks to the top of the window and the word count floats in the bottom corner. You can achieve this using Tailwind utility classes in containerClassName or standard CSS.

Using containerClassName
<ConfigurableEditorWithAuth
  apiKey="your-api-key"
  toolbar={{ mode: "static" }}
  editor={{ maxHeight: "none" }}
  contentClassName="!bg-transparent !border-none"
  containerClassName="
    [&_.toolbar-content>.toolbar-features]:bg-transparent
    [&_.toolbar-content>.toolbar-comments-feature]:bg-transparent 
    [&_.toolbar-container]:border-b
    [&_.toolbar-container]:border-foreground/10
    [&_.toolbar-container]:bg-background
    [&_.toolbar-container]:sticky
    [&_.toolbar-container]:top-0
    [&_.toolbar-container]:z-50                          
    [&_.editor-area>div]:px-3                          
    [&_.editor-area>.wordCount]:fixed                          
    [&_.editor-area>.wordCount]:bottom-4
    [&_.editor-area>.wordCount]:right-16                      
  "
/>

Theming

FORCE THEME

If your application supports only one theme, use these CSS variables to avoid theme-related issues and ensure consistent rendering. Choose the dark mode CSS for dark-only setups, and the light mode CSS for light-only setups.

dark.css
.eddyter-scope {
        --cteditorf47ac10b-background: 240 6% 10%;
        --cteditorf47ac10b-foreground: 0 0% 100%;
        --cteditorf47ac10b-secondary: 240 7% 15%;
        --cteditorf47ac10b-main-secondary: 0 0% 16.1%;
        --cteditorf47ac10b-body: 240 10% 4%;
        --cteditorf47ac10b-card: 0 0% 14.9%;
        --cteditorf47ac10b-card-foreground: 0 0% 98%;
        --cteditorf47ac10b-popover: 0 0% 14.9%;
        --cteditorf47ac10b-popover-foreground: 0 0% 98%;
        --cteditorf47ac10b-primary: 0 0% 98%;
        --cteditorf47ac10b-primary-foreground: 0 0% 9%;
        --cteditorf47ac10b-secondary-foreground: 0 0% 98%;
        --cteditorf47ac10b-muted: 0 0% 14.9%;
        --cteditorf47ac10b-muted-foreground: 0 0% 63.9%;
        --cteditorf47ac10b-accent: 0 0% 14.9%;
        --cteditorf47ac10b-accent-foreground: 0 0% 98%;
        --cteditorf47ac10b-destructive: 0 62.8% 30.6%;
        --cteditorf47ac10b-destructive-foreground: 0 0% 98%;
        --cteditorf47ac10b-border: 0 0% 14.9%;
        --cteditorf47ac10b-input: 0 0% 14.9%;
        --cteditorf47ac10b-ring: 0 0% 83.1%;
        --cteditorf47ac10b-main-background: 0 0% 12.9%;
        --cteditorf47ac10b-grammar-tooltip-bg: 219 32% 12%;
        --cteditorf47ac10b-suggestion-bg:148 19% 18%;
        --cteditorf47ac10b-suggestion-border:144 100% 62%;
        --cteditorf47ac10b-suggestion-text:144 100% 62%;
        --cteditorf47ac10b-incorrect-word-bg:219 59% 7%;
        --cteditorf47ac10b-incorrect-word-border:4 100% 50%;
        --cteditorf47ac10b-incorrect-word-text:3 100% 80%;
        --cteditorf47ac10b-explanation-bg:230 35% 17%;
        --cteditorf47ac10b-explanation-border:221 83% 53%;
    }

Support & Resources

License

Eddyter is licensed under the MIT License. Security, privacy, and compliance are our core technical principles.

Build Better Together

Our documentation is constantly evolving. If you can't find what you're looking for, feel free to reach out.