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

The official eddyter/laravel Composer package wraps @eddyter/core with a Blade component and form binding. Works on Laravel 10–13 with PHP 8.1+. No React, Vite, or Node.js required.

Pick your framework

Getting Started

Plug Eddyter into Laravel with the official eddyter/laravel Composer package. Use the Blade component in server-rendered forms — no React, Vite, or Node.js build step required.

Framework Support

Check the compatibility banner above for supported versions. Mix and match Eddyter across React, the framework-agnostic SDK, Angular, Svelte, Vue, and Laravel.
1

Installation

Install via Composer, then publish the required browser bridge. Laravel auto-discovers the service provider.

terminal
composer require eddyter/laravel
php artisan eddyter:install

Optional config / overwrite:

# Also publish config/eddyter.php
php artisan eddyter:install --config

# Overwrite previously published files
php artisan eddyter:install --force --config
2

Configure the API key

Add your browser API key to .env. If configuration is cached, clear it:

.env
# .env
EDDYTER_API_KEY=your_browser_key

php artisan config:clear

Production note

Add @eddyterStyles in <head>, and @eddyterScripts before </body>. The combined @eddyterAssets directive remains available when separate placement is not possible.
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 a form

Implement the editor with your API key:

resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    @eddyterStyles
</head>
<body>
    @yield('content')

    @eddyterScripts
</body>
</html>

{{-- resources/views/posts/create.blade.php --}}
<form method="POST" action="{{ route('posts.store') }}">
    @csrf

    <label for="title">Title</label>
    <input type="text" name="title" value="{{ old('title') }}">

    <label for="body">Body</label>
    <x-eddyter name="body" :value="old('body')" height="500px" />

    <button type="submit">Save</button>
</form>

Environment Variable

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

Sanitize submitted HTML

The Laravel package transports editor HTML but does not sanitize it. Apply your application's HTML allowlist or sanitizer before storing or rendering untrusted content.

Video on Integrating with AI

Authentication

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

How it works

  1. Set EDDYTER_API_KEY in .env. The Blade component reads it from config('eddyter.api_key') by default. Override per-instance with the api-key prop. The browser key is intentionally sent to the client and Eddyter validates it automatically; no verification route is required by default.
  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:

resources/views/posts/create.blade.php
<x-eddyter
    name="body"
    verify-key-url="{{ route('eddyter.verify') }}"
/>

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

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

Toolbar Configuration

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

resources/views/posts/create.blade.php
<x-eddyter
    name="body"
    :toolbar="['mode' => 'sticky', 'offset' => 64, 'zIndex' => 1200]"
/>

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

In static mode, the editor automatically defaults to a maxHeight of 600px. You only need to pass the editor option if you wish to override this default.

resources/views/posts/create.blade.php
<x-eddyter
    name="body"
    :toolbar="['mode' => 'static']"
    :editor-options="['maxHeight' => '420px']"
/>

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 by simply passing the fitToPage={true} prop. The editor will handle all layout defaults automatically.

Example Usage
Component.tsx
<ConfigurableEditorWithAuth
  apiKey="your-api-key"
  fitToPage={true}
/>

Theming

FORCE THEME

By default, Eddyter automatically detects the host application's theme. If you want to force a specific theme (regardless of the user's system or application settings), you can use the darkMode prop:

Force Dark Mode

ForceDark.tsx
<ConfigurableEditorWithAuth
  apiKey="your-api-key"
  darkMode={true}
/>

Force Light Mode

ForceLight.tsx
<ConfigurableEditorWithAuth
  apiKey="your-api-key"
  darkMode={false}
/>

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.