{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "static-docs",
  "title": "Static Rendering",
  "description": "A minimal, memoized, read-only version of Plate with RSC/SSR support.",
  "files": [
    {
      "path": "../../content/docs/(guides)/static.mdx",
      "content": "---\ntitle: Static Rendering\ndescription: A minimal, memoized, read-only version of Plate with RSC/SSR support.\n---\n\n`<PlateStatic>` is a **fast, read-only** React component for rendering Plate content, optimized for **server-side** or **React Server Component** (RSC) environments. It avoids client-side editing logic and memoizes node renders for better performance compared to using [`<Plate>`](/docs/api/core/plate-components) in read-only mode.\n\nIt's a core part of [`serializeHtml`](/docs/api/core/plate-plugin#serializehtml) for HTML export and is ideal for any server or RSC context needing a non-interactive, presentational view of Plate content.\n\n## Key Advantages\n\n-   **Server-Safe:** No browser API dependencies; works in SSR/RSC.\n-   **No Plate Editor Overhead:** Excludes interactive features like selections or event handlers.\n-   **Memoized Rendering:** Uses `_memo` and structural checks to re-render only changed nodes.\n-   **Partial Re-Renders:** Changes in one part of the document don't force a full re-render.\n-   **Lightweight:** Smaller bundle size as it omits interactive editor code.\n\n## When to Use `<PlateStatic>`\n\n-   Generating HTML with [HTML Serialization](/docs/html).\n-   Displaying server-rendered previews in Next.js (especially with RSC).\n-   Building static sites with read-only Plate content.\n-   Optimizing performance-critical read-only views.\n-   Rendering AI-streaming content.\n\n<Callout type=\"info\" title=\"Interactive vs. Static\">\n  For interactive read-only features (like comment popovers or selections), use the standard `<Plate>` component in the browser. For purely server-rendered, non-interactive content, `<PlateStatic>` is the recommended choice.\n</Callout>\n\n## Kit Usage\n\n<Steps>\n\n### Installation\n\nThe fastest way to enable static rendering is with the `BaseEditorKit`, which includes pre-configured base plugins that work seamlessly with server-side rendering.\n\n<ComponentSource name=\"editor-base-kit\" />\n\n### Add Kit\n\n```tsx\nimport { createSlateEditor } from 'platejs';\nimport { PlateStatic } from 'platejs/static';\nimport { BaseEditorKit } from '@/components/editor/editor-base-kit';\n\nconst editor = createSlateEditor({\n  plugins: BaseEditorKit,\n  value: [\n    { type: 'h1', children: [{ text: 'Server-Rendered Title' }] },\n    { type: 'p', children: [{ text: 'This content is rendered statically.' }] },\n  ],\n});\n\n// Render statically\nexport default function MyStaticPage() {\n  return <PlateStatic editor={editor} />;\n}\n```\n\n### Example\n\nSee a complete server-side static rendering example:\n\n<ComponentSource name=\"slate-to-html\" />\n\n</Steps>\n\n## Manual Usage\n\n<Steps>\n\n### Create a Slate Editor\n\nInitialize a Slate editor instance using `createSlateEditor` with your required plugins and components. This is analogous to using `usePlateEditor` for the interactive `<Plate>` component.\n\n```tsx title=\"lib/plate-static-editor.ts\"\nimport { createSlateEditor } from 'platejs';\n// Import your desired base plugins (e.g., BaseHeadingPlugin, MarkdownPlugin)\n// Ensure you are NOT importing from /react subpaths for server environments.\n\nconst editor = createSlateEditor({\n  plugins: [\n    // Add your list of base plugins here\n    // Example: BaseHeadingPlugin, MarkdownPlugin.configure({...})\n  ],\n  value: [ // Example initial value\n    {\n      type: 'p',\n      children: [{ text: 'Hello from a static Plate editor!' }],\n    },\n  ],\n});\n```\n\n### Define Static Node Components\n\nIf your interactive editor uses client-side components (e.g., with `use client` or event handlers), you **must** create static, server-safe equivalents. These components should render pure HTML without browser-specific logic.\n\n```tsx title=\"components/ui/paragraph-node-static.tsx\"\nimport React from 'react';\nimport type { SlateElementProps } from 'platejs/static';\n\nexport function ParagraphElementStatic(props: SlateElementProps) {\n  return (\n    <SlateElement {...props}>\n      {props.children}\n    </SlateElement>\n  );\n}\n```\nCreate similar static components for headings, images, links, etc.\n\n### Map Plugin Keys to Static Components\n\nCreate an object that maps plugin keys or node types to their corresponding static React components, then pass it to the editor.\n\n```ts title=\"components/static-components.ts\"\nimport { ParagraphElementStatic } from './ui/paragraph-node-static';\nimport { HeadingElementStatic } from './ui/heading-node-static';\n// ... import other static components\n\nexport const staticComponents = {\n  p: ParagraphElementStatic,\n  h1: HeadingElementStatic,\n  // ... add mappings for all your element and leaf types\n};\n```\n\n### Render `<PlateStatic>`\n\nUse the `<PlateStatic>` component, providing the `editor` instance configured with your components.\n\n```tsx title=\"app/my-static-page/page.tsx (RSC Example)\"\nimport { createSlateEditor } from 'platejs';\nimport { PlateStatic } from 'platejs/static';\n// import { BaseHeadingPlugin, ... } from '@platejs/basic-nodes'; // etc.\nimport { staticComponents } from '@/components/static-components';\n\nexport default async function MyStaticPage() {\n  // Example: Fetch or define editor value\n  const initialValue = [\n    { type: 'h1', children: [{ text: 'Server-Rendered Title' }] },\n    { type: 'p', children: [{ text: 'Content rendered statically.' }] },\n  ];\n\n  const editor = createSlateEditor({\n    plugins: [/* your base plugins */],\n    components: staticComponents,\n    value: initialValue,\n  });\n\n  return (\n    <PlateStatic\n      editor={editor}\n      style={{ padding: 16 }}\n      className=\"my-plate-static-content\"\n    />\n  );\n}\n```\n\n<Callout type=\"note\" title=\"Value Override\">\n  If you pass a `value` prop directly to `<PlateStatic>`, it will override `editor.children`.\n  ```tsx\n  <PlateStatic\n    editor={editor}\n    value={[\n      { type: 'p', children: [{ text: 'Overridden content.' }] }\n    ]}\n  />\n  ```\n</Callout>\n\n### Memoization Details\n\n`<PlateStatic>` enhances performance through memoization:\n-   Each `<ElementStatic>` and `<LeafStatic>` is wrapped in `React.memo`.\n-   **Reference Equality:** Unchanged node references prevent re-renders.\n-   **`_memo` Field:** Setting `node._memo = true` (or any stable value) on an element or leaf can force Plate to skip re-rendering that specific node, even if its content changes. This is useful for fine-grained control over updates.\n\n</Steps>\n\n## Client-Side Alternative: `PlateView`\n\nFor cases where you need **minimal interactivity** with static content, use `<PlateView>`. This component wraps `<PlateStatic>` and adds client-side event handlers for user interactions while maintaining the performance benefits of static rendering.\n\n### Example: Server Component with Both Static Views\n\n```tsx title=\"app/document/page.tsx\"\nimport { createStaticEditor, PlateStatic } from 'platejs/static';\nimport { BaseEditorKit } from '@/components/editor/editor-base-kit';\nimport { InteractiveViewer } from './interactive-viewer';\n\nexport default async function DocumentPage() {\n  const content = await fetchDocument(); // Your document data\n  \n  // Server-side static editor\n  const editor = createStaticEditor({\n    plugins: BaseEditorKit,\n    value: content,\n  });\n\n  return (\n    <div className=\"grid grid-cols-2 gap-4\">\n      {/* Pure static rendering - no interactivity */}\n      <div>\n        <h2>Static View (Server Rendered)</h2>\n        <PlateStatic editor={editor} />\n      </div>\n\n      {/* Interactive view - rendered on client */}\n      <div>\n        <h2>Interactive View</h2>\n        <InteractiveViewer value={content} />\n      </div>\n    </div>\n  );\n}\n```\n\n### Example: Client Component with PlateView\n\n```tsx title=\"app/document/interactive-viewer.tsx\"\n'use client';\n\nimport { usePlateViewEditor } from 'platejs/react';\nimport { PlateView } from 'platejs/react';\nimport { BaseEditorKit } from '@/components/editor/editor-base-kit';\n\nexport function InteractiveViewer({ value }) {\n  const editor = usePlateViewEditor({\n    plugins: BaseEditorKit,\n    value,\n  });\n\n  return <PlateView editor={editor} />;\n}\n```\n\n### Key Features of `PlateView`\n\n- **Client-side only**: Requires `'use client'` directive\n- **Adds interactivity**: Enables user interactions with the content (e.g., text selection, copying, future interactions like tooltips, highlights, etc.)\n- **Minimal overhead**: Still uses `PlateStatic` internally for rendering\n- **Use with `usePlateViewEditor`**: Creates a static editor optimized for view-only React components\n- **ViewPlugin included**: The static editor automatically includes `ViewPlugin` which provides event handling capabilities\n\n<Callout type=\"warning\" title=\"Server Component Compatibility\">\n  `PlateView` cannot be used in Server Components. If you're passing an editor from a server component to a client component, you'll encounter serialization errors. Use `PlateStatic` on the server side, or create the editor client-side with `usePlateViewEditor`.\n</Callout>\n\n## `PlateStatic` vs. `PlateView` vs. `Plate` + `readOnly`\n\n| Aspect                | `<PlateStatic>`                                       | `<PlateView>`                                          | `<Plate>` + `readOnly`                                 |\n| --------------------- | ----------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------ |\n| **Environment**       | Server/Client (SSR/RSC safe)                          | Client-only                                            | Client-only                                            |\n| **Interactivity**     | None                                                  | Minimal (selection, copy, toolbar, etc.)     | Full interactive features (browser-only)               |\n| **Browser APIs**      | Not used                                              | Minimal (event handlers)                               | Full usage                                             |\n| **Performance**       | Best - static HTML only                               | Good - static rendering + event delegation             | Heavier - full editor internals                        |\n| **Bundle Size**       | Smallest                                              | Small                                                  | Largest                                                |\n| **Use Cases**         | Server rendering, HTML export                         | Client-side content with basic interactions            | Full read-only editor with all features                |\n| **Recommendation**    | SSR/RSC without any interactions                      | Client-side content needing light interactivity        | Client-side with complex interactive needs             |\n\n## RSC/SSR Example\n\nIn a Next.js App Router (or similar RSC environment), `<PlateStatic>` can be used directly in Server Components:\n\n```tsx title=\"app/preview/page.tsx (RSC)\"\nimport { createSlateEditor } from 'platejs';\nimport { PlateStatic } from 'platejs/static';\n// Example base plugins (ensure non-/react imports)\n// import { BaseHeadingPlugin } from '@platejs/basic-nodes';\nimport { staticComponents } from '@/components/static-components'; // Your static components mapping\n\nexport default async function Page() {\n  // Fetch or define content server-side\n  const serverContent = [\n    { type: 'h1', children: [{ text: 'Rendered on the Server! 🎉' }] },\n    { type: 'p', children: [{ text: 'This content is static and server-rendered.' }] },\n  ];\n\n  const editor = createSlateEditor({\n    // plugins: [BaseHeadingPlugin, /* ...other base plugins */],\n    plugins: [], // Add your base plugins\n    components: staticComponents,\n    value: serverContent,\n  });\n\n  return (\n    <PlateStatic\n      editor={editor}\n      className=\"my-static-preview-container\"\n    />\n  );\n}\n```\nThis renders the content to HTML on the server without needing a client-side JavaScript bundle for `PlateStatic` itself.\n\n## Pairing with `serializeHtml`\n\nFor generating a complete HTML string (e.g., for emails, PDFs, or external systems), use `serializeHtml`. It utilizes `<PlateStatic>` internally.\n\n```ts title=\"lib/html-serializer.ts\"\nimport { createSlateEditor } from 'platejs';\nimport { serializeHtml } from 'platejs/static';\nimport { staticComponents } from '@/components/static-components';\n// import { BaseHeadingPlugin, ... } from '@platejs/basic-nodes';\n\nasync function getDocumentAsHtml(value: any[]) {\n  const editor = createSlateEditor({\n    plugins: [/* ...your base plugins... */],\n    components: staticComponents,\n    value,\n  });\n\n  const html = await serializeHtml(editor, {\n    // editorComponent: PlateStatic, // Optional: Defaults to PlateStatic\n    props: { className: 'prose max-w-none' }, // Example: Pass props to the root div\n  });\n\n  return html;\n}\n\n// Example Usage:\n// const mySlateValue = [ { type: 'h1', children: [{ text: 'My Document' }] } ];\n// getDocumentAsHtml(mySlateValue).then(console.log);\n```\nFor more details, see the [HTML Serialization guide](/docs/html).\n\n## API Reference\n\n### `<PlateStatic>` Props\n\n```ts\nimport type React from 'react';\nimport type { Descendant } from 'slate';\nimport type { PlateEditor } from 'platejs/core'; // Adjust imports as per your setup\n\ninterface PlateStaticProps extends React.HTMLAttributes<HTMLDivElement> {\n  /**\n   * The Plate editor instance, created via `createSlateEditor`.\n   * Must include plugins and components relevant to the content being rendered.\n   */\n  editor: PlateEditor;\n\n  /**\n   * Optional Plate `Value` (array of `Descendant` nodes).\n   * If provided, this will be used for rendering instead of `editor.children`.\n   */\n  value?: Descendant[];\n\n  /** Inline CSS styles for the root `div` element. */\n  style?: React.CSSProperties;\n\n  // Other HTMLDivElement attributes like `className`, `id`, etc., are also supported.\n}\n```\n\n-   **`editor`**: An instance of `PlateEditor` created with `createSlateEditor`, including components configuration.\n-   **`value`**: Optional. If provided, this array of `Descendant` nodes will be rendered, overriding the content currently in `editor.children`.\n\n## Next Steps\n\n-   Explore [HTML Serialization](/docs/html) for exporting content.\n-   Learn about using Plate in [React Server Components](/docs/installation/rsc).\n-   Refer to individual plugin documentation for their base (non-React) imports.",
      "type": "registry:file",
      "target": "content/docs/plate/(guides)/static.mdx"
    }
  ],
  "type": "registry:file"
}