Quick Start
A working Typix editor in three files
This guide gets you to a working editor with toolbar in under five minutes, using the v2 API.
What you'll build
A React component that:
- Mounts a Lexical-powered editor via
useTypixEditor - Shares the editor instance through
TypixEditorContext.Provider - Renders the editable surface with
<EditorContent> - Uses shipped toolbar buttons vendored into
components/typix/main/via the CLI (no hand-rollededitor.toggleBold()wiring)
Prereqs
- A React 18 or 19 project (Next.js, Vite, Remix, etc.)
- Packages from Installation
- Vendored design-system CSS imported in your
globals.css(see Installation)
Create the editor component
"use client";
import {
EditorContent,
TypixEditorContext,
defaultTheme,
useTypixEditor,
} from "@typix-editor/react";
import { StarterKit } from "@typix-editor/extension-starter-kit";
const extensions = [StarterKit()];
export function Editor() {
const editor = useTypixEditor({
extensions,
theme: defaultTheme,
namespace: "my-editor",
});
return (
<TypixEditorContext.Provider value={{ editor }}>
<EditorContent
editor={editor}
placeholder="Start typing…"
className="prose max-w-none p-6"
/>
</TypixEditorContext.Provider>
);
}"use client" is required. useTypixEditor calls into Lexical
which needs the DOM. Server Components can't run it.
Mount it on a page
import { Editor } from "@/components/editor";
export default function Page() {
return (
<main className="mx-auto max-w-3xl py-10">
<Editor />
</main>
);
}That's it — refresh your dev server and you have a working editor with
text, headings, lists, links, and history (everything StarterKit ships).
Add a toolbar
The simplest toolbar uses shipped components vendored into
components/typix/main/. They read editor state from context — no manual
editor.chain().toggleBold() wiring needed.
First vendor the buttons + toolbar primitive:
npx typix ui add toolbar undo-redo-button heading-button blockquote-button \
code-block-button list-dropdown-menu mark-buttonThen build the toolbar:
"use client";
import {
Toolbar,
ToolbarGroup,
ToolbarSeparator,
} from "@/components/typix/primitives/toolbar";
import { UndoRedoButton } from "@/components/typix/main/undo-redo-button";
import { HeadingButton } from "@/components/typix/main/heading-button";
import { BlockquoteButton } from "@/components/typix/main/blockquote-button";
import { CodeBlockButton } from "@/components/typix/main/code-block-button";
import { ListDropdownMenu } from "@/components/typix/main/list-dropdown-menu";
import { MarkButton } from "@/components/typix/main/mark-button";
export function EditorToolbar() {
return (
<Toolbar className="flex-wrap border-b px-2 py-1">
<ToolbarGroup>
<UndoRedoButton action="undo" />
<UndoRedoButton action="redo" />
</ToolbarGroup>
<ToolbarSeparator className="mx-1 h-5 w-px" />
<ToolbarGroup>
<HeadingButton level={1} />
<HeadingButton level={2} />
<BlockquoteButton />
<CodeBlockButton />
</ToolbarGroup>
<ToolbarSeparator className="mx-1 h-5 w-px" />
<ToolbarGroup>
<ListDropdownMenu />
</ToolbarGroup>
<ToolbarSeparator className="mx-1 h-5 w-px" />
<ToolbarGroup>
<MarkButton type="bold" />
<MarkButton type="italic" />
<MarkButton type="underline" />
<MarkButton type="strike" />
<MarkButton type="code" />
</ToolbarGroup>
</Toolbar>
);
}Drop it inside the provider:
"use client";
import { EditorToolbar } from "./toolbar";
// …imports as before
export function Editor() {
const editor = useTypixEditor({
extensions,
theme: defaultTheme,
namespace: "my-editor",
});
return (
<TypixEditorContext.Provider value={{ editor }}>
<EditorToolbar />
<EditorContent editor={editor} placeholder="Start typing…" />
</TypixEditorContext.Provider>
);
}Save and load content
useTypixEditor accepts an onUpdate callback that fires on every
content change. Use editor.getJSON() or editor.getHTML() to serialize.
const editor = useTypixEditor({
extensions,
theme: defaultTheme,
namespace: "my-editor",
// Load saved content (omit for empty editor)
content: loadFromStorage(),
// Save on every change
onUpdate: ({ editor }) => {
saveToStorage(editor.getJSON());
},
});