Skip to main content
The Node.js website uses a dual-package architecture for React components. Understanding which package a component belongs in is the first decision you make when building new UI.

The two packages

@node-core/ui-components

Reusable, framework-agnostic components published to npm. No Next.js dependencies. Includes Common, Containers, Icons, MDX utilities, and hooks.

apps/site/components

Next.js-specific components that wrap ui-components with routing, i18n, theming, and other framework features.

Choosing the right package

Before creating a component, answer one question: does it need Next.js APIs?
NeedsPackage
Routing (usePathname, useRouter)apps/site/components
Internationalization (useTranslations, useLocale)apps/site/components
Theming (useTheme from next-themes)apps/site/components
Dynamic imports (next/dynamic)apps/site/components
Pure UI, no framework coupling@node-core/ui-components
When in doubt, build the base component in @node-core/ui-components and write a thin wrapper in apps/site/components that injects the framework-specific behavior.

The wrapper pattern

Many site components exist solely to connect a base UI component to Next.js. The base component accepts plain props; the wrapper reads from Next.js hooks and passes them down.
// Base component — @node-core/ui-components
const BaseNavLink: FC<BaseLinkProps> = ({ href, isActive, children }) => (
  <a href={href} className={`${styles.link} ${isActive ? styles.active : ''}`}>
    {children}
  </a>
);

// Wrapper — apps/site/components
const NavLink: FC<NavLinkProps> = ({ href, children }) => {
  const pathname = usePathname();
  const isActive = pathname === href;

  return (
    <BaseNavLink href={href} isActive={isActive}>
      {children}
    </BaseNavLink>
  );
};
This pattern keeps the UI library free of Next.js and makes components testable in isolation (and in Storybook) without a Next.js runtime.

Explore the component system

Creating components

File structure, TypeScript templates, and naming conventions.

UI components

Everything in the @node-core/ui-components package.

Site components

The Next.js layer — withNavBar, withFooter, withSidebar, and more.

CSS Modules

How component styles are scoped and structured.

Tailwind CSS

Using @apply and Tailwind v4 utilities inside CSS Modules.

Unit tests

Testing components with Node.js built-in test runner.

Storybook

Writing stories for @node-core/ui-components.

Visual regression

Automated screenshot testing with Chromatic.

Build docs developers (and LLMs) love