Guía de desarrollo de bloques
Crea bloques personalizados para tu sitio headless de Cmssy - defineBlock, fields, el componente del bloque y el context.
Anatomía de un bloque
Un bloque de Cmssy vive en tu propio repo de Next.js como una carpeta dentro de blocks/:
- block.ts — declara el bloque con
defineBlock+fields(su tipo, etiqueta y esquema editable) - Hero.tsx — el componente React que renderiza el contenido
Registra el bloque en cmssy/blocks.ts. El editor lee el esquema de cada bloque a través del puente del SDK, así que al añadir un bloque a una página se renderiza un formulario de edición a partir de tus fields.
Definir un bloque
// blocks/hero/block.ts
import { defineBlock, fields } from "@cmssy/react";
import Hero from "./Hero";
// Exportado aparte, para que el componente derive de él sus props.
export const heroProps = {
heading: fields.text({ 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 }),
};
export const heroBlock = defineBlock({
type: "hero",
label: "Hero",
component: Hero,
props: heroProps,
});
Tipos de campo: text, textarea, richText, markdown, number, date, datetime, boolean, color, media, link, url, email, select, radio, multiselect, relation, repeater, table, json, form, pageSelector. Consulta Esquema y tipos de campo.
El componente del bloque
Los bloques reciben { content, context, data }. El contenido ya está resuelto para el idioma activo, así que lee los campos directamente.
// blocks/hero/Hero.tsx
import type { BlockProps } from "@cmssy/react";
import { heroProps } from "./block";
export default function Hero({ content, context }: BlockProps<typeof heroProps>) {
// Tipado desde el esquema: heading es string, showCta es boolean.
const { heading, showCta, ctaUrl } = content;
const isPreview = context?.isPreview ?? false;
return (
<section>
<h1>{heading}</h1>
{showCta && <a href={ctaUrl}>Get started</a>}
</section>
);
}
BlockProps<typeof heroProps> hace del esquema el único sitio donde se nombra un campo. Renombra heading y el componente deja de compilar, en vez de renderizar nada en silencio, que es lo que habría hecho leer content.heading de un Record<string, unknown>. Si el bloque tiene loader, pasa su tipo de retorno como segundo argumento: BlockProps<typeof heroProps, Posts> tipa también la prop data.
context lleva locale ({ current, default, enabled }) e isPreview (true dentro del editor), además de forms para cualquier formulario que el bloque referencie. auth y workspace aparecen cuando tu app los aporta mediante buildBlockContext. La UI sensible al idioma lee context.locale.enabled. Para tus propios modelos o registros usa createCmssyClient; para cargar durante el SSR añade un loader y lee su resultado desde data. Consulta Funciones avanzadas y Loaders de servidor.
Registrar y publicar
// cmssy/blocks.ts
import { heroBlock } from "@/blocks/hero/block";
export const blocks = [heroBlock];
Ejecuta pnpm dev, abre el editor de páginas y tu bloque aparecerá en el selector. Despliega tu app de Next.js para publicar — no hay un paso separado de build o publicación de bloques.
Próximos pasos
- Esquema y tipos de campo — todos los tipos de campo, repeaters, campos condicionales, grupos
- Funciones avanzadas — bloques de layout, estilos, loaders de servidor