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.tsx
    May 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.tsx
    May import: primitives
  • blocks/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.tsx
    May import: primitives, graphics
  • components/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.tsx
    May 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-header
    May 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";
  • Pure UI, no Sitecore, no business logic? primitives
  • A composite of primitives, still CMS-agnostic? blocks
  • Consumes withSitecore or a Sitecore field type? components
  • A whole sample page or partial design? experiences
  • An icon set or illustration? graphics