DocsAPI ReferenceComponents<App>

<App>

Mount a schema-driven, multi-page React Editor application. <App> sets up a React Router instance, then routes each entry in pages against the URL — rendering it through <Render>, or through <Editor> when the URL is under editorPath.

For an introduction, see Multi-Page Apps.

import { App, outlinePlugin } from "@reacteditor/core";
 
const config = { components: {} };
 
const pages = {
  "/": { content: [], root: {} },
  "/about": { content: [], root: {} },
};
 
// blocksPlugin is auto-injected; outlinePlugin must be passed explicitly
// to enable the Outline panel.
const plugins = [outlinePlugin()];
 
export function Example() {
  return <App config={config} pages={pages} plugins={plugins} />;
}

Props

ParamExampleTypeStatus
configconfig: { components: {} }ConfigRequired
pagespages: { "/": data }Record<string, Data>Required
childrenchildren: <App.Render />ReactNode-
currentPathcurrentPath: "/about"String-
editorPatheditorPath: "/admin"String | null-
fieldTransformsfieldTransforms: {}FieldTransforms-
iframeiframe: { enabled: false }IframeConfig-
metadatametadata: { title: "x" }Object-
onChange()onChange: (data) => {}Function-
onPublish()onPublish: (data, route) => {}Function-
overridesoverrides: { header: () => <div /> }Overrides-
permissionspermissions: { delete: false }Permissions[]-
pluginsplugins: [myPlugin]Plugin[]-
renderNotFoundrenderNotFound: () => <NotFound />Function-
routerrouter: "browser""browser" | "hash" | "memory"-
viewportsviewports: [{ width: 1440 }]Viewport[]-

Required props

config

The shared Config used to render every page in pages. See the Config docs for a full reference.

export function Example() {
  return (
    <App
      config={{
        components: {
          HeadingBlock: {
            fields: { children: { type: "text" } },
            render: ({ children }) => <h1>{children}</h1>,
          },
        },
      }}
      // ...
    />
  );
}

pages

A map from route pattern to Data payload. Keys use the same path syntax as React Router, so dynamic segments (e.g. /products/:handle) are supported.

export function Example() {
  return (
    <App
      pages={{
        "/": {
          content: [
            { type: "HeadingBlock", props: { id: "h-1", children: "Home" } },
          ],
          root: {},
        },
        "/about": { content: [], root: {} },
      }}
      // ...
    />
  );
}

Inside a rendered page, components can read URL parameters with useRouteParams.

Optional props

children

Take over the default layout and compose your own. When children is provided, <App> skips its built-in layout and renders your tree inside the router/context. Use App.Render and App.Editor to mount the page renderer and editor wherever you want them.

import { App, Editor } from "@reacteditor/core";
 
export function Example() {
  return (
    <App config={config} pages={pages}>
      <MyLayout>
        <App.Render />
        <App.Editor>
          <Editor.Preview />
          <Editor.Fields />
        </App.Editor>
      </MyLayout>
    </App>
  );
}

See Composing your own layout for the full pattern.

currentPath

The pathname used by the router on first render. Required for SSR (so the server-rendered markup matches the requested URL) and for the "memory" router. Ignored by the default "browser" router and by "hash".

<App
  currentPath={req.url}
  // ...
/>

editorPath

The URL prefix under which the editor is mounted. Defaults to "/editor". Pass null to disable editor mode entirely (render-only build).

// Move the editor to /admin
<App editorPath="/admin" /* ... */ />
// Render-only — no editor routes mounted
<App editorPath={null} /* ... */ />

fieldTransforms

Specify transforms to modify field values before being passed to the editor canvas. Implements the Field Transforms API. Only applied while editing.

iframe

Configure iframe behaviour for the editor canvas. See <Editor> iframe params.

metadata

An object containing additional data provided to each component’s render and resolveData functions. Forwarded to both <Render> and <Editor>.

<App
  metadata={{ title: "Hello, world" }}
  // ...
/>

onChange(data)

Forwarded to <Editor>’s onChange. Fires on every edit while the user is in editor mode.

onPublish(data, route)

Forwarded to <Editor>’s onPublish with one extra argument: the route key of the page that was published. Use this to scope your save to the right row in your database.

<App
  onPublish={async (data, route) => {
    await fetch("/api/save", {
      method: "post",
      body: JSON.stringify({ route, data }),
    });
  }}
  // ...
/>

overrides

An Overrides object defining custom render methods for the editor UI. Only applied while editing.

permissions

Set the global permissions for the editor. Only applied while editing.

plugins

An array of plugins to enhance the editor. Only applied while editing.

renderNotFound

Custom 404 component shown when the URL doesn’t match any entry in pages. Falls back to a built-in screen.

<App
  renderNotFound={() => <MyCustomNotFound />}
  // ...
/>

router

The React Router variant to use on the client. Defaults to "browser" (uses real URLs via the History API).

ValueWhen to use
"browser"Default. Real URLs (/about).
"hash"Static hosts that can’t rewrite URLs (/#/about).
"memory"Embedded previews or environments without a URL bar. Pair with currentPath.

SSR always uses StaticRouter regardless of this value.

viewports

Configure the viewports available in the editor canvas. See <Editor> viewports.

Composition

<App> exposes two compositional primitives. They each handle their own routing — you never write <Route> elements yourself.

App.Render

Mounts <Render> for the current page when the URL is not under editorPath. Returns null while editing.

<App.Render />

App.Render props

ParamExampleType
metadatametadata: { title: "x" }Object
renderNotFoundrenderNotFound: () => <NotFound />Function

App.Editor

Mounts <Editor> for the current page when the URL is under editorPath. Returns null otherwise.

children are forwarded to <Editor> for compositional UI (<Editor.Preview>, <Editor.Fields>, <Editor.Components>, <Editor.Outline>).

<App.Editor onPublish={save}>
  <Editor.Preview />
  <Editor.Fields />
</App.Editor>

App.Editor props

App.Editor accepts the same editor pass-through props as <App>. When you compose, set them on App.Editor rather than on <App>.

ParamExampleType
childrenchildren: <Editor.Preview />ReactNode
fieldTransformsfieldTransforms: {}FieldTransforms
iframeiframe: { enabled: false }IframeConfig
metadatametadata: { title: "x" }Object
onChangeonChange: (data) => {}Function
onPublishonPublish: (data, route) => {}Function
overridesoverrides: { header: () => <div /> }Overrides
permissionspermissions: { delete: false }Permissions
pluginsplugins: [myPlugin]Plugin[]
renderNotFoundrenderNotFound: () => <NotFound />Function
viewportsviewports: [{ width: 1440 }]Viewport[]