feat: use REGISTRY_URL

This commit is contained in:
shadcn
2026-03-04 13:01:04 +04:00
parent 02f34a3b31
commit aa4a97730a
15 changed files with 61 additions and 39 deletions

View File

@@ -1,6 +1,7 @@
import * as fs from "fs/promises"
import * as path from "path"
import { preFlightBuild } from "@/src/preflights/preflight-build"
import { SHADCN_URL } from "@/src/registry/constants"
import { registryItemSchema, registrySchema } from "@/src/schema"
import { handleError } from "@/src/utils/handle-error"
import { highlighter } from "@/src/utils/highlighter"
@@ -57,7 +58,7 @@ export const build = new Command()
// Add the schema to the registry item.
registryItem["$schema"] =
"https://ui.shadcn.com/schema/registry-item.json"
`${SHADCN_URL}/schema/registry-item.json`
// Loop through each file in the files array.
for (const file of registryItem.files ?? []) {

View File

@@ -1,5 +1,6 @@
import { existsSync } from "fs"
import path from "path"
import { SHADCN_URL } from "@/src/registry/constants"
import { getBase, getConfig } from "@/src/utils/get-config"
import {
formatMonorepoMessage,
@@ -143,11 +144,11 @@ function collectInfo(
: null,
components,
links: {
docs: "https://ui.shadcn.com/docs",
components: `https://ui.shadcn.com/docs/components/${base}/[component].md`,
docs: `${SHADCN_URL}/docs`,
components: `${SHADCN_URL}/docs/components/${base}/[component].md`,
ui: `${GITHUB_RAW_BASE}/${base}/ui/[component].tsx`,
examples: `${GITHUB_RAW_BASE}/${base}/examples/[component]-example.tsx`,
schema: "https://ui.shadcn.com/schema.json",
schema: `${SHADCN_URL}/schema.json`,
},
}
}

View File

@@ -10,7 +10,7 @@ import {
resolveRegistryBaseConfig,
} from "@/src/preset/presets"
import { getRegistryBaseColors, getRegistryStyles } from "@/src/registry/api"
import { BUILTIN_REGISTRIES } from "@/src/registry/constants"
import { BUILTIN_REGISTRIES, SHADCN_URL } from "@/src/registry/constants"
import { clearRegistryContext } from "@/src/registry/context"
import { registryConfigSchema } from "@/src/registry/schema"
import { isUrl } from "@/src/registry/utils"
@@ -317,7 +317,7 @@ export const init = new Command()
)
logger.log(
` See ${highlighter.info(
"https://ui.shadcn.com/docs/installation/laravel"
`${SHADCN_URL}/docs/installation/laravel`
)} for more information.`
)
logger.break()
@@ -813,7 +813,7 @@ async function promptForConfig(defaultConfig: Config | null = null) {
}
return rawConfigSchema.parse({
$schema: "https://ui.shadcn.com/schema.json",
$schema: `${SHADCN_URL}/schema.json`,
style: options.style,
tailwind: {
config: options.tailwindConfig,

View File

@@ -1,6 +1,7 @@
import * as fs from "fs/promises"
import * as path from "path"
import { preFlightRegistryBuild } from "@/src/preflights/preflight-registry"
import { SHADCN_URL } from "@/src/registry/constants"
import { recursivelyResolveFileImports } from "@/src/registry/utils"
import { configSchema, registryItemSchema, registrySchema } from "@/src/schema"
import * as ERRORS from "@/src/utils/errors"
@@ -121,7 +122,7 @@ async function buildRegistry(opts: z.infer<typeof buildOptionsSchema>) {
// Add the schema to the registry item.
registryItem["$schema"] =
"https://ui.shadcn.com/schema/registry-item.json"
`${SHADCN_URL}/schema/registry-item.json`
for (const file of registryItem.files) {
const absPath = path.resolve(resolvePaths.cwd, file.path)

View File

@@ -1,5 +1,6 @@
import { promises as fs } from "fs"
import path from "path"
import { SHADCN_URL } from "@/src/registry/constants"
import { Config } from "@/src/utils/get-config"
import { highlighter } from "@/src/utils/highlighter"
import { logger } from "@/src/utils/logger"
@@ -15,7 +16,7 @@ const FILES_NEEDING_MANUAL_REVIEW = [
"calendar.tsx",
]
const RTL_DOCS_URL = "https://ui.shadcn.com/docs/rtl#manual-migration-optional"
const RTL_DOCS_URL = `${SHADCN_URL}/docs/rtl#manual-migration-optional`
export async function migrateRtl(
config: Config,

View File

@@ -1,5 +1,6 @@
import path from "path"
import { addOptionsSchema } from "@/src/commands/add"
import { SHADCN_URL } from "@/src/registry/constants"
import * as ERRORS from "@/src/utils/errors"
import { getConfig } from "@/src/utils/get-config"
import {
@@ -66,7 +67,7 @@ export async function preFlightAdd(options: z.infer<typeof addOptionsSchema>) {
)
logger.error(
`Learn more at ${highlighter.info(
"https://ui.shadcn.com/docs/components-json"
`${SHADCN_URL}/docs/components-json`
)}.`
)
logger.break()

View File

@@ -1,6 +1,7 @@
import path from "path"
import { addOptionsSchema } from "@/src/commands/add"
import { migrateOptionsSchema } from "@/src/commands/migrate"
import { SHADCN_URL } from "@/src/registry/constants"
import * as ERRORS from "@/src/utils/errors"
import { getConfig } from "@/src/utils/get-config"
import { highlighter } from "@/src/utils/highlighter"
@@ -55,7 +56,7 @@ export async function preFlightMigrate(
)
logger.error(
`Learn more at ${highlighter.info(
"https://ui.shadcn.com/docs/components-json"
`${SHADCN_URL}/docs/components-json`
)}.`
)
logger.break()

View File

@@ -1,7 +1,7 @@
import { getRegistryItems } from "@/src/registry/api"
import { buildUrlAndHeadersForRegistryItem } from "@/src/registry/builder"
import { configWithDefaults } from "@/src/registry/config"
import { REGISTRY_URL } from "@/src/registry/constants"
import { REGISTRY_URL, SHADCN_URL } from "@/src/registry/constants"
import { type registryConfigSchema } from "@/src/registry/schema"
import { createConfig } from "@/src/utils/get-config"
import { highlighter } from "@/src/utils/highlighter"
@@ -11,8 +11,6 @@ import open from "open"
import prompts from "prompts"
import { type z } from "zod"
const SHADCN_URL = REGISTRY_URL.replace(/\/r\/?$/, "")
export const DEFAULT_PRESETS = {
nova: {
title: "Nova",
@@ -174,7 +172,7 @@ export async function promptForPreset(options: {
})),
{
title: "Custom",
description: "Build your own on https://ui.shadcn.com/create",
description: `Build your own at ${highlighter.info(`${SHADCN_URL}/create`)}`,
value: "custom",
},
],

View File

@@ -4,6 +4,8 @@ import { z } from "zod"
export const REGISTRY_URL =
process.env.REGISTRY_URL ?? "https://ui.shadcn.com/r"
export const SHADCN_URL = REGISTRY_URL.replace(/\/r\/?$/, "")
export const FALLBACK_STYLE = "new-york-v4"
export const BASE_COLORS = [
@@ -11,10 +13,6 @@ export const BASE_COLORS = [
name: "neutral",
label: "Neutral",
},
{
name: "gray",
label: "Gray",
},
{
name: "zinc",
label: "Zinc",
@@ -24,8 +22,20 @@ export const BASE_COLORS = [
label: "Stone",
},
{
name: "slate",
label: "Slate",
name: "mauve",
label: "Mauve",
},
{
name: "olive",
label: "Olive",
},
{
name: "mist",
label: "Mist",
},
{
name: "taupe",
label: "Taupe",
},
] as const

View File

@@ -1,3 +1,4 @@
import { SHADCN_URL } from "@/src/registry/constants"
import { z } from "zod"
// Error codes for programmatic error handling
@@ -245,7 +246,7 @@ export class RegistryParseError extends RegistryError {
cause: parseError,
context: { item },
suggestion:
"The registry item may be corrupted or have an invalid format. Please make sure it returns a valid JSON object. See https://ui.shadcn.com/schema/registry-item.json.",
`The registry item may be corrupted or have an invalid format. Please make sure it returns a valid JSON object. See ${SHADCN_URL}/schema/registry-item.json.`,
})
this.parseError = parseError

View File

@@ -1,3 +1,4 @@
import { SHADCN_URL } from "@/src/registry/constants"
import { highlighter } from "@/src/utils/highlighter"
import { logger } from "@/src/utils/logger"
@@ -19,7 +20,7 @@ export const laravel = createTemplate({
)
logger.log(
` See ${highlighter.info(
"https://ui.shadcn.com/docs/installation/laravel"
`${SHADCN_URL}/docs/installation/laravel`
)} for more information.`
)
logger.break()

View File

@@ -1,9 +1,11 @@
import { SHADCN_URL } from "@/src/registry/constants"
export const FRAMEWORKS = {
"next-app": {
name: "next-app",
label: "Next.js",
links: {
installation: "https://ui.shadcn.com/docs/installation/next",
installation: `${SHADCN_URL}/docs/installation/next`,
tailwind: "https://tailwindcss.com/docs/guides/nextjs",
},
},
@@ -11,7 +13,7 @@ export const FRAMEWORKS = {
name: "next-pages",
label: "Next.js",
links: {
installation: "https://ui.shadcn.com/docs/installation/next",
installation: `${SHADCN_URL}/docs/installation/next`,
tailwind: "https://tailwindcss.com/docs/guides/nextjs",
},
},
@@ -19,7 +21,7 @@ export const FRAMEWORKS = {
name: "remix",
label: "Remix",
links: {
installation: "https://ui.shadcn.com/docs/installation/remix",
installation: `${SHADCN_URL}/docs/installation/remix`,
tailwind: "https://tailwindcss.com/docs/guides/remix",
},
},
@@ -27,7 +29,7 @@ export const FRAMEWORKS = {
name: "react-router",
label: "React Router",
links: {
installation: "https://ui.shadcn.com/docs/installation/react-router",
installation: `${SHADCN_URL}/docs/installation/react-router`,
tailwind:
"https://tailwindcss.com/docs/installation/framework-guides/react-router",
},
@@ -36,7 +38,7 @@ export const FRAMEWORKS = {
name: "vite",
label: "Vite",
links: {
installation: "https://ui.shadcn.com/docs/installation/vite",
installation: `${SHADCN_URL}/docs/installation/vite`,
tailwind: "https://tailwindcss.com/docs/guides/vite",
},
},
@@ -44,7 +46,7 @@ export const FRAMEWORKS = {
name: "astro",
label: "Astro",
links: {
installation: "https://ui.shadcn.com/docs/installation/astro",
installation: `${SHADCN_URL}/docs/installation/astro`,
tailwind: "https://tailwindcss.com/docs/guides/astro",
},
},
@@ -52,7 +54,7 @@ export const FRAMEWORKS = {
name: "laravel",
label: "Laravel",
links: {
installation: "https://ui.shadcn.com/docs/installation/laravel",
installation: `${SHADCN_URL}/docs/installation/laravel`,
tailwind: "https://tailwindcss.com/docs/guides/laravel",
},
},
@@ -60,7 +62,7 @@ export const FRAMEWORKS = {
name: "tanstack-start",
label: "TanStack Start",
links: {
installation: "https://ui.shadcn.com/docs/installation/tanstack",
installation: `${SHADCN_URL}/docs/installation/tanstack`,
tailwind: "https://tailwindcss.com/docs/installation/using-postcss",
},
},
@@ -68,7 +70,7 @@ export const FRAMEWORKS = {
name: "gatsby",
label: "Gatsby",
links: {
installation: "https://ui.shadcn.com/docs/installation/gatsby",
installation: `${SHADCN_URL}/docs/installation/gatsby`,
tailwind: "https://tailwindcss.com/docs/guides/gatsby",
},
},
@@ -76,7 +78,7 @@ export const FRAMEWORKS = {
name: "expo",
label: "Expo",
links: {
installation: "https://ui.shadcn.com/docs/installation/expo",
installation: `${SHADCN_URL}/docs/installation/expo`,
tailwind: "https://www.nativewind.dev/docs/getting-started/installation",
},
},
@@ -84,7 +86,7 @@ export const FRAMEWORKS = {
name: "manual",
label: "Manual",
links: {
installation: "https://ui.shadcn.com/docs/installation/manual",
installation: `${SHADCN_URL}/docs/installation/manual`,
tailwind: "https://tailwindcss.com/docs/installation",
},
},

View File

@@ -1,6 +1,7 @@
import { promises as fsPromises } from "fs"
import path from "path"
import { getShadcnRegistryIndex } from "@/src/registry/api"
import { SHADCN_URL } from "@/src/registry/constants"
import { rawConfigSchema } from "@/src/schema"
import { Framework, FRAMEWORKS } from "@/src/utils/frameworks"
import { Config, getConfig, resolveConfigPaths } from "@/src/utils/get-config"
@@ -384,7 +385,7 @@ export async function getProjectConfig(
}
const config: z.infer<typeof rawConfigSchema> = {
$schema: "https://ui.shadcn.com/schema.json",
$schema: `${SHADCN_URL}/schema.json`,
rsc: projectInfo.isRSC,
tsx: projectInfo.isTsx,
style: "new-york",

View File

@@ -1,3 +1,4 @@
import { SHADCN_URL } from "@/src/registry/constants"
import { RegistryItem } from "@/src/schema"
import { Config } from "@/src/utils/get-config"
import { getPackageInfo } from "@/src/utils/get-package-info"
@@ -40,7 +41,7 @@ export async function updateDependencies(
} else {
dependenciesSpinner.stopAndPersist()
logger.warn(
"\nIt looks like you are using React 19. \nSome packages may fail to install due to peer dependency issues in npm (see https://ui.shadcn.com/react-19).\n"
`\nIt looks like you are using React 19. \nSome packages may fail to install due to peer dependency issues in npm (see ${SHADCN_URL}/react-19).\n`
)
const confirmation = await prompts([
{

View File

@@ -92,14 +92,16 @@ npx shadcn@latest docs button dialog select
## Workflow
1. **Get project context** — already injected above. Run `npx shadcn@latest info` again if you need to refresh.
2. **Check installed components**look in the `resolvedPaths.ui` directory before importing or adding. Don't import components that haven't been added, and don't re-add ones already installed.
2. **Check installed components first**before running `add`, always check the `components` list from project context or list the `resolvedPaths.ui` directory. Don't import components that haven't been added, and don't re-add ones already installed.
3. **Find components**`npx shadcn@latest search`.
4. **Get docs and examples** — run `npx shadcn@latest docs <component>` to get URLs, then fetch them. Use `npx shadcn@latest view` to browse registry items you haven't installed. To preview changes to installed components, use `npx shadcn@latest add --diff`.
5. **Install or update**`npx shadcn@latest add`. When updating existing components, use `--dry-run` and `--diff` to preview changes first (see [Updating Components](#updating-components) below).
6. **Fix imports in third-party components** — After adding components from community registries (e.g. `@bundui`, `@magicui`), check the added non-UI files for hardcoded import paths like `@/components/ui/...`. These won't match the project's actual aliases. Use `npx shadcn@latest info` to get the correct `ui` alias (e.g. `@workspace/ui/components`) and rewrite the imports accordingly. The CLI rewrites imports for its own UI files, but third-party registry components may use default paths that don't match the project.
7. **Switching presets** — Ask the user first: **reinstall**, **merge**, or **skip**?
7. **Review added components** — After adding a component or block from any registry, **always read the added files and verify they are correct**. Check for missing sub-components (e.g. `SelectItem` without `SelectGroup`), missing imports, incorrect composition, or violations of the [Critical Rules](#critical-rules). Also replace any icon imports with the project's `iconLibrary` from the project context (e.g. if the registry item uses `lucide-react` but the project uses `hugeicons`, swap the imports and icon names accordingly). Fix all issues before moving on.
8. **Registry must be explicit** — When the user asks to add a block or component, **do not guess the registry**. If no registry is specified (e.g. user says "add a login block" without specifying `@shadcn`, `@tailark`, etc.), ask which registry to use. Never default to a registry on behalf of the user.
9. **Switching presets** — Ask the user first: **reinstall**, **merge**, or **skip**?
- **Reinstall**: `npx shadcn@latest init --preset <code> --force --reinstall`. Overwrites all components.
- **Merge**: `npx shadcn@latest init --preset <code> --force --no-reinstall`, then `npx shadcn@latest info` to get installed components, then [smart merge](#updating-components) each one.
- **Merge**: `npx shadcn@latest init --preset <code> --force --no-reinstall`, then run `npx shadcn@latest info` to list installed components, then for each installed component use `--dry-run` and `--diff` to [smart merge](#updating-components) it individually.
- **Skip**: `npx shadcn@latest init --preset <code> --force --no-reinstall`. Only updates config and CSS, leaves components as-is.
## Updating Components