{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "installation-node-docs",
  "title": "Node.js",
  "description": "Install and configure Plate for Node.js.",
  "files": [
    {
      "path": "../../content/docs/installation/node.mdx",
      "content": "---\ntitle: Node.js\ndescription: Install and configure Plate for Node.js.\n---\n\nUse Plate in Node.js when you need to read, validate, transform, or serialize editor values outside the browser. Node scripts use the base runtime imports, while React editors use `/react` subpaths. This guide walks through a server-safe editor, Markdown IO, and a content transform.\n\n## Node.js Setup\n\n<Callout type=\"warning\" title=\"Use base imports\">\n  Do not import from `platejs/react` or `@platejs/*/react` in Node.js scripts.\n  Use `createSlateEditor` from `platejs` and base plugins from `@platejs/*`\n  packages.\n</Callout>\n\n<Steps>\n\n### Install Packages\n\nInstall the core runtime and the packages your pipeline needs.\n\n```bash\nnpm install platejs @platejs/basic-nodes @platejs/markdown\n```\n\n| Package | Owns |\n| --- | --- |\n| `platejs` | `createSlateEditor`, core editor APIs, core paragraph behavior. |\n| `@platejs/basic-nodes` | Base headings, blockquotes, horizontal rules, and text marks. |\n| `@platejs/markdown` | Markdown serialization, deserialization, and the `MarkdownPlugin` API. |\n\n### Create a Server Editor\n\nCreate the editor with base plugins only. The editor exposes the same `editor.api`\nand `editor.tf` surfaces without mounting a React tree.\n\n```ts showLineNumbers title=\"scripts/process-content.ts\"\nimport type { Value } from 'platejs';\n\nimport {\n  BaseBasicBlocksPlugin,\n  BaseBasicMarksPlugin,\n} from '@platejs/basic-nodes';\nimport { createSlateEditor } from 'platejs';\n\nconst value: Value = [\n  {\n    children: [{ text: 'Document Title' }],\n    type: 'h1',\n  },\n  {\n    children: [\n      { text: 'With ' },\n      { bold: true, text: 'bold' },\n      { text: ' text.' },\n    ],\n    type: 'p',\n  },\n];\n\nconst editor = createSlateEditor({\n  plugins: [BaseBasicBlocksPlugin, BaseBasicMarksPlugin],\n  value,\n});\n\nconst plainText = editor.api.string([]);\n\nconsole.info(plainText);\n```\n\n### Read and Write Markdown\n\nAdd `MarkdownPlugin` when the script needs Markdown helpers through\n`editor.getApi(MarkdownPlugin)`. You can also call `deserializeMd` and\n`serializeMd` directly.\n\n```ts showLineNumbers title=\"scripts/markdown-io.ts\"\nimport {\n  BaseBasicBlocksPlugin,\n  BaseBasicMarksPlugin,\n} from '@platejs/basic-nodes';\nimport {\n  MarkdownPlugin,\n  deserializeMd,\n  serializeMd,\n} from '@platejs/markdown';\nimport { createSlateEditor } from 'platejs';\n\nconst editor = createSlateEditor({\n  plugins: [BaseBasicBlocksPlugin, BaseBasicMarksPlugin, MarkdownPlugin],\n});\n\nconst value = deserializeMd(\n  editor,\n  [\n    '# Migration Note',\n    '',\n    'Move legacy content into **Plate** format.',\n  ].join('\\n')\n);\n\nconst markdown = serializeMd(editor, { value });\n\nconsole.info(markdown);\n```\n\n### Transform Content\n\nUse transforms for migrations and bulk cleanup. Pass `at: []` when the operation\nshould scan the whole document.\n\n```ts showLineNumbers title=\"scripts/normalize-headings.ts\"\nimport type { Value } from 'platejs';\n\nimport {\n  BaseBasicBlocksPlugin,\n  BaseBasicMarksPlugin,\n} from '@platejs/basic-nodes';\nimport { MarkdownPlugin, serializeMd } from '@platejs/markdown';\nimport { createSlateEditor } from 'platejs';\n\nexport function normalizeHeadings(value: Value) {\n  const editor = createSlateEditor({\n    plugins: [BaseBasicBlocksPlugin, BaseBasicMarksPlugin, MarkdownPlugin],\n    value,\n  });\n\n  editor.tf.setNodes(\n    { type: 'h2' },\n    {\n      at: [],\n      match: (node) => 'type' in node && node.type === 'h1',\n    }\n  );\n\n  editor.tf.insertNodes(\n    [{ children: [{ text: 'Imported from the legacy CMS.' }], type: 'p' }],\n    { at: [editor.children.length] }\n  );\n\n  return {\n    markdown: serializeMd(editor),\n    text: editor.api.string([]),\n    value: editor.children,\n  };\n}\n```\n\n</Steps>\n\n## Runtime Boundaries\n\n| Runtime | Import from | Use for |\n| --- | --- | --- |\n| Node.js scripts | `platejs`, `@platejs/*` | Migration, validation, serialization, search indexing. |\n| React editors | `platejs/react`, `@platejs/*/react` | Editable UI, hooks, rendered components, toolbar behavior. |\n| Static rendering | `platejs/static` | Server-rendered read-only content. |\n\n<Callout type=\"info\">\n  Plugin packages can expose both base and React entrypoints. In Node.js, choose\n  the base entrypoint even when the same feature has React components for the\n  browser editor.\n</Callout>\n\n## API Reference\n\n| API | Package | Notes |\n| --- | --- | --- |\n| `createSlateEditor` | `platejs` | Creates a non-React editor instance. |\n| `editor.api.string([])` | `platejs` | Reads text from the whole document. |\n| `editor.tf.setNodes` | `platejs` | Updates matching nodes. Use `at: []` for document-wide transforms. |\n| `editor.tf.insertNodes` | `platejs` | Inserts nodes at a path. |\n| `deserializeMd` | `@platejs/markdown` | Converts Markdown into a Plate value. |\n| `serializeMd` | `@platejs/markdown` | Converts the editor value or an explicit `value` option to Markdown. |\n\n## Next Steps\n\n| Task | Guide |\n| --- | --- |\n| Serialize to Markdown | [Markdown](/docs/markdown) |\n| Serialize to HTML | [HTML](/docs/html) |\n| Render read-only content | [Static Rendering](/docs/static) |\n| Query editor state | [Editor API](/docs/api/slate/editor-api) |\n| Apply transforms | [Editor Transforms](/docs/api/slate/editor-transforms) |\n\nDone. You now have a server-safe Plate runtime that can power migration scripts,\nvalidation jobs, and content serialization.\n",
      "type": "registry:file",
      "target": "content/docs/plate/installation/node.mdx"
    }
  ],
  "type": "registry:file"
}