eddev
Blocks

Configuring the Editor

Control which blocks authors can use

The editor config lives in blocks/_editor.tsx. It decides which blocks are available at the root of a post, which template blocks should be inserted automatically, and how block wrappers should be styled in the WordPress editor.

import { defineEditorConfig } from "eddev/blocks"

export default defineEditorConfig({
  matchers: [
    {
      match: (post) => post.type === "page" && post.template === "default",
      config: {
        rootBlocks: ["#root"],
      },
    },
  ],
})

Each matcher receives information about the current editor document. Return true from match when that config should apply.

Root Blocks

rootBlocks controls which blocks can be added at the top level of the post content.

export default defineEditorConfig({
  matchers: [
    {
      match: (post) => post.type === "page" && post.template === "front-page",
      config: {
        rootBlocks: ["#homepage-root", "content/hero"],
      },
    },
  ],
})

Entries can be eddev block names, WordPress core block names, or block tags. The framework default is ["root"], but our docs and new examples use explicit # tags such as ["#root"]. Core block tags are configured separately; see Core Blocks.

Templates

Templates let you insert blocks automatically.

export default defineEditorConfig({
  matchers: [
    {
      match: (post) => post.type === "case-study",
      config: {
        hideTitle: true,
        rootBlocks: ["#root"],
        headerTemplate: [["case-study/header", {}]],
        defaultBlocks: [["core/paragraph", {}]],
      },
    },
  ],
})
  • defaultBlocks are inserted when the post has no editable blocks.
  • headerTemplate keeps blocks at the top of the editor.
  • footerTemplate keeps blocks at the bottom of the editor.
  • template replaces the whole page with a locked block template.
  • hideTitle hides the standard WordPress title field when a block edits the title instead.

Template entries use eddev block names like page/page-header, not ACF names like acf/page-page-header.

Use template when the entire editing surface is fixed. Do not combine it with headerTemplate or footerTemplate.

Editor Wrapper Classes

Use generateBlockClassName to add classes around blocks in the WordPress editor. This does not change frontend markup.

import { BlockWrapperClassGenerator, defineEditorConfig } from "eddev/blocks"

const subpageClasses: BlockWrapperClassGenerator = (block) => {
  if (!block.isRootBlock) return

  if (block.flags?.sideRail) {
    return "admin-subpage-siderail"
  }

  if (!block.flags?.fullWidth) {
    return "col-subpage-content"
  }
}

export default defineEditorConfig({
  matchers: [
    {
      match: (post) => post.type === "page" && post.template === "default",
      config: {
        rootBlocks: ["#root", "#inline"],
        generateBlockClassName: subpageClasses,
      },
    },
  ],
})

The block object includes the block name, slug, tags, flags, parent lookup, root status, and selection/move/remove state. Flags are often the most maintainable way to make layout decisions without checking a long list of block names.

Patterns And Template Parts

Matchers can also target reusable WordPress patterns and template parts:

export default defineEditorConfig({
  matchers: [
    {
      match: (post) => post.isPattern,
      config: {
        rootBlocks: ["#inline"],
      },
    },
    {
      match: (post) => post.isTemplatePart && post.slug === "site-header",
      config: {
        rootBlocks: ["parts/part-site-header"],
      },
    },
  ],
})

For most projects, keep this limited to shared headers, footers, menus, and content patterns. See Template Parts for the current templatePart block metadata pattern.

Custom Rich Text Formats

customRichTextFormats registers extra formatting buttons for EditableText.

export default defineEditorConfig({
  customRichTextFormats: [
    {
      id: "site/label",
      title: "Label",
      className: "type-label",
      icon: "editor-textcolor",
      tagName: "span",
      disabledByDefault: true,
    },
  ],
})

If disabledByDefault is true, enable the format on individual fields:

<EditableText store="eyebrow" allowedFormats={["site/label"]} />

This is an advanced editor polish tool. Most block text should use the default formatting options, plainText, or allowedFormats={[]}.

On this page