Skip to content

Tailwind CSS + shadcn/ui — GE Design System

OWNER: alexander ALSO_USED_BY: floris, floor LAST_VERIFIED: 2026-03-26 GE_STACK_VERSION: tailwindcss ^4, shadcn ^3.8.4, class-variance-authority ^0.7.1, clsx ^2.1.1, tailwind-merge ^3.4.0, radix-ui ^1.4.3


Overview

Tailwind CSS v4 and shadcn/ui form the visual foundation of every GE client project. Tailwind v4 uses CSS-first configuration via @theme — no tailwind.config.js. shadcn/ui provides owned component source code built on Radix primitives. Agents use this page to understand how GE structures styling and UI components.


GE Design System Approach

CHECK: Every GE project starts from the same design token base. IF: A client project needs custom branding. THEN: Override semantic tokens in :root — never modify base tokens in @theme.

CHECK: shadcn/ui components live in components/ui/. IF: You need a project-specific variant. THEN: Create a wrapper in components/ that composes the ui/ primitive. THEN: Never edit components/ui/ files directly — they are the upgrade-safe base.


Tailwind v4 Configuration

Tailwind v4 is CSS-first. The entire config lives in your main CSS file.

CHECK: The project uses @import "tailwindcss" as the single entry point. IF: You see @tailwind base, @tailwind components, @tailwind utilities. THEN: You are looking at v3 syntax — migrate immediately.

CHECK: Design tokens are defined in @theme { } blocks. IF: You need a custom color, spacing value, or font. THEN: Add it inside @theme — Tailwind auto-generates utilities from it.

CHECK: Content detection is automatic in v4. IF: Files in .gitignore are being scanned. THEN: This is a bug — v4 respects .gitignore by default.

ANTI_PATTERN: Creating a tailwind.config.js file in a v4 project. FIX: All configuration belongs in CSS via @theme and @import.

ANTI_PATTERN: Using postcss-import or autoprefixer alongside v4. FIX: Tailwind v4 handles imports and vendor prefixing internally.


shadcn/ui as Component Base

shadcn/ui is not a dependency — it is copied source code you own. GE uses shadcn as the starting point, then customizes per project.

CHECK: Components are installed via npx shadcn@latest add <component>. IF: You need a component that shadcn provides. THEN: Install it first, then customize — never build from scratch.

CHECK: All shadcn components use Radix UI primitives underneath. IF: You need keyboard navigation, focus management, or ARIA. THEN: Radix handles it — do not re-implement accessibility.


GE Component Folder Structure

components/
  ui/           # Raw shadcn components (upgrade-safe, minimal edits)
  primitives/   # Lightly modified base components (GE defaults applied)
  blocks/       # Product-level compositions (cards, dashboards, forms)
  layout/       # Shell, sidebar, nav, footer

CHECK: A new component is being created. IF: It is a generic UI element (button, input, dialog). THEN: It belongs in components/ui/ via shadcn install. IF: It is a GE-specific composition of multiple primitives. THEN: It belongs in components/blocks/.


Key Utilities

GE uses three utilities together for className management:

  • clsx — conditional class joining
  • tailwind-merge — deduplicates conflicting Tailwind classes
  • cn() — the combined helper (clsx + tailwind-merge)

CHECK: Every component that accepts className as a prop. THEN: Use cn() to merge — never string concatenation.

import { cn } from "@/lib/utils"

export function Card({ className, ...props }) {
  return <div className={cn("rounded-lg border bg-card p-6", className)} {...props} />
}

Performance Notes

Tailwind v4's Oxide engine (Rust-based) delivers: - Full builds: under 100ms (was 3.5s in v3) - Incremental builds: single-digit milliseconds - No purge configuration needed — automatic tree-shaking


Cross-References

READ_ALSO: wiki/docs/stack/tailwind-shadcn/design-tokens.md READ_ALSO: wiki/docs/stack/tailwind-shadcn/component-patterns.md READ_ALSO: wiki/docs/stack/tailwind-shadcn/responsive.md READ_ALSO: wiki/docs/stack/tailwind-shadcn/pitfalls.md READ_ALSO: wiki/docs/stack/tailwind-shadcn/checklist.md READ_ALSO: wiki/docs/stack/nextjs/index.md