Overview
The basics of creating Gutenberg blocks
Blocks are the main editing unit for page content. In an eddev theme, a block is usually a React component in blocks/**/*.tsx, with optional metadata and a paired GraphQL query.
Most sites only need a small set of block conventions:
blocks/content/section.tsxdefines a block component.blocks/content/section.graphqlselects the ACF or WordPress data passed to that component.blocks/_editor.tsxcontrols which blocks authors can add for each post type or template.blocks/_core.tsxoptionally replaces the frontend rendering of WordPress core blocks.- Views render block content with
<ContentBlocks blocks={props.page?.contentBlocks} />.
The Short Version
import { defineBlock, EditableText, InnerBlocks } from "eddev/blocks"
export const meta: BlockMeta = {
title: "Section",
tags: ["#root"],
}
export default defineBlock("content/section", () => {
return (
<section className="grid-auto">
<div className="col-span-12 md:col-span-3">
<EditableText as="h2" store="title" defaultValue="Enter a title" />
</div>
<div className="col-span-12 md:col-span-9">
<InnerBlocks allowedBlocks={["#inline"]} />
</div>
</section>
)
})defineBlock("content/section", ...) should match the file path without blocks/ or .tsx. This is what lets generated block props line up with the right component.
Data Flow
Block data is not passed straight from ACF into React. eddev parses Gutenberg content in WordPress, runs the matching blocks/**/*.graphql query for each ACF block, and sends the selected data to React as typed props.
That extra query step is useful: a block can select exactly the fields it needs, follow relationships like post objects or media fields, and reuse fragments from queries/fragments.
Editor Flow
The editor is configured separately from individual blocks. Use block tags for broad authoring contexts like #root, #inline, or #card-grid-item, then use blocks/_editor.tsx to decide which tags or block names are available for a given post type or template.
Keep the first pass simple:
- define the block component
- add ACF fields only when inline editing is not enough
- add a GraphQL file only for data the component needs
- constrain where it appears with tags and editor config
The rest of this section covers those pieces in that order.