Component tiers
The Showcase design system is organised into five tiers. Each tier can only import from the tiers below it — never sideways and never upward. Knowing which tier you're working in tells you what you're allowed to depend on and what shape your code should take.
Boundaries keep concerns separated and changes safe:
- Reuse. A primitive can be used in any Sitecore-aware component, but the reverse is impossible — that's how a low-level button stays usable everywhere.
- Portability. Blocks are CMS-agnostic, so they can ship to projects that aren't on Sitecore.
- Lockable surfaces. Authors interact with the components and experiences tier. The lower tiers are build-time abstractions.
primitives/Leaf-level UI atoms.Buttons, inputs, badges, cards — pure React, no Sitecore awareness, no business logic. Built on Radix UI and Tailwind.
Example:primitives/core/button.tsxMay import: Nothing upward. Primitives are leaves.graphics/Icons and illustrations.Icon registries and illustration components. Reachable from every tier above but composed only out of primitives.
Example:graphics/icon.tsxMay import: primitivesblocks/CMS-agnostic composites.Multi-primitive React components with no Sitecore coupling. Action bars, carousels, chat messages — building blocks you could drop into any React app.
Example:blocks/action-bar.tsxMay import: primitives, graphicscomponents/Sitecore-aware components.The tier that consumes withSitecore, ships a .sitecore.ts adapter, or imports a Sitecore Edge schema. This is what authors place on a page.
Example:components/cards-and-lists/item-carousel.tsxMay import: blocks, primitives, graphics (never peer components)experiences/Top-level compositions.Whole-page recipes — partial designs, page items, and sample experiences. The composition layer customers ship as starter content.
Example:experiences/standard-headerMay import: components, blocks, primitives, graphics
Imports flow strictly downward. Every arrow in the diagram below is allowed; anything not in the diagram isn't.
experiences ──▶ components, blocks, primitives, graphics
components ──▶ blocks, primitives, graphics
blocks ──▶ primitives, graphics
graphics ──▶ primitives
primitives ──▶ (leaf)A valid import
// blocks/promo-card.tsx — a block importing primitives
import { Button } from "@/components/registry/primitives/core/button";
import { Card } from "@/components/registry/primitives/core/card";
export function PromoCard({ title }: { title: string }) {
return (
<Card>
<h3>{title}</h3>
<Button>Learn more</Button>
</Card>
);
}An invalid import
// blocks/promo-card.tsx — DON'T do this
// A block reaching "up" into a Sitecore-aware component is a boundary
// violation. blocks must stay CMS-agnostic.
import { ItemCarousel } from "@/components/registry/components/cards-and-lists/item-carousel";tests/architecture.test.ts) fails the build if any file imports across a forbidden edge. You don't have to memorise the rules — the test catches them.- Pure UI, no Sitecore, no business logic? →
primitives - A composite of primitives, still CMS-agnostic? →
blocks - Consumes
withSitecoreor a Sitecore field type? →components - A whole sample page or partial design? →
experiences - An icon set or illustration? →
graphics