You know the drill.
You build a beautiful set of shadcn/ui components for Project A — a Button, a Card, a Dialog with custom animations. Then Project B kicks off. You copy the files over. Then Project C. Then a subtle bug is found in the Button. Now you're patching it in three places.
This is the classic monorepo problem, and it's exactly what I set out to fix.
What I Built
turborepo-react-shadcn-starter is a production-ready monorepo template that wires up:
- Turborepo for workspace orchestration and intelligent build caching
- React + Vite for the fastest possible frontend dev experience
- shadcn/ui as a shared package — write once, use everywhere
- TypeScript across the entire workspace
- ESLint with shared config baked in
The key insight: shadcn/ui lives in @repo/ui, a shared package, not inside any single app. Every app in your monorepo consumes the same components from the same source of truth.
The Problem with Typical Setups
Most teams drop shadcn/ui directly into a single app. That works fine until you need a second app. Then your choices are:
- Copy-paste the components → drift and duplication immediately
- Publish to npm → versioning overhead for internal code
- Monorepo with a shared package → ✅ This is the right answer
Turborepo makes option 3 near-effortless, but setting it up from scratch (workspace configs, TypeScript path aliases, ESLint sharing, shadcn CLI pointing at the right package) takes a few hours of trial and error. This starter eliminates all of that.
What's Inside
turborepo-react-shadcn-starter/
├── apps/
│ └── web/ # Vite + React app
├── packages/
│ ├── ui/ # @repo/ui — shared shadcn/ui components
│ ├── eslint-config/ # @repo/eslint-config
│ └── typescript-config/ # @repo/typescript-config
├── turbo.json
└── package.json
apps/web — The Main App
A clean Vite + React app already wired to consume components from @repo/ui. No boilerplate to delete, no config to untangle.
packages/ui — The Shared Component Library
This is where all your shadcn/ui components live. The package is set up so the shadcn CLI knows exactly where to drop new components:
# Add any shadcn component directly into the shared package
npx -w @repo/ui shadcn@latest add alert-dialog
Every app that imports from @repo/ui gets the component instantly. No copying. No syncing.
Shared ESLint + TypeScript Configs
Both are extracted into their own packages and extended by every app and package in the workspace. Change a lint rule once, it applies everywhere.
Getting Started in Under 2 Minutes
# Clone the template
git clone https://github.com/sharath-mohan/turborepo-react-shadcn-starter.git my-project
cd my-project
# Install everything (all workspaces in one shot)
npm install
# Start dev servers
npm run dev
Turborepo runs tasks in parallel and caches outputs intelligently — subsequent builds are dramatically faster because it only rebuilds what changed.
Adding a Second App
This is where monorepos shine. Scaffolding a new app that immediately has access to your entire shared UI library takes one command:
# Generate a new workspace app
npx turbo gen workspace --name my-dashboard
# Or copy the existing web app as a starting point
npx turbo gen workspace --name my-dashboard --copy
Your new app can immediately import from @repo/ui:
import { Button } from "@repo/ui/components/button";
import { Card, CardContent } from "@repo/ui/components/card";
No extra setup. No publishing. No path hacks.
Remote Caching (The Turborepo Superpower)
If you're working in a team or running CI, Turborepo's remote cache means builds are shared across machines. Your CI pipeline can skip rebuilding packages that haven't changed since the last run.
npx turbo login
npx turbo link
That's it. Now every engineer on the team — and your CI — shares a single build cache.
Why This Stack Makes Sense
| Concern | Solution |
|---|---|
| Fast local DX | Vite HMR — updates in milliseconds |
| Shared UI components |
@repo/ui — single source of truth |
| Type safety | TypeScript across all apps + packages |
| Code quality | Shared ESLint config |
| Build performance | Turborepo task graph + caching |
| Scalability | Add apps without touching existing code |
Who This Is For
- Teams building multiple frontend apps that share design system components
- Developers tired of duplicating UI code across projects
- Anyone who wants to adopt a monorepo architecture without the setup cost
- Frontend leads looking for a clean starting point for a new platform
What's Next
I'm planning to add:
- [ ] Storybook integration for the shared UI package
- [ ] Playwright e2e testing setup
- [ ] Docker + CI/CD workflow examples
- [ ] Additional shadcn/ui components pre-included
If any of these would be useful to you — or if you have other ideas — open an issue or drop a comment below.
Give It a Try
The template is open source and ready to use:
👉 github.com/sharath-mohan/turborepo-react-shadcn-starter
If it saves you setup time, a ⭐ on GitHub goes a long way — it helps more developers discover it.
Contributions, feedback, and PRs are all welcome. Let's make the scaffolding part of monorepos a solved problem.
Built with Turborepo, React, Vite, shadcn/ui, and TypeScript.
Top comments (0)