---
title: "Advanced editor in React"
description: "Mount the collaborative AdvancedEditor on React with the chrome components beside it, over the same backend as the Vue surface."
canonical_url: "https://skaile-ai.github.io/forge-editor/guides/advanced-react"
---
# Advanced editor in React

> Mount the collaborative AdvancedEditor on React with the chrome components beside it, over the same backend as the Vue surface.

`AdvancedEditor` from `@skaile/forge-editor/react/advanced` is the React counterpart of the Vue `AdvancedEditor`: an `EditorSurface` over `composeEditor` of its `content`, `interaction`, `ai`, `add`, `remove` and `backend` props (defaults `{ content: 'rich', interaction: 'full', ai: true }`, i.e. `advancedEditor()`), which lists every feature and integration (`core-content`, `core-ui`, `media`, `transcript`, `composites`, `mentions`, `authors`, `comments`, `ai`, `collab`, `block-ui`, `composite-media`, `composite-ai`, `transcript-ai`, `themes`) with its React binding, in the same schema order as the Vue surface. It uses no Vue, Nuxt UI or Nuxt module. The runnable reference is [`examples/react-advanced`](https://github.com/skaile-ai/forge-editor/tree/main/examples/react-advanced) (`bun run --cwd examples/react-advanced dev`, port 3043): the React counterpart of the Nuxt document page. It reuses the Nuxt app's documents, session and collaboration socket through the Vite proxy (`/api`, `/collab`), so start the Nuxt app first (`bun run dev`, port 3056).

**Setup** is the [simple React setup](https://skaile-ai.github.io/forge-editor/getting-started/quick-start-react#setup) plus three things:

- **Styles.** Replace the three library imports by one: `@import "@skaile/forge-editor/react/styles/advanced.css";` after `tailwindcss` and `tw-animate-css` (it imports `ui-vars.css`, `core.css`, every feature sheet and `themes.css` last, plus the bridge that lets an Obsidian theme restyle the shadcn tokens). Keep the `@source` for the library's whole `dist` (`src` in this repository, as the example does) and the shadcn theme block; `examples/react-advanced/src/index.css` has a complete copy.
- **Notices.** Create the context with `createEditorContext({ notify: reactNotifier })` and render sonner's `<Toaster />` once inside the provider (both exported by `@skaile/forge-editor/react`). Features send `Notice`s to the surface's notifier (import problems, AI rate limits, comment errors, „Dokument gelöscht“ with undo in the tree); without `<Toaster />` none is visible.
- **Dependencies.** The simple setup's list plus `sonner` (the `Toaster` and the notice seam), `yjs` and `@hocuspocus/provider` for collaboration; use the exact version ranges of the [example's `package.json`](https://github.com/skaile-ai/forge-editor/blob/main/examples/react-advanced/package.json).

`main.tsx`:

```tsx [examples/react-advanced/src/main.tsx]
import lucide from '@iconify-json/lucide/icons.json'
import { addCollection } from '@iconify/react'
import { createHttpBackend } from '@skaile/forge-editor/adapters/http'
import { createEditorContext } from '@skaile/forge-editor/core'
import { EditorContextProvider, reactNotifier, Toaster } from '@skaile/forge-editor/react'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { App } from './App'
import './index.css'

// Preload the icon set: the page makes no request to the Iconify API.
addCollection(lucide)

// The host owns the context; the provider never disposes it. The backend is the HTTP one (`/api/editor` over the Nuxt host,
// the collaboration websocket `/collab/<id>`); the backend offers `settings`, so they sync with the host's account store,
// notices of app-level models become sonner toasts.
const context = createEditorContext({ backend: createHttpBackend(), notify: reactNotifier })

createRoot(document.getElementById('app')!).render(
  <StrictMode>
    <EditorContextProvider context={context}>
      <App />
      <Toaster />
    </EditorContextProvider>
  </StrictMode>,
)
```

The example passes `createHttpBackend()` so settings sync with the host's `/api/editor/settings`; pass `createMemoryBackend()` for local-only settings.

**The page.** The chrome components beside the editor take the editor from `onReady` and find its preset through it. `AdvancedEditor` takes the surface's props except `preset`, plus the composition props (`content`, `interaction`, `ai`, `add`, `remove`, `backend`, `blockTypes`, `blockUi`, `coreContent`, read once at mount); `<AdvancedEditor remove={['tables']} ai={false} />` is the advanced editor without tables and AI:

```tsx
import { AiSidebar } from '@skaile/forge-editor/ai/react'
import { CommentsMargin } from '@skaile/forge-editor/comments/react'
import { CompositeInspector } from '@skaile/forge-editor/composites/react'
import type { CollaborationSession } from '@skaile/forge-editor/core'
import { EditorSettingsModal, EditorToolbar } from '@skaile/forge-editor/react'
import { AdvancedEditor } from '@skaile/forge-editor/react/advanced'
import type { Editor } from '@tiptap/core'
import { useState } from 'react'

export function Page({ id, session }: { id: string, session: CollaborationSession }) {
  const [editor, setEditor] = useState<Editor>()
  const [scrollEl, setScrollEl] = useState<HTMLElement | null>(null)
  const [settingsOpen, setSettingsOpen] = useState(false)
  const [sidebarOpen, setSidebarOpen] = useState(false)
  const [commentsOpen, setCommentsOpen] = useState(false)

  return (
    <>
      <EditorToolbar editor={editor} />
      <main ref={setScrollEl} className="relative flex min-h-0 flex-1 overflow-auto">
        <AdvancedEditor
          key={id}
          collaboration={session}
          documentId={id}
          settingsUi="external"
          sidebarOpen={sidebarOpen}
          onSidebarOpenChange={setSidebarOpen}
          commentsOpen={commentsOpen}
          onCommentsOpenChange={setCommentsOpen}
          onReady={setEditor}
          onSettingsOpen={() => setSettingsOpen(true)}
        />
        <CommentsMargin editor={editor} container={scrollEl} open={commentsOpen} />
      </main>
      <CompositeInspector editor={editor} />
      <AiSidebar editor={editor} open={sidebarOpen} onOpenChange={setSidebarOpen} />
      <EditorSettingsModal editor={editor} open={settingsOpen} onOpenChange={setSettingsOpen} />
    </>
  )
}
```

Notes:

- **Collaboration.** The `session` is `{ ydoc, provider, user }` (`CollaborationSession` from `@skaile/forge-editor/core`): create the `Y.Doc` and the `HocuspocusProvider` in an effect (so StrictMode's double mount leaves exactly one provider), destroy the provider in its cleanup, and key the editor by document so a new document is a new Y.Doc ([Collaboration on the client](https://skaile-ai.github.io/forge-editor/guides/collaboration)). Without `collaboration` pass `value`/`onChange` for a standalone editor (the collaboration and comments features then contribute nothing).
- **Beside the editor.** `EditorToolbar`, `EditorSettingsModal`/`EditorSettingsPanel`, `CommentsMargin`, `CompositeTable`, `CompositeInspector`, `AiSidebar`, `EditorOutline` and `DocumentTree` are components you place; each takes the `editor` from `onReady`. `useEditorUi(editor)` returns the chrome of a ready editor (`openSettings(tab?)`, `toggleSidebar()`, `toggleComments()`, `commentsOpen`, `togglePalette()`, `paletteOpen`) for your own buttons.
- **Own features.** Pass them as `add={[myFeature()]}` (appended after the catalog), or build the preset for an `EditorSurface` yourself: `advancedEditor({ add: [myFeature()] })`, as in the Nuxt app's kitchen sink (`app/pages/kitchen-sink/surface.vue`).
- **The file browser** is [`DocumentTree` from `@skaile/forge-editor/tree/react`](https://skaile-ai.github.io/forge-editor/guides/document-tree) over a `DocumentStore`; the example wires it to the host's `/api`.
- **Backend.** The same as for the Vue advanced editor: `/collab/:id`, the AI endpoints, assets, users/tags and themes of the Nuxt module and a host adapter ([Nuxt module](https://skaile-ai.github.io/forge-editor/guides/nuxt-module) and [EditorPorts](https://skaile-ai.github.io/forge-editor/guides/editor-ports)). A React app with its own server brings the same routes.


## Sitemap

See the full [sitemap](https://skaile-ai.github.io/forge-editor/sitemap.md) for all pages.
