Now with AI-powered page building via MCP Server
Documentation

Block Development Guide

Build custom blocks for your headless cmssy site - defineBlock, fields, the block component, and context.

Last updated: June 7, 2026

Block anatomy

A cmssy block lives in your own Next.js repo as a folder under blocks/:

  • block.ts — declares the block with defineBlock + fields (its type, label, and editable schema)
  • src/index.tsx — the React component that renders the content

Register the block in cmssy/blocks.ts. The editor reads each block's schema over the SDK bridge, so adding a block to a page renders an editor form from your fields.


Define a block

import type { ComponentType } from "react";
import { defineBlock, fields } from "@cmssy/react";
import Component from "./src";

export const heroBlock = defineBlock({
  type: "hero",
  label: "Hero",
  component: Component as unknown as ComponentType<{ content: Record<string, unknown> }>,
  props: {
    heading: fields.singleLine({ label: "Heading", defaultValue: "Welcome" }),
    body: fields.richText({ label: "Body" }),
    ctaUrl: fields.link({ label: "CTA URL", defaultValue: "/signup" }),
    showCta: fields.boolean({ label: "Show CTA", defaultValue: true }),
  },
});

Field types: singleLine, multiLine, richText, numeric, date, media, link, select, multiselect, boolean, color, repeater. See Schema & Field Types.


The block component

Blocks receive { content, context }. The content is already resolved for the active locale, so read fields directly.

import type { CmssyBlockContext } from "@cmssy/react";

export default function Hero({ content, context }: {
  content: Record<string, unknown>;
  context?: CmssyBlockContext;
}) {
  const locale = context?.locale.current ?? "en";
  const isPreview = context?.isPreview ?? false;
  return <section><h1>{String(content.heading ?? "")}</h1></section>;
}

context is { locale: { current, default, enabled }, isPreview }. Locale-aware UI reads context.locale.enabled. Auth and form definitions are not in context in headless — fetch them via createCmssyClient.


Register & ship

// cmssy/blocks.ts
import { heroBlock } from "@/blocks/hero/block";
export const blocks = [heroBlock];

Run pnpm dev, open the page editor, and your block appears in the picker. Deploy your Next.js app to ship — there is no separate block build or publish step.


Next Steps

Start building blocks

Set up the SDK, then create and register your first block.

Block Development Guide - Cmssy Headless SDK