Dyrecteddyrected
Recipes

Build Flexible Pages from Reusable Blocks

Model editor-controlled layouts with stable block contracts.

Blocks work well when editors choose from a bounded design vocabulary and the frontend owns rendering.

Define labeled hero, rich-text, and call-to-action blocks for an editor-controlled page layout.

Use this when

  • build a page builder
  • let editors arrange page sections
  • create reusable content blocks
  • model flexible landing pages

Dyrected concepts

blocks, Block, content modeling

Additional packages: No additional packages.

Complete recipe

This is the canonical source compiled and behavior-tested by @dyrected/knowledge.

import { defineBlock, defineBlocksField, defineCollection, defineTextField, defineTextareaField, defineUrlField } from "@dyrected/core";

export const HeroBlock = defineBlock({
  slug: "hero",
  labels: { singular: "Hero", plural: "Heroes" },
  fields: [
    defineTextField({ name: "heading", label: "Heading", required: true }),
    defineTextareaField({ name: "body", label: "Body" }),
  ],
});

export const CallToActionBlock = defineBlock({
  slug: "callToAction",
  labels: { singular: "Call to action", plural: "Calls to action" },
  fields: [
    defineTextField({ name: "label", label: "Link label", required: true }),
    defineUrlField({ name: "url", label: "URL", required: true }),
  ],
});

export const Pages = defineCollection({
  slug: "pages",
  fields: [
    defineTextField({ name: "title", label: "Title", required: true }),
    defineBlocksField({
      name: "layout",
      label: "Page layout",
      blocks: [HeroBlock, CallToActionBlock],
    }),
  ],
});

Decisions and cautions

  • Keep block slugs stable; they are persisted as blockType.
  • Render unknown block types safely during rolling deployments.
  • Add new optional fields with compatible defaults and migrate removed/renamed fields deliberately.
  • Avoid a block for every cosmetic variation. Model content meaning first and keep layout variants constrained.

Use an array when every item has one shape. Use related collections when entries need independent reuse, permissions, or querying.

On this page