115k

Changelog

RSS

Latest updates and announcements.

May 2026 - Registry Include and Validate

This release adds two updates for registry authors:

  • include for composing large source registries from multiple registry.json files.
  • shadcn registry validate for checking source registries before publishing.

This makes it easier to maintain source and dynamic registries without keeping one large registry.json file by hand.

Registry authors can now organize a large source registry across multiple registry.json files and compose them with shadcn build.

registry.json
components
└── ui
    ├── button.tsx
    ├── input.tsx
    └── registry.json
hooks
├── registry.json
├── use-media-query.ts
└── use-toggle.ts
registry.json
{
  "$schema": "https://ui.shadcn.com/schema/registry.json",
  "name": "acme",
  "homepage": "https://acme.com",
  "include": [
    "components/ui/registry.json",
    "hooks/registry.json"
  ]
}

Included registry.json files are valid registry files for composition and may omit name and homepage. Only the root registry.json must define the registry metadata.

components/ui/registry.json
{
  "$schema": "https://ui.shadcn.com/schema/registry.json",
  "items": [
    {
      "name": "button",
      "type": "registry:ui",
      "files": [
        {
          "path": "button.tsx",
          "type": "registry:ui"
        }
      ]
    }
  ]
}

Build output

shadcn build resolves included registries and writes a flattened registry.json without include. Item file paths are preserved from the root registry, so a file declared in components/ui/registry.json is written as components/ui/button.tsx in the built registry item.

Validate your registry

You can now validate a source registry before publishing or serving it.

pnpm dlx shadcn registry validate

Validation runs against the source registry files directly. You do not need to run shadcn build first.

The command checks the root registry.json, included registry files, item schema errors, duplicate item names, include rules, and local item file paths. Validation reports all actionable errors it can find in one run.

Registry loaders

The shadcn/registry package also exports loadRegistry and loadRegistryItem for dynamic registry routes.

app/r/registry.json/route.ts
import { loadRegistry } from "shadcn/registry"
 
export async function GET() {
  const registry = await loadRegistry()
 
  return Response.json(registry)
}
app/r/[name].json/route.ts
import { loadRegistryItem } from "shadcn/registry"
 
export async function GET(
  _: Request,
  { params }: { params: Promise<{ name: string }> }
) {
  const { name } = await params
  const item = await loadRegistryItem(name)
 
  return Response.json(item)
}

See the registry.json documentation and getting started guide for more details.

May 2026 - Package Imports and Target Aliases

We've added support for package imports and aliases in files.target in shadcn@4.7.0.

Package imports

The shadcn CLI now supports package.json#imports for installing components, rewriting imports, and resolving third-party registries. You can use private #... import aliases from your package.json instead of relying only on compilerOptions.paths in tsconfig.json.

package.json
{
  "imports": {
    "#components/*": "./src/components/*.tsx",
    "#lib/*": "./src/lib/*.ts",
    "#hooks/*": "./src/hooks/*.ts"
  }
}

Then use the same roots in components.json:

components.json
{
  "aliases": {
    "components": "#components",
    "ui": "#components/ui",
    "lib": "#lib",
    "hooks": "#hooks",
    "utils": "#lib/utils"
  }
}

This also works in monorepos where app-local files use package imports and shared UI files are imported from workspace package exports.

See the package imports guide for setup details.

Target aliases

Registry items can now use target aliases in files[].target to install files under the user's configured shadcn directories. For example, the following registry item will install the prompt-input.tsx file under the ui/ai directory.

example.json
{
  "files": [
    {
      "path": "registry/default/ai/prompt-input.tsx",
      "type": "registry:ui",
      "target": "@ui/ai/prompt-input.tsx"
    }
  ]
}

See the registry examples for more details.

April 2026 - shadcn preset

We added shadcn preset commands for working with preset codes.

Decode a preset

You can decode a preset code to see exactly what it contains:

pnpm dlx shadcn@latest preset decode b5owWMfJ8l
Preset
  code         b5owWMfJ8l
  version      b
  style        mira
  baseColor    mauve
  theme        mauve
  chartColor   amber
  iconLibrary  hugeicons
  font         inter
  fontHeading  oxanium
  radius       large
  menuAccent   subtle
  menuColor    inverted-translucent
  url          https://ui.shadcn.com/create?preset=b5owWMfJ8l

Resolve from a project

Use preset resolve in an existing project to see the preset that matches your current configuration.

pnpm dlx shadcn@latest preset resolve
Preset
  code         b5Kc6P0Vc
  version      b
  style        luma
  baseColor    olive
  theme        lime
  chartColor   sky
  iconLibrary  hugeicons
  font         geist
  fontHeading  inherit
  radius       default
  menuAccent   subtle
  menuColor    default
  url          https://ui.shadcn.com/create?preset=b5Kc6P0Vc

It works with monorepos too:

pnpm dlx shadcn@latest preset resolve -c apps/web

Share or open

Use preset url when you need a shareable link:

pnpm dlx shadcn@latest preset url b5owWMfJ8l
https://ui.shadcn.com/create?preset=b5owWMfJ8l

Use preset open to open the preset on shadcn/create for customization:

pnpm dlx shadcn@latest preset open b5owWMfJ8l
Opening https://ui.shadcn.com/create?preset=b5owWMfJ8l in your browser.

This makes presets easier to inspect, share, and hand off to coding agents without manually decoding codes or building URLs.

Try a Preset

April 2026 - Pointer Cursor

You can now enable cursor: pointer for buttons when initializing a project.

pnpm dlx shadcn@latest init --pointer

This adds the following CSS to your global CSS file:

globals.css
@layer base {
  button:not(:disabled),
  [role="button"]:not(:disabled) {
    cursor: pointer;
  }
}

The --pointer option is not part of preset codes. It is applied as a project setup option, similar to --rtl.

April 2026 - Partial Preset Apply

You can now selectively apply a preset.

Say someone shares a preset with you and you already have your own components, but you like the theme or the fonts. Now you can apply just that.

Keep your components. Apply only what you want.

# Apply the full preset.
npx shadcn@latest apply --preset b2D0vQ7G4
 
# Apply only the theme.
npx shadcn@latest apply --preset b2D0vQ7G4 --only theme
 
# Apply only the fonts.
npx shadcn@latest apply --preset b2D0vQ7G4 --only font
 
# Apply theme and fonts.
npx shadcn@latest apply --preset b2D0vQ7G4 --only theme,font

The default behavior is unchanged. Running shadcn apply --preset <preset> still applies the full preset.

Partial preset apply currently supports theme and font.

Try a Preset