Using Next.js and Shadcn/UI in a monorepo environment.
As per the documentation https://ui.shadcn.com/docs/monorepo, I added form component as
cd apps/web
pnpm dlx shadcn@canary add form
This added form component in
packages/ui/src/components/form.tsx
and installed zod
inside packages/ui/package.json
{
"name": "@workspace/ui",
"version": "0.0.0",
"type": "module",
"private": true,
"scripts": {
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
"@hookform/resolvers": "^5.2.1",
...
"sonner": "^2.0.6",
"zod": "^3.24.2"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.0.8",
"@turbo/gen": "^2.4.2",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@workspace/eslint-config": "workspace:*",
"@workspace/typescript-config": "workspace:*",
"tailwindcss": "^4.0.8",
"typescript": "^5.7.3"
},
"exports": {
"./globals.css": "./src/styles/globals.css",
"./postcss.config": "./postcss.config.mjs",
"./lib/*": "./src/lib/*.ts",
"./components/*": "./src/components/*.tsx",
"./hooks/*": "./src/hooks/*.ts"
}
}
The form component is usable inside apps/web/
as
import {
Form,
FormControl,
FormField,
FormItem,
} from "@workspace/ui/components/form";
But unable to import zod
inside apps/web
.
The same is the case with sonner
, which I then installed inside apps/web
for working. Can't the packages required for a specific component be shared in apps?
package.json
inside apps/web
is
{
"name": "web",
"version": "0.0.1",
"type": "module",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "next lint --fix",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@tanstack/react-table": "^8.21.3",
"@workspace/ui": "workspace:*",
"lucide-react": "^0.475.0",
"next": "^15.2.3",
"next-themes": "^0.4.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"sonner": "^2.0.6"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"@workspace/eslint-config": "workspace:^",
"@workspace/typescript-config": "workspace:*",
"typescript": "^5.7.3"
}
}
sonner
is reflected in this file as well because it was intentionally installed in apps/web
.
In your root pnpm-workspace.yaml
, make sure it includes all packages:
packages:
- "apps/*"
- "packages/*"
Then hoist shared deps to the root by adding them at the top-level package.json:
{
"dependencies": {
"zod": "^3.24.2",
"sonner": "^2.0.6"
}
}
Then run:
pnpm install