---
name: ecsplico-editor
description: "Integrate, compose or extend the @skaile/forge-editor Vue/React block editor (TipTap v3): pick entries, register the Nuxt module and EditorPorts, add features or own blocks, verify with the package checks. Use when a task touches @skaile/forge-editor or packages/editor."
---

# @skaile/forge-editor

Vue 3 and React 19 block editor library on TipTap v3. An editor is a list of features (`EditorFeature`) validated by `defineEditor` into an immutable `EditorPreset` and mounted by `EditorSurface`. Documentation: https://skaile-ai.github.io/forge-editor/

## When to use

- Adding the editor to a Vue, Nuxt or React app, or wiring its server side (`EditorPorts`, collaboration, AI).
- Choosing a preset or composing a feature list.
- Adding an own block (node, node view, slash command, conversion) or an own feature.
- Changing `packages/editor` itself.

Not a general CMS: it edits structured documents; storage and identity stay with the host.

## Surfaces and entries

Every entry is an explicit subpath of `package.json#exports`; there is no wildcard. The root entry `@skaile/forge-editor` is type-only.

| Need | Import |
|---|---|
| Simple editor (Vue) | `SimpleEditor` from `@skaile/forge-editor/vue/simple` |
| Everything (Vue, backend via Nuxt module) | `AdvancedEditor`, `advancedEditor` from `@skaile/forge-editor/vue/advanced` |
| Vue chrome and context | `createEditor`, `EditorSurface`, `EditorToolbar`, `EditorSettingsPanel` from `@skaile/forge-editor/vue` |
| React chrome and context | `EditorContextProvider`, `EditorSurface`, `EditorToolbar`, `Toaster` from `@skaile/forge-editor/react` |
| Simple or advanced editor (React) | `@skaile/forge-editor/react/simple`, `@skaile/forge-editor/react/advanced` |
| Framework-free core | `defineEditor`, `coreContentFeature`, `coreUiFeature`, `createEditorContext`, `command` from `@skaile/forge-editor/core` |
| One feature | models from `.../<x>`, `<x>Feature()` and components from `.../<x>/vue` or `.../<x>/react` |
| Preset from three dimensions | `composeEditor`, `simpleEditor` from `@skaile/forge-editor/presets/compose` |
| Nitro server side | `provideEditorServer`, `useEditorServer` from `@skaile/forge-editor/server/nitro`, `EditorPorts` from `@skaile/forge-editor/server`; Nuxt module `@skaile/forge-editor/nuxt` |
| Schema for a server or validator | `.../schema/simple`, `.../schema/advanced`, `.../<x>/schema` |
| CSS | `.../styles/core.css` plus the sheet of each feature (`media`, `mentions`, `tables`, `comments`, `block-ui`, `themes`, …) |

Import values from the subpath that owns them. Never import a browser entry from server code, never `/server` or `/nuxt` from browser code. Full inventory of every exported name: https://skaile-ai.github.io/forge-editor/reference/exports

## Workflow

1. Read the page that matches the task. Fetch the Markdown twin: `https://skaile-ai.github.io/forge-editor/raw/<path>.md`.
   - Integrate the editor: `/raw/ai-agents/integrate.md`
   - Add a block or feature: `/raw/ai-agents/extend.md`
   - Check the invariants: `/raw/ai-agents/invariants.md`
2. Implement against the page. Copy code from the linked guides and tutorial chapters, which show real files from the repository, instead of writing it from memory.
3. Run the verification commands (below) from the repository root and fix what they report.

Verification commands (full list in https://skaile-ai.github.io/forge-editor/reference/commands):

```sh
bun run typecheck:editor        # types of the library
bun run check:editor-entries    # after touching a package entry: builds, bundle isolation, schema snapshot
bun run check:editor-composition # defineEditor validation
bun run check:editor-i18n       # after any user-facing string
```

Run `check:editor-entries` after touching an entry and `check:editor-i18n` after a user-facing string. After adding a feature add a fixture under `packages/editor/checks/fixtures/<name>/` and a `FIXTURES` entry in `packages/editor/checks/entries.ts`.

## Invariants

- **CSS order.** `core.css` after Tailwind and Nuxt UI, then each feature sheet, `themes.css` last; Tailwind must see the library (`@source`).
- **Editor context is mandatory.** Vue: `app.use(createEditor())` (the Nuxt module does it); React: `<EditorContextProvider context={createEditorContext()}>`. Without it the components throw.
- **Notices.** Vue needs `<UApp>` for toasts; React needs `createEditorContext({ notify: reactNotifier })` and one `<Toaster />`.
- **UI provider.** Wrap the page in `<UApp>`; plain Vue also needs `app.use(ui)` from `@nuxt/ui/vue-plugin` and the `ui({ router: false })` Vite plugin.
- **SSR.** Editors are client-only: `ssr: false`, or `<ClientOnly>`.
- **Mount-time props.** Preset, `collaboration`, `abilities`, `extensions`, `commands`, `blockActions`, `blockTypes`, `documentId` are read once; remount with a new `key` to change them. Keep them constant, never a new object per render.
- **Schema match.** A simple editor rejects advanced JSON (`contentError`); `collaboration` needs a preset containing `collab`, and `commentsFeature()` needs `collab`.
- **Bundle isolation.** `core` and `settings` import no feature; a feature never imports another feature; the simple bundle holds no feature code, Yjs, AI SDK, Nuxt or server modules.
- **Entries.** Server code imports only framework-free entries (`/schema`, `/protocol`, `/types`, `/settings`) or `/server`. A new public entry needs an explicit `package.json#exports` row.
- **Module order.** `@nuxt/ui` before `@skaile/forge-editor/nuxt` in `modules`.
- **Server ports.** `identity` and `documents` are required in `EditorPorts`; a route whose port is absent answers 501. AI keys come from environment variables only.
- **New nodes on collaborative documents.** Register the Vue-free node in the server schema: `provideEditorServer({ ports, schema: () => [...advancedSchemaExtensions(), YourNode] })`.
- **Settings keys.** Only keys of `EditorSettings` persist; unknown ones are dropped.

Details and the remaining invariants: https://skaile-ai.github.io/forge-editor/ai-agents/invariants

## Reference pages

| Page | URL |
|---|---|
| Reading the docs as an agent | https://skaile-ai.github.io/forge-editor/ai-agents |
| Integrate the editor | https://skaile-ai.github.io/forge-editor/ai-agents/integrate |
| Add a block or feature | https://skaile-ai.github.io/forge-editor/ai-agents/extend |
| Pitfalls and invariants | https://skaile-ai.github.io/forge-editor/ai-agents/invariants |
| Verify | https://skaile-ai.github.io/forge-editor/ai-agents/verify |
| Public exports | https://skaile-ai.github.io/forge-editor/reference/exports |
| Presets and features | https://skaile-ai.github.io/forge-editor/reference/presets-and-features |
| Feature contract | https://skaile-ai.github.io/forge-editor/reference/feature-contract |
| CSS and UI-provider requirements | https://skaile-ai.github.io/forge-editor/reference/css-and-ui |
| Commands | https://skaile-ai.github.io/forge-editor/reference/commands |
| EditorPorts guide | https://skaile-ai.github.io/forge-editor/guides/editor-ports |
| Tutorial (Vue to React, own blocks, AI) | https://skaile-ai.github.io/forge-editor/tutorial/overview |
| Whole site as one file | https://skaile-ai.github.io/forge-editor/llms-full.txt |
