From d7e0dc3ec81676d47351e8f7134639e0dd0c3e3c Mon Sep 17 00:00:00 2001 From: shadcn Date: Thu, 23 Oct 2025 22:00:55 +0400 Subject: [PATCH 1/3] feat(shadcn): middleware to proxy (#8555) * feat: implement getFrameworkVersion * feat(shadcn): add transformNext transformer * feat(shadcn): rename * chore: update * chore: changeset * fix * fix: small refactor --- .changeset/major-keys-begin.md | 5 + packages/shadcn/src/utils/get-project-info.ts | 42 ++ .../utils/transformers/transform-next.test.ts | 424 ++++++++++++++++++ .../src/utils/transformers/transform-next.ts | 33 ++ .../shadcn/src/utils/updaters/update-files.ts | 32 ++ .../test/utils/get-project-info.test.ts | 145 +++++- 6 files changed, 680 insertions(+), 1 deletion(-) create mode 100644 .changeset/major-keys-begin.md create mode 100644 packages/shadcn/src/utils/transformers/transform-next.test.ts create mode 100644 packages/shadcn/src/utils/transformers/transform-next.ts diff --git a/.changeset/major-keys-begin.md b/.changeset/major-keys-begin.md new file mode 100644 index 0000000000..ddd2df4be0 --- /dev/null +++ b/.changeset/major-keys-begin.md @@ -0,0 +1,5 @@ +--- +"shadcn": minor +--- + +rename middleware to proxy for Next.js 16 diff --git a/packages/shadcn/src/utils/get-project-info.ts b/packages/shadcn/src/utils/get-project-info.ts index 8bca68172d..f70b609b62 100644 --- a/packages/shadcn/src/utils/get-project-info.ts +++ b/packages/shadcn/src/utils/get-project-info.ts @@ -18,6 +18,7 @@ export type ProjectInfo = { tailwindConfigFile: string | null tailwindCssFile: string | null tailwindVersion: TailwindVersion + frameworkVersion: string | null aliasPrefix: string | null } @@ -75,6 +76,7 @@ export async function getProjectInfo(cwd: string): Promise { tailwindConfigFile, tailwindCssFile, tailwindVersion, + frameworkVersion: null, aliasPrefix, } @@ -84,6 +86,10 @@ export async function getProjectInfo(cwd: string): Promise { ? FRAMEWORKS["next-app"] : FRAMEWORKS["next-pages"] type.isRSC = isUsingAppDir + type.frameworkVersion = await getFrameworkVersion( + type.framework, + packageJson + ) return type } @@ -165,6 +171,42 @@ export async function getProjectInfo(cwd: string): Promise { return type } +export async function getFrameworkVersion( + framework: Framework, + packageJson: ReturnType +) { + if (!packageJson) { + return null + } + + // Only detect Next.js version for now. + if (!["next-app", "next-pages"].includes(framework.name)) { + return null + } + + const version = + packageJson.dependencies?.next || packageJson.devDependencies?.next + + if (!version) { + return null + } + + // Extract full semver (major.minor.patch), handling ^, ~, etc. + const versionMatch = version.match(/^[\^~]?(\d+\.\d+\.\d+)/) + if (versionMatch) { + return versionMatch[1] // e.g., "16.0.0" + } + + // For ranges like ">=15.0.0 <16.0.0", extract the first version. + const rangeMatch = version.match(/(\d+\.\d+\.\d+)/) + if (rangeMatch) { + return rangeMatch[1] + } + + // For "latest", "canary", "rc", etc., return the tag as-is. + return version +} + export async function getTailwindVersion( cwd: string ): Promise { diff --git a/packages/shadcn/src/utils/transformers/transform-next.test.ts b/packages/shadcn/src/utils/transformers/transform-next.test.ts new file mode 100644 index 0000000000..ea64a52bf2 --- /dev/null +++ b/packages/shadcn/src/utils/transformers/transform-next.test.ts @@ -0,0 +1,424 @@ +import { FRAMEWORKS } from "@/src/utils/frameworks" +import { type Config } from "@/src/utils/get-config" +import { transformNext } from "@/src/utils/transformers/transform-next" +import { describe, expect, test, vi } from "vitest" + +import { transform } from "../transformers" + +const testConfig: Config = { + style: "new-york", + tsx: true, + rsc: true, + tailwind: { + baseColor: "neutral", + cssVariables: true, + config: "tailwind.config.ts", + css: "tailwind.css", + }, + aliases: { + components: "@/components", + utils: "@/lib/utils", + }, + resolvedPaths: { + cwd: "/test-project", + components: "/test-project/components", + utils: "/test-project/lib/utils", + ui: "/test-project/ui", + lib: "/test-project/lib", + hooks: "/test-project/hooks", + tailwindConfig: "tailwind.config.ts", + tailwindCss: "tailwind.css", + }, +} + +vi.mock("@/src/utils/get-project-info", () => ({ + getProjectInfo: vi.fn(), +})) + +describe("transformNext", () => { + describe("Next.js 16+ transformations", () => { + test("should transform function declaration export", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["next-app"], + frameworkVersion: "16.0.0", + isSrcDir: false, + isRSC: true, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + expect( + await transform( + { + filename: "middleware.ts", + raw: `import { NextResponse } from "next/server" + +export function middleware(request: Request) { + return NextResponse.next() +}`, + config: testConfig, + }, + [transformNext] + ) + ).toMatchInlineSnapshot(` + "import { NextResponse } from "next/server" + + export function proxy(request: Request) { + return NextResponse.next() + }" + `) + }) + + test("should transform async function declaration", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["next-app"], + frameworkVersion: "16.1.0", + isSrcDir: false, + isRSC: true, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + expect( + await transform( + { + filename: "middleware.ts", + raw: `import { NextResponse } from "next/server" + +export async function middleware(request: Request) { + return NextResponse.next() +}`, + config: testConfig, + }, + [transformNext] + ) + ).toMatchInlineSnapshot(` + "import { NextResponse } from "next/server" + + export async function proxy(request: Request) { + return NextResponse.next() + }" + `) + }) + + test("should transform const arrow function export", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["next-app"], + frameworkVersion: "16.0.0", + isSrcDir: false, + isRSC: true, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + expect( + await transform( + { + filename: "middleware.ts", + raw: `import { NextResponse } from "next/server" + +export const middleware = (request: Request) => { + return NextResponse.next() +}`, + config: testConfig, + }, + [transformNext] + ) + ).toMatchInlineSnapshot(` + "import { NextResponse } from "next/server" + + export const proxy = (request: Request) => { + return NextResponse.next() + }" + `) + }) + + test("should transform named export with alias", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["next-app"], + frameworkVersion: "16.0.0", + isSrcDir: false, + isRSC: true, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + expect( + await transform( + { + filename: "middleware.ts", + raw: `import { NextResponse } from "next/server" + +function handler(request: Request) { + return NextResponse.next() +} + +export { handler as middleware }`, + config: testConfig, + }, + [transformNext] + ) + ).toMatchInlineSnapshot(` + "import { NextResponse } from "next/server" + + function handler(request: Request) { + return NextResponse.next() + } + + export { handler as proxy }" + `) + }) + }) + + describe("Next.js < 16 or unknown versions (no transformation)", () => { + test("should not transform for Next.js 15", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["next-app"], + frameworkVersion: "15.0.0", + isSrcDir: false, + isRSC: true, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + const input = `import { NextResponse } from "next/server" + +export function middleware(request: Request) { + return NextResponse.next() +}` + + expect( + await transform( + { + filename: "middleware.ts", + raw: input, + config: testConfig, + }, + [] // Don't include transformNext for Next.js 15 + ) + ).toBe(input) + }) + + test("should not transform when frameworkVersion is null", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["next-app"], + frameworkVersion: null, + isSrcDir: false, + isRSC: true, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + const input = `import { NextResponse } from "next/server" + +export function middleware(request: Request) { + return NextResponse.next() +}` + + expect( + await transform( + { + filename: "middleware.ts", + raw: input, + config: testConfig, + }, + [] // Don't include transformNext when frameworkVersion is null + ) + ).toBe(input) + }) + + test("should not transform for canary tag (unknown version)", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["next-app"], + frameworkVersion: "canary", + isSrcDir: false, + isRSC: true, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + const input = `import { NextResponse } from "next/server" + +export function middleware(request: Request) { + return NextResponse.next() +}` + + expect( + await transform( + { + filename: "middleware.ts", + raw: input, + config: testConfig, + }, + [] // Don't include transformNext for canary tag + ) + ).toBe(input) + }) + + test("should not transform for latest tag (unknown version)", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["next-app"], + frameworkVersion: "latest", + isSrcDir: false, + isRSC: true, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + const input = `import { NextResponse } from "next/server" + +export function middleware(request: Request) { + return NextResponse.next() +}` + + expect( + await transform( + { + filename: "middleware.ts", + raw: input, + config: testConfig, + }, + [] // Don't include transformNext for latest tag + ) + ).toBe(input) + }) + }) + + describe("Non-middleware files", () => { + test("should not transform non-middleware files", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["next-app"], + frameworkVersion: "16.0.0", + isSrcDir: false, + isRSC: true, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + const input = `export function middleware() { + return "not a middleware file" +}` + + expect( + await transform( + { + filename: "utils.ts", + raw: input, + config: testConfig, + }, + [] // Don't include transformNext for non-middleware files + ) + ).toBe(input) + }) + + test("should not transform nested middleware files", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["next-app"], + frameworkVersion: "16.0.0", + isSrcDir: false, + isRSC: true, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + const input = `export function middleware() { + return "nested middleware" +}` + + // Nested middleware files should not be transformed + expect( + await transform( + { + filename: "lib/middleware.ts", + raw: input, + config: testConfig, + }, + [] // Don't include transformNext for nested middleware files + ) + ).toBe(input) + + expect( + await transform( + { + filename: "lib/supabase/middleware.ts", + raw: input, + config: testConfig, + }, + [] // Don't include transformNext for nested middleware files + ) + ).toBe(input) + }) + }) + + describe("Non-Next.js projects", () => { + test("should not transform for Vite projects", async () => { + const { getProjectInfo } = await import("@/src/utils/get-project-info") + vi.mocked(getProjectInfo).mockResolvedValue({ + framework: FRAMEWORKS["vite"], + frameworkVersion: null, + isSrcDir: false, + isRSC: false, + isTsx: true, + tailwindConfigFile: null, + tailwindCssFile: null, + tailwindVersion: "v4", + aliasPrefix: "@", + }) + + const input = `export function middleware() { + return "some middleware" +}` + + expect( + await transform( + { + filename: "middleware.ts", + raw: input, + config: testConfig, + }, + [] // Don't include transformNext for non-Next.js projects + ) + ).toBe(input) + }) + }) +}) diff --git a/packages/shadcn/src/utils/transformers/transform-next.ts b/packages/shadcn/src/utils/transformers/transform-next.ts new file mode 100644 index 0000000000..acdc61727d --- /dev/null +++ b/packages/shadcn/src/utils/transformers/transform-next.ts @@ -0,0 +1,33 @@ +import { Transformer } from "@/src/utils/transformers" + +export const transformNext: Transformer = async ({ sourceFile }) => { + // export function middleware. + sourceFile.getFunctions().forEach((func) => { + if (func.getName() === "middleware") { + func.rename("proxy") + } + }) + + // export const middleware. + sourceFile.getVariableDeclarations().forEach((variable) => { + if (variable.getName() === "middleware") { + variable.rename("proxy") + } + }) + + // export { handler as middleware }. + sourceFile.getExportDeclarations().forEach((exportDecl) => { + const namedExports = exportDecl.getNamedExports() + namedExports.forEach((namedExport) => { + if (namedExport.getName() === "middleware") { + namedExport.setName("proxy") + } + const aliasNode = namedExport.getAliasNode() + if (aliasNode?.getText() === "middleware") { + namedExport.setAlias("proxy") + } + }) + }) + + return sourceFile +} diff --git a/packages/shadcn/src/utils/updaters/update-files.ts b/packages/shadcn/src/utils/updaters/update-files.ts index 3225fbdf3a..0e468e2e52 100644 --- a/packages/shadcn/src/utils/updaters/update-files.ts +++ b/packages/shadcn/src/utils/updaters/update-files.ts @@ -21,6 +21,7 @@ import { transform } from "@/src/utils/transformers" import { transformCssVars } from "@/src/utils/transformers/transform-css-vars" import { transformIcons } from "@/src/utils/transformers/transform-icons" import { transformImport } from "@/src/utils/transformers/transform-import" +import { transformNext } from "@/src/utils/transformers/transform-next" import { transformRsc } from "@/src/utils/transformers/transform-rsc" import { transformTwPrefixes } from "@/src/utils/transformers/transform-tw-prefix" import prompts from "prompts" @@ -138,6 +139,9 @@ export async function updateFiles( transformCssVars, transformTwPrefixes, transformIcons, + ...(_isNext16Middleware(filePath, projectInfo, config) + ? [transformNext] + : []), ] ) @@ -186,6 +190,11 @@ export async function updateFiles( } } + // Rename middleware.ts to proxy.ts for Next.js 16+. + if (_isNext16Middleware(filePath, projectInfo, config)) { + filePath = filePath.replace(/middleware\.(ts|js)$/, "proxy.$1") + } + // Create the target directory if it doesn't exist. if (!existsSync(targetDir)) { await fs.mkdir(targetDir, { recursive: true }) @@ -715,3 +724,26 @@ export function toAliasedImport( // but usually config.aliases already include it. return `${aliasBase}${suffix}${keepExt}` } + +function _isNext16Middleware( + filePath: string, + projectInfo: ProjectInfo | null, + config: Config +) { + const isRootMiddleware = + filePath === path.join(config.resolvedPaths.cwd, "middleware.ts") || + filePath === path.join(config.resolvedPaths.cwd, "middleware.js") + + const isNextJs = + projectInfo?.framework.name === "next-app" || + projectInfo?.framework.name === "next-pages" + + if (!isRootMiddleware || !isNextJs || !projectInfo?.frameworkVersion) { + return false + } + + const majorVersion = parseInt(projectInfo.frameworkVersion.split(".")[0]) + const isNext16Plus = !isNaN(majorVersion) && majorVersion >= 16 + + return isNext16Plus +} diff --git a/packages/shadcn/test/utils/get-project-info.test.ts b/packages/shadcn/test/utils/get-project-info.test.ts index cd9708cd54..e09177d14b 100644 --- a/packages/shadcn/test/utils/get-project-info.test.ts +++ b/packages/shadcn/test/utils/get-project-info.test.ts @@ -2,7 +2,10 @@ import path from "path" import { describe, expect, test } from "vitest" import { FRAMEWORKS } from "../../src/utils/frameworks" -import { getProjectInfo } from "../../src/utils/get-project-info" +import { + getFrameworkVersion, + getProjectInfo, +} from "../../src/utils/get-project-info" describe("get project info", async () => { test.each([ @@ -16,6 +19,7 @@ describe("get project info", async () => { tailwindConfigFile: "tailwind.config.ts", tailwindCssFile: "app/globals.css", tailwindVersion: "v3", + frameworkVersion: null, aliasPrefix: "@", }, }, @@ -29,6 +33,7 @@ describe("get project info", async () => { tailwindConfigFile: "tailwind.config.ts", tailwindCssFile: "src/app/styles.css", tailwindVersion: "v3", + frameworkVersion: null, aliasPrefix: "#", }, }, @@ -42,6 +47,7 @@ describe("get project info", async () => { tailwindConfigFile: "tailwind.config.ts", tailwindCssFile: "styles/globals.css", tailwindVersion: "v4", + frameworkVersion: null, aliasPrefix: "~", }, }, @@ -55,6 +61,7 @@ describe("get project info", async () => { tailwindConfigFile: "tailwind.config.ts", tailwindCssFile: "src/styles/globals.css", tailwindVersion: "v4", + frameworkVersion: null, aliasPrefix: "@", }, }, @@ -68,6 +75,7 @@ describe("get project info", async () => { tailwindConfigFile: "tailwind.config.ts", tailwindCssFile: "src/styles/globals.css", tailwindVersion: "v3", + frameworkVersion: "14.2.4", aliasPrefix: "~", }, }, @@ -81,6 +89,7 @@ describe("get project info", async () => { tailwindConfigFile: "tailwind.config.ts", tailwindCssFile: "src/styles/globals.css", tailwindVersion: "v3", + frameworkVersion: "13.4.2", aliasPrefix: "~", }, }, @@ -94,6 +103,7 @@ describe("get project info", async () => { tailwindConfigFile: "tailwind.config.ts", tailwindCssFile: "app/tailwind.css", tailwindVersion: "v3", + frameworkVersion: null, aliasPrefix: "~", }, }, @@ -107,6 +117,7 @@ describe("get project info", async () => { tailwindConfigFile: "tailwind.config.ts", tailwindCssFile: "app/tailwind.css", tailwindVersion: "v3", + frameworkVersion: null, aliasPrefix: "~", }, }, @@ -120,6 +131,7 @@ describe("get project info", async () => { tailwindConfigFile: "tailwind.config.js", tailwindCssFile: "src/index.css", tailwindVersion: "v3", + frameworkVersion: null, aliasPrefix: null, }, }, @@ -131,3 +143,134 @@ describe("get project info", async () => { ).toStrictEqual(type) }) }) + +describe("getFrameworkVersion", () => { + describe("Next.js version detection", () => { + test.each([ + { + name: "exact semver", + input: "16.0.0", + framework: "next-app", + expected: "16.0.0", + }, + { + name: "caret prefix", + input: "^16.1.2", + framework: "next-app", + expected: "16.1.2", + }, + { + name: "tilde prefix", + input: "~15.0.3", + framework: "next-app", + expected: "15.0.3", + }, + { + name: "version range", + input: ">=15.0.0 <16.0.0", + framework: "next-app", + expected: "15.0.0", + }, + { + name: "latest tag", + input: "latest", + framework: "next-app", + expected: "latest", + }, + { + name: "canary tag", + input: "canary", + framework: "next-app", + expected: "canary", + }, + { + name: "rc tag", + input: "rc", + framework: "next-app", + expected: "rc", + }, + ])( + `should extract $name ($input) -> $expected`, + async ({ input, framework, expected }) => { + const packageJson = { + dependencies: { + next: input, + }, + } + const version = await getFrameworkVersion( + FRAMEWORKS[framework as keyof typeof FRAMEWORKS], + packageJson + ) + expect(version).toBe(expected) + } + ) + + test("should handle version in devDependencies", async () => { + const packageJson = { + devDependencies: { + next: "16.0.0", + }, + } + const version = await getFrameworkVersion( + FRAMEWORKS["next-pages"], + packageJson + ) + expect(version).toBe("16.0.0") + }) + + test("should return null when next is not in dependencies", async () => { + const packageJson = { + dependencies: { + react: "^18.0.0", + }, + } + const version = await getFrameworkVersion( + FRAMEWORKS["next-app"], + packageJson + ) + expect(version).toBe(null) + }) + + test("should return null when packageJson is null", async () => { + const version = await getFrameworkVersion(FRAMEWORKS["next-app"], null) + expect(version).toBe(null) + }) + }) + + describe("Other frameworks", () => { + test.each([ + { + name: "Vite", + framework: "vite", + package: "vite", + version: "^5.0.0", + }, + { + name: "Remix", + framework: "remix", + package: "@remix-run/react", + version: "^2.0.0", + }, + { + name: "Astro", + framework: "astro", + package: "astro", + version: "^4.0.0", + }, + ])( + `should return null for $name`, + async ({ framework, package: pkg, version: ver }) => { + const packageJson = { + dependencies: { + [pkg]: ver, + }, + } + const version = await getFrameworkVersion( + FRAMEWORKS[framework as keyof typeof FRAMEWORKS], + packageJson + ) + expect(version).toBe(null) + } + ) + }) +}) From 39032bb3901195905dbdfad19ec68fcd42e26d23 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 23 Oct 2025 22:12:05 +0400 Subject: [PATCH 2/3] chore(release): version packages (#8551) * chore(release): version packages * chore(release): version packages * chore: deps --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: shadcn --- .changeset/major-keys-begin.md | 5 ----- .changeset/nine-steaks-rule.md | 5 ----- apps/v4/package.json | 2 +- apps/www/package.json | 2 +- packages/shadcn/CHANGELOG.md | 8 ++++++++ packages/shadcn/package.json | 2 +- pnpm-lock.yaml | 4 ++-- 7 files changed, 13 insertions(+), 15 deletions(-) delete mode 100644 .changeset/major-keys-begin.md delete mode 100644 .changeset/nine-steaks-rule.md diff --git a/.changeset/major-keys-begin.md b/.changeset/major-keys-begin.md deleted file mode 100644 index ddd2df4be0..0000000000 --- a/.changeset/major-keys-begin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"shadcn": minor ---- - -rename middleware to proxy for Next.js 16 diff --git a/.changeset/nine-steaks-rule.md b/.changeset/nine-steaks-rule.md deleted file mode 100644 index 08b9c10721..0000000000 --- a/.changeset/nine-steaks-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"shadcn": minor ---- - -add Next.js 16 support for init command diff --git a/apps/v4/package.json b/apps/v4/package.json index 19d5bd5d16..c26e0bedbe 100644 --- a/apps/v4/package.json +++ b/apps/v4/package.json @@ -89,7 +89,7 @@ "recharts": "2.15.1", "rehype-pretty-code": "^0.14.1", "rimraf": "^6.0.1", - "shadcn": "3.4.2", + "shadcn": "3.5.0", "shiki": "^1.10.1", "sonner": "^2.0.0", "tailwind-merge": "^3.0.1", diff --git a/apps/www/package.json b/apps/www/package.json index 772e690725..a97eeb13d4 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -88,7 +88,7 @@ "react-resizable-panels": "^2.0.22", "react-wrap-balancer": "^0.4.1", "recharts": "2.12.7", - "shadcn": "3.4.2", + "shadcn": "3.5.0", "sharp": "^0.32.6", "sonner": "^1.2.3", "swr": "2.2.6-beta.3", diff --git a/packages/shadcn/CHANGELOG.md b/packages/shadcn/CHANGELOG.md index 0258ccfa8c..6f34ca1c9f 100644 --- a/packages/shadcn/CHANGELOG.md +++ b/packages/shadcn/CHANGELOG.md @@ -1,5 +1,13 @@ # @shadcn/ui +## 3.5.0 + +### Minor Changes + +- [#8555](https://github.com/shadcn-ui/ui/pull/8555) [`d7e0dc3ec81676d47351e8f7134639e0dd0c3e3c`](https://github.com/shadcn-ui/ui/commit/d7e0dc3ec81676d47351e8f7134639e0dd0c3e3c) Thanks [@shadcn](https://github.com/shadcn)! - rename middleware to proxy for Next.js 16 + +- [#8550](https://github.com/shadcn-ui/ui/pull/8550) [`6bddba986d75da35e18343dbb6254fed4537b7d7`](https://github.com/shadcn-ui/ui/commit/6bddba986d75da35e18343dbb6254fed4537b7d7) Thanks [@shadcn](https://github.com/shadcn)! - add Next.js 16 support for init command + ## 3.4.2 ### Patch Changes diff --git a/packages/shadcn/package.json b/packages/shadcn/package.json index ce000dd20b..9d5655fbe2 100644 --- a/packages/shadcn/package.json +++ b/packages/shadcn/package.json @@ -1,6 +1,6 @@ { "name": "shadcn", - "version": "3.4.2", + "version": "3.5.0", "description": "Add components to your apps.", "publishConfig": { "access": "public" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 21b56c6b20..7f14908a4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -331,7 +331,7 @@ importers: specifier: ^6.0.1 version: 6.0.1 shadcn: - specifier: 3.4.2 + specifier: 3.5.0 version: link:../../packages/shadcn shiki: specifier: ^1.10.1 @@ -611,7 +611,7 @@ importers: specifier: 2.12.7 version: 2.12.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) shadcn: - specifier: 3.4.2 + specifier: 3.5.0 version: link:../../packages/shadcn sharp: specifier: ^0.32.6 From a16a77446ad5fd4110a80b3dbad9246aa9c2fd38 Mon Sep 17 00:00:00 2001 From: Shaban Date: Fri, 24 Oct 2025 11:37:47 +0500 Subject: [PATCH 3/3] feat: rename @efferd-ui -> @efferd (#8557) --- apps/v4/public/r/registries.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/v4/public/r/registries.json b/apps/v4/public/r/registries.json index 625319c5c2..4974c2b1e2 100644 --- a/apps/v4/public/r/registries.json +++ b/apps/v4/public/r/registries.json @@ -17,7 +17,7 @@ "@clerk": "https://clerk.com/r/{name}.json", "@coss": "https://coss.com/ui/r/{name}.json", "@cult-ui": "https://cult-ui.com/r/{name}.json", - "@efferd-ui": "https://ui.efferd.com/r/{name}.json", + "@efferd": "https://efferd.com/r/{name}.json", "@eldoraui": "https://eldoraui.site/r/{name}.json", "@elements": "https://tryelements.dev/r/{name}.json", "@elevenlabs-ui": "https://ui.elevenlabs.io/r/{name}.json",