Installation

Set up Gaudi UI in your project and add patterns with the CLI.

The gaudi-ui CLI sets up your project once, then copies in the patterns you pick. It works in any React 19 + Tailwind CSS v4 project with an @/* path alias in tsconfig.json, or with your own aliases set in gaudi.json.

Initialize

npx gaudi-ui@latest init

This writes the files the patterns build on and installs the cn and @fontsource-variable/inter packages.

FileWhat it is
styles/theme.cssColors, radius and font
styles/typography.cssThe type scale
lib/cn.tsClass merging

Import the styles

In your main CSS file, import the font and both stylesheets after Tailwind:

styles/index.css

@import 'tailwindcss';
@import '@fontsource-variable/inter';
@import './theme.css';
@import './typography.css';

Isolate the app root

Base UI renders popups (Dialog, Popover, Menu, …) in portals. Give the app root its own stacking context so popups always sit above the page, and position body for iOS Safari:

styles/index.css

.root {
  isolation: isolate;
}

body {
  position: relative;
}

app/layout.tsx

<body>
  <div className="root">{children}</div>
</body>

Add patterns

Add a pattern by the name shown on its component's page:

npx gaudi-ui@latest add button-loading

Pass several names at once, run add alone to pick from a list, or use add --all.

Use them

Import a pattern like any other component in your project:

import ButtonLoading from '@/components/button/button-loading';

export function Toolbar() {
  return <ButtonLoading />;
}

Project structure

Files go under src/ when the project has one, the project root otherwise:

src/
├── styles/
│   ├── index.css
│   ├── theme.css
│   └── typography.css
├── lib/
│   └── cn.ts
└── components/
    └── button/
        └── button-loading.tsx

Patterns are grouped by component. They import shared code through @/, so @/* must point at the same folder:

tsconfig.json

{
  "compilerOptions": {
    "paths": { "@/*": ["./src/*"] }
  }
}

The CLI asks before replacing a file you already have. --yes keeps yours and --overwrite replaces it.

Each install is recorded in gaudi-lock.json at the project root: the item's version and a hash of every file written. The CLI uses it to find newer versions and to warn you before an update overwrites your edits, so keep it in git alongside your code. See Updating.

Monorepos and custom aliases

To install into a shared package, or with aliases other than @/, add a gaudi.json next to that package's package.json and run the CLI from there:

packages/ui/gaudi.json

{
  "$schema": "https://gaudi-ui.vercel.app/schema/config.json",
  "paths": {
    "components": "src/components",
    "lib": "src/lib",
    "styles": "src/styles"
  },
  "aliases": {
    "components": "@workspace/ui/components",
    "lib": "@workspace/ui/lib"
  }
}
  • paths sets where each group is written. Paths must stay inside the package.
  • aliases sets the import prefix; every @/… import is rewritten to match. styles takes no alias, since nothing imports it from code.
  • Groups you leave out keep the defaults. The groups are components, lib, hooks and styles.

CLI reference

CommandWhat it does
gaudi-ui initAdd the foundations and utilities, and their npm packages
gaudi-ui add <name...>Add items and everything they require
gaudi-ui add --allAdd every item
gaudi-ui listShow every item, patterns grouped by component
gaudi-ui outdatedList installed items that have a newer version
gaudi-ui changesShow what changed since your installed versions, as steps
gaudi-ui updateShow each item's changes and ask before replacing it
OptionEffect
--cwd <dir>Run against another project folder
--dir <dir>Write under this folder instead of src/. Not allowed when gaudi.json sets paths
--overwriteReplace files that already exist
-y, --yesSkip the prompts: keep files you already have and install npm packages. With update, replace the items you name; edited items also need --overwrite
--skip-installDon't install npm packages; print the command instead
--registry <url>Read from another registry (also GAUDI_REGISTRY_URL); a folder path works too
--from <version>changes: start after this version instead of the installed one
--diffchanges: include the line-by-line diff
--jsonWith outdated and changes, print JSON instead of text, for scripts and agents
--appliedWith update, mark the items you name as up to date after you've applied their changes by hand. Writes no files

The CLI picks your package manager from the lockfile (pnpm, yarn, bun or npm).

Registry

The CLI reads plain JSON from this site: /r/registry.json lists every item, and /r/<name>.json holds one item with its files, such as /r/button-loading.json. /r/changes/<name>.json lists the item's versions and what changed in each.

Without the CLI

Copy the files yourself:

  • Foundations and Utilities pages have the files every pattern builds on.
  • Each component page has a Manual tab with a pattern's source and the packages it needs.

Copied files aren't in gaudi-lock.json, so outdated and update skip them. To see what changed in an item, run:

npx gaudi-ui@latest changes <name> --from <version>