Imports flow downward only.
L1 — shared primitives
components/ui/
Foundational components installed from the registry — button, input, card, badge. They never
import from a higher layer, and they hold no business logic.
L2 — domain composites
Components that know about your domain — a weather card, a report row — built entirely from L1 primitives. This is the first layer allowed to know what the application is about.L3 — page orchestrators
Sections that arrange L2 composites into a region of a page. They arrange; they do not implement.L4 — error boundaries and loading states
Every L3 section is wrapped. A crashing chart shows a fallback where the chart was, and the rest of the page keeps working.L5 — server page wrappers
app/[route]/page.tsx. Data fetching and the route-level composition. This is where the
network lives, so it is the layer where a failure is expected rather than exceptional.
Why downward only
The rule is what buys the isolation. An L1 button that imported an L3 dashboard section would make the button untestable, un-installable into another project, and capable of taking a page down from inside a design system component. Each of those is a real failure mode; the import direction removes all three at once.The design portal hosts an interactive demonstration of all five layers, where each section
is wrapped in a
SectionErrorBoundary and you can trigger a crash to watch the isolation
hold. That live React surface does not port to this documentation site.