blocks/ already has the layout you want and you need to make it editable through Sanity Studio. The .astro component file stays completely unchanged — you only add the data pipeline.
For building an entirely new block with custom rendering, see Adding a custom block.
The adapter pattern
fulldev/ui template blocks define their ownProps interface. Sanity stores structured content. The GROQ projection acts as the adapter layer that reshapes Sanity output into the flat props the component expects:
The template block’s
Props interface is the contract you must satisfy. Read the component file first to understand every prop shape before writing the schema.Files touched per block
Wiring a template block requires changes to exactly 4 files. No.astro file is modified.
| File | What you add |
|---|---|
studio/src/schemaTypes/blocks/your-block.ts | New schema file — maps component props to Sanity field types |
studio/src/schemaTypes/index.ts | Import and register the new schema |
studio/src/schemaTypes/documents/page.ts | Add { type: 'your-block' } to the blocks[] array |
astro-app/src/lib/sanity.ts | Add the GROQ projection fragment |
Steps
Read the component's Props interface
Open the template block file to understand exactly what shape of data it expects. For example, Map each prop to a Sanity field type. Nested objects become object fields. Arrays become array fields. Image
hero-1.astro:src strings typically come from asset->url in GROQ.Create the Sanity schema
Create
studio/src/schemaTypes/blocks/hero-1.ts (use the kebab-case name matching the filename). Because this is a template block — not a custom block — you can use defineType directly rather than defineBlock, though defineBlock also works and gives you the base layout fields automatically.Register the schema in index.ts and page schema
In In the page schema (
studio/src/schemaTypes/index.ts:studio/src/schemaTypes/documents/page.ts), add to the blocks[] array:Add the GROQ projection and run typegen
Open Run typegen to generate TypeScript types for the new block:Verify the block renders in local dev:Add the block to a test page in Sanity Studio (
astro-app/src/lib/sanity.ts and add a projection fragment for the new block type inside the blocks[] projection. The projection must output fields that match the component’s Props interface exactly.http://localhost:3333) and confirm the fields appear and the rendered output matches the Storybook story for that block.Common patterns
Images
Template blocks typically expect{ src: string; alt: string }. Dereference the asset in GROQ:
asset->{ url, metadata { dimensions } } and extract width and height from dimensions.
Nested arrays of objects
When a prop islinks?: { text?: string; href?: string }[], the GROQ projection must preserve the array:
Portable Text
If a custom template block’s slot is populated by Portable Text (rare for template blocks), project it as an array and use@portabletext/astro to render it.
Icon names
fulldev/ui components use@iconify/utils icon names (e.g., lucide:arrow-right). Store these as string fields in Sanity — editors type the icon name directly, or you provide a predefined list.
Relationship to the block registry
The template block’s.astro file is already in blocks/ and is already registered in allBlocks with its kebab-case name as the key. The registry requires no changes.
After you add the Sanity schema, the block type name (e.g., hero-1) will match the key already in allBlocks['hero-1']. Blocks stored in Sanity with _type: 'hero-1' will dispatch to the correct component automatically.