Block Contracts: The Forgotten API

by Josh Oransky

Edge Delivery developers talk about blocks the way frontend developers talk about components: as a unit of UI. They are not. A block is an API contract between three parties (the author, the developer, and the framework), and the contract is encoded in the HTML structure the backend delivers to your decorator.

Treating that structure as accidental is how teams end up with blocks that work today and break the moment an author adds an extra row.

The three signatures

Every block has three signatures the team has to agree on, ideally before any code is written.

The authoring signature defines what the author types in the document. Number of rows, what each cell contains, optional vs. required, what variations are supported. This is the contract with the content team.

The DOM signature defines the HTML the backend hands to your decorator. Wrapper divs, cell positions, default text wrapping. This is the contract with the framework.

The output signature defines the final DOM after decoration. CSS class hooks, ARIA attributes, semantic landmarks, button affordances. This is the contract with the runtime and with accessibility tooling.

Most block bugs are mismatches between two of these three signatures. A common pattern: developer assumes one row, author adds a second; the decorator processes only the first row's cells and the second one renders raw. Nobody catches it until QA.

Designing the contract on purpose

Before you write the block decorator, write the contract. A README or a comment block at the top of the JS file does the job:

That last bullet is the one that separates blocks that survive production from ones that don't. Authors will add fields you didn't account for. They will omit ones you considered required. The block has to handle both without rendering broken markup to a customer.

Why the contract is "the forgotten API"

External integrations get OpenAPI specs. Internal services get type definitions. Block contracts get whatever lives in the developer's head plus a screenshot in Confluence. When the developer leaves, the contract leaves with them.

Write the contract down. Put it in the block's JS comment block, or in a sibling README. Keep it short: half a screen, not a manifesto. When the next developer touches the block, they can read what was actually agreed instead of reverse-engineering it from the decorator.

The author contract is just as much an API as the REST endpoint feeding your storefront. Treat it that way.