Capítulo 18 de 108

Installation: Manual

Core Idea

Full manual setup without the CLI: install deps, configure aliases, add the theme CSS, write the cn helper, and hand-author components.json. Useful for frameworks the CLI doesn't support or for full control.

Key Concepts

  • Required deps: shadcn class-variance-authority clsx tailwind-merge lucide-react tw-animate-css.
  • cn helper: clsx + tailwind-merge wrapper, the utility every component uses to merge className props.
  • Two alias options: tsconfig.json paths (@/*) or package.json#imports (#components/* etc., needs moduleResolution: "bundler" + resolvePackageJsonImports: true).
  • components.json is hand-authored here, not generated by init.

Code Examples

npm install shadcn class-variance-authority clsx tailwind-merge lucide-react tw-animate-css
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "base-nova",
  "rsc": false,
  "tsx": true,
  "tailwind": {
    "config": "",
    "css": "src/styles/globals.css",
    "baseColor": "neutral",
    "cssVariables": true,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "hooks": "@/hooks"
  },
  "iconLibrary": "lucide"
}
  • O que demonstra: components.json mínimo e completo escrito à mão, sem depender de init.
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";

@custom-variant dark (&:is(.dark *));
  • O que demonstra: os três imports obrigatórios no topo do CSS global (Tailwind, tw-animate-css, shadcn/tailwind.css) mais o dark custom variant.

Anti-patterns

  • Skipping @import "shadcn/tailwind.css": loses shared utilities like data-open:/data-closed: custom variants and accordion animations that CLI-installed components rely on.
  • Mismatched aliases between components.json and tsconfig/package.json#imports: components install to the wrong path or fail to resolve.

Key Takeaways

  1. Manual install is the ground truth for what shadcn init automates: deps, aliases, theme CSS, cn helper, components.json.
  2. Using package.json#imports requires mirroring the same #... alias roots in components.json's aliases block.
  3. After this setup, components can still be added the normal way with npx shadcn add <component>, manual install only replaces init, not add.

Connects To

  • components-json: full field reference for the file authored here.
  • theming: explains every CSS variable defined in the globals.css block.
  • cli: init is what this chapter replicates by hand.