Lexical Setup Isn’t What You Think — Here’s the Real Minimal Setup

If you’re trying to set up Lexical for the first time and thought:

“Just install lexical and start typing.”

Wrong. I made that mistake too — and lost hours figuring it out.

So I'm writing this post to help save you time.

Installing lexical alone won’t give you a working editor

Lexical is just the core engine. It handles state and structure behind the scenes, but it doesn’t:

  • Let you type
  • Show any content
  • Handle user input

That’s because it’s immutable by design. It needs extra plugins to actually work like a text editor.

What you really need

To make Lexical work, you must also install one of these:

Type of Editor Package to Install
Plain Text @lexical/plain
Rich Text @lexical/rich-text

These plugins handle the UI and typing behavior for you.

Quick Setup

Install the packages:

npm install lexical @lexical/plain

Then create a simple index.html and editor.js:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Lexical Vanilla Example</title>
    <style>
      #editor {
        border: 1px solid #ccc;
        min-height: 100px;
        padding: 10px;
      }
    </style>
  </head>
  <body>
    <div id="editor" contenteditable="true"></div>

    <script type="module" src="./editor.js"></script>
  </body>
</html>
import { createEditor } from 'lexical';
import { PlainTextPlugin } from '@lexical/plain';

const editorElement = document.getElementById('editor');

// Create the editor
const editor = createEditor();

// Register plain text functionality
editor.registerRootElement(editorElement);

// Add basic typing support (plugin)
PlainTextPlugin({
  editor,
  contentEditable: editorElement,
  placeholder: 'Type something...',
});

Bonus (Solid.js Example)

import { createSignal, onCleanup, onMount } from "solid-js";
import { createEditor } from "lexical";
import { registerRichText } from "@lexical/rich-text";

const editorConfig = {
    namespace: 'editor',
    onError: console.error
}

export default function Editor() {
    let editorRef: HTMLElement | undefined = undefined;
    const editor = createEditor(editorConfig);
    const [editorState, setEditorState] = createSignal();
    registerRichText(editor);

    editor.registerUpdateListener(({ editorState }) => {
        editorState.read(() => {
            setEditorState(editor.getEditorState());
        });
    });

    onMount(() => {
        if (!editorRef) return;
  
        editor.setRootElement(editorRef);

        onCleanup(() => {
            editor.setRootElement(null);
        });
    })

    return (
        <div 
            ref={editorRef}
            contentEditable
        />
    );
}

This is the minimal setup required to integrate Lexical.js using plain JavaScript.

Happy Editing!