---
title: "shadcn/ui: Installation"
slug: "shadcn-installation"
category: "frontend"
tags: ["frontend", "shadcn", "react", "tailwind", "cli", "setup"]
status: "stable"
last_updated: 2026-08-14
summary: "Run the CLI init once, add components one at a time, and wire CSS variable theming (oklch, no tailwind.config, Tailwind v4 default) before touching any component."
related: ["[[frontend/shadcn]]", "[[frontend/shadcn-theming]]", "[[frontend/shadcn-composition]]", "[[frontend/tailwind]]", "[[frontend/react]]", "[[frontend/nextjs]]", "[[frontend/forms]]"]
---

## Overview

shadcn/ui installation is a one-time scaffold, not an npm dependency. The CLI writes components directly into your source tree. Getting the init step right prevents a class of problems: missing CSS variables, broken dark mode, Tailwind config mismatches, and component files that reference utilities you never set up. This page covers the sequence that avoids those issues.

## Run `init` once per project before adding any component

The `init` command writes `components.json`, the base CSS variables, and the utility helpers (`lib/utils.ts`) that every component imports. Run it before any `add` call.

```bash
npx shadcn@latest init
```

The CLI asks a handful of questions: TypeScript preference, base color, and the `globals.css` path. On a Tailwind v4 project (the current default) it does not ask for a `tailwind.config` path, because there is no config file to point at; theming lives entirely in `globals.css`. Answer accurately; the values are written to `components.json` and used on every subsequent `add` call. If you answer wrong, re-run `init` before proceeding rather than editing `components.json` by hand.

For Next.js with App Router, the CSS path is `app/globals.css`. See [[frontend/nextjs-app-router]] for the full App Router layout.

## Inspect `components.json` after init

`components.json` is the config the CLI reads on every `add`. The critical fields are `aliases`: they control the import paths written into every component file.

```json
{
  "style": "new-york",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "css": "app/globals.css",
    "baseColor": "neutral",
    "cssVariables": true
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  }
}
```

On a Tailwind v3 project, `tailwind.config` still points at `tailwind.config.ts`; the field is simply absent (or unused) once the project is on v4. Set `cssVariables: true` either way. The CSS-variable path keeps theming in one place; the raw Tailwind-color path hardcodes colors into every component and makes retheming expensive. See [[frontend/shadcn-theming]] for the full theming model.

## Add components one at a time as features need them

Install a component only when the next feature uses it. The CLI writes one file (plus peer files) per call.

```bash
npx shadcn@latest add button
npx shadcn@latest add dialog
npx shadcn@latest add form
npx shadcn@latest add table
```

Do not run a bulk add of the entire catalog. Each component adds code you will read in PRs, audit for accessibility, and occasionally edit. Dead components are dead weight in a layer you own. If a component is never imported, remove the file.

## Confirm peer dependencies are installed

The CLI installs Radix primitives and helpers (`class-variance-authority`, `tailwind-merge`, `clsx`) as it goes. Verify they landed in `package.json` after the first `add`.

```bash
npm ls class-variance-authority tailwind-merge clsx
```

If the package manager is Yarn or pnpm, the CLI may not auto-install them. Run the install step manually if you see missing-module errors. The `lib/utils.ts` file the CLI writes uses `tailwind-merge` directly, so a missing dep will fail at runtime, not build time.

## Confirm the CSS variables block landed in `globals.css`

Open `globals.css` after `init` and verify the `:root` and `.dark` blocks exist. A failed write (permission error, wrong path in `components.json`) leaves the block out and every component renders with broken tokens.

```css
:root {
  --background: oklch(1 0 0);
  --foreground: oklch(0.145 0 0);
  /* ... */
}
.dark {
  --background: oklch(0.145 0 0);
  --foreground: oklch(0.985 0 0);
}
```

The current CLI default writes full `oklch()` color functions, not the bare HSL channel triples used by older shadcn scaffolds. A project generated before the Tailwind v4 switch may still carry HSL channels (`--background: 0 0% 100%`) composed as `hsl(var(--background) / <alpha>)`; both formats work, but do not mix them within one token set. See [[frontend/shadcn-theming]] for how to change the palette.

## Wire Tailwind so the CSS variables become utilities

shadcn components use utilities like `bg-background`, `text-foreground`, and `border-border`. These work only if Tailwind maps those names to the CSS variables.

With Tailwind v4 (the current default), map the variables with `@theme inline` in `globals.css`; no `tailwind.config` file is involved:

```css
@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
}
```

With a legacy Tailwind v3 project, add `extend.colors` in `tailwind.config.ts` instead:

```ts
colors: {
  background: "hsl(var(--background) / <alpha-value>)",
  foreground: "hsl(var(--foreground) / <alpha-value>)",
}
```

The v3 `<alpha-value>` token is required for opacity utilities on the HSL-channel format. Without it, `bg-background/50` silently renders as fully opaque. On oklch tokens under Tailwind v4, `@theme inline` mapping handles opacity automatically through `color-mix()`. See [[frontend/tailwind]] for the broader Tailwind configuration.

## Commit `components/ui` as first-party code

Every file the CLI writes is yours. Commit it. There is no shadcn version to pin, no upgrade command, and no runtime package to audit. When upstream ships a fix for a component, read the diff on GitHub and port the relevant lines yourself.

Treat `components/ui/*.tsx` the same as any code you write: review it in PRs, lint it, and test any behavioral changes. See [[frontend/shadcn-composition]] for how to extend and compose the installed components.

## Related

- [[frontend/shadcn]]
- [[frontend/shadcn-theming]]
- [[frontend/shadcn-composition]]
- [[frontend/shadcn-forms]]
- [[frontend/tailwind]]
- [[frontend/react]]
- [[frontend/nextjs]]
