Most CMS integrations rot quietly. An editor renames a field, a developer refactors a query, and nothing complains — until a section renders blank in production three weeks later. Nuxion is built so that class of bug can't ship. The chain from a Sanity schema to a rendered Vue component is typed end-to-end and enforced at build time.
Here's the core idea: every block is three files that stay in lockstep — a schema, a component, and a single registry entry that ties the two together by _type. Break the contract, and the type check fails.
The registry is the source of truth
ComponentRenderer.vue resolves each block's _type against a merged registry of web and custom components, then binds the block's data onto the resolved component. The registry key must match the schema name exactly:
'custom.features-grid': {
element: defineAsyncComponent(() => import('./CustomFeaturesGrid.vue')),
props: { ...data },
},Because the key is a literal union derived from your schemas, a typo here is a red squiggle, not a silent miss.
The rename test
testRenametitletoheadingin a schema and runnpm run typecheck. Every query and component that still readstitlelights up. Fix them, and only then does the build pass.
Projections keep GROQ typed
Typed queries live in groq-queries.ts and flow through useSanityQuery<T>() with TypeGen-generated types. The default spread covers colors and images; link.group and portable-text fields usually need an explicit projection entry.
"If it compiles, the CMS wiring is correct. That's the whole promise — you stop testing the plumbing and go build."
Scaffold, don't hand-wire
You almost never write those three files by hand. The scaffolder generates the schema, a typed component, every registration, and regenerates types in one command — the block is immediately insertable in Studio:
npm run scaffold:component -- custom.testimonialFrom there it's ordinary Vue. Bind the typed data, reach for shared element types like link.group and portable-text instead of reinventing them, and let PageSection own width and gutter so your block only handles vertical rhythm and content.
The payoff compounds. Every block you add inherits the same guarantees, so a project with forty custom sections is exactly as safe to refactor as one with four.
