## Why Choose a Monorepo for Tamagui Projects?
In modern development, monorepos have gained popularity for managing multiple related projects in a single repository. Unlike traditional polyrepos, where each app or package lives separately, a monorepo centralizes code sharing, simplifies dependency management, and streamlines CI/CD pipelines. For Tamagui—a powerful, universal UI kit designed for React Native and the web—a monorepo setup shines by allowing shared components, themes, and configurations across platforms.
### Monorepo vs. Polyrepo: A Quick Comparison
| Aspect | Monorepo (e.g., Turborepo + Tamagui) | Polyrepo |
|---------------------|--------------------------------------|------------------------------|
| **Code Sharing** | Atomic updates, shared types | Manual syncing, version locks|
| **Dependency Mgmt**| Single lockfile, hoisting | Multiple package.json files |
| **Build Speed** | Incremental caching (Turbo) | Full rebuilds per repo |
| **Team Workflow** | Unified PRs, easier refactoring | Cross-repo coordination |
| **Scalability** | Handles 100s of packages | Fragmented at scale |
Tamagui's design philosophy aligns perfectly with monorepos. It optimizes for performance with CSS-in-JS alternatives, styled-system utilities, and theming that works seamlessly on native and web. Real-world applications include Expo apps, Next.js sites, and hybrid setups like those at [Tamagui's core repo](https://github.com/tamagui/tamagui).
Using Cursor, an AI-powered code editor, accelerates this process. Cursor understands monorepo structures, suggests configurations, and auto-generates boilerplate, making setup 5-10x faster than manual coding.
## Prerequisites and Initial Setup
Before diving in, ensure you have:
- Node.js 18+ installed.
- Cursor editor (download from cursor.com).
- Yarn or npm as package manager (Yarn recommended for workspaces).
Start by creating a new directory and initializing the monorepo:
```bash
mkdir my-tamagui-monorepo
cd my-tamagui-monorepo
yarn init -y
yarn add -D turbo@latest typescript @types/node
```
This sets up Turborepo, the build tool that orchestrates tasks across packages with intelligent caching. Turborepo detects changes and only rebuilds affected packages, crucial for large UIs like Tamagui.
Next, configure `turbo.json` for pipeline definitions:
```json
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {},
"type-check": {}
}
}
```
Add `package.json` scripts:
```json
{
"scripts": {
"dev": "turbo run dev",
"build": "turbo run build",
"lint": "turbo run lint",
"type-check": "turbo run type-check"
},
"workspaces": ["apps/*", "packages/*"]
}
```
## Structuring Your Monorepo Packages
Organize into `apps/` for deployable projects and `packages/` for shared libs:
```
my-tamagui-monorepo/
├── apps/
│ ├── web/ # Next.js app
│ └── native/ # Expo/React Native app
├── packages/
│ ├── ui/ # Tamagui components
│ ├── config/ # Tamagui config
│ └── eslint-config/
├── turbo.json
└── package.json
```
This structure promotes reusability. For instance, `packages/ui` holds styled Tamagui buttons reusable in both web and native apps.
## Integrating Tamagui Core
Tamagui requires specific TypeScript and bundler configs for optimal performance. Install it across the monorepo:
```bash
yarn workspace @repo/ui add tamagui
yarn workspace apps/web add tamagui
yarn workspace apps/native add tamagui expo
```
Use Yarn's workspace protocol (`@repo/ui`) for internal deps, avoiding version mismatches.
Create `packages/config/tamagui.config.ts`:
```ts
import { createTamagui, createTokens } from 'tamagui'
const tokens = createTokens({
size: {
0: 0,
1: 4,
// ... full token set
},
// colors, space, radius, etc.
})
export default createTamagui({
tokens,
themes: {
light: {
background: '#fff',
// ...
},
},
})
```
This config enables Tamagui's optimizations like static CSS extraction and tree-shaking.
## App-Specific Configurations
### Web App (Next.js)
In `apps/web/next.config.js`:
```js
const { withTamagui } = require('@tamagui/next-plugin')
/** @type {import('next').NextConfig} */
const config = {
transpilePackages: ['@repo/ui'],
}
module.exports = withTamagui(config)
```
`apps/web/tamagui.config.ts` imports from `@repo/config`:
```ts
import config from '@repo/config'
export default config
```
Root `tsconfig.json`:
```json
{
"compilerOptions": {
"strict": true,
"baseUrl": ".",
"paths": {
"@repo/*": ["./packages/*"]
}
}
}
```
Package-level `tsconfig.json` extends root with Tamagui plugins.
### Native App (Expo)
`apps/native/app.json`:
```json
{
"expo": {
"plugins": [
"tamagui",
{
"config": "./tamagui.config.ts",
"components": ["./src/components"]
}
]
}
}
```
This enables compile-time optimizations for React Native.
## Shared UI Package Development
In `packages/ui/package.json`:
```json
{
"name": "@repo/ui",
"dependencies": {
"tamagui": "*"
}
}
```
Example component `Button.tsx`:
```tsx
import { styled } from 'tamagui'
export const Button = styled({
backgroundColor: '$blue10',
color: 'white',
padding: '$4',
borderRadius: '$10',
}, {
variants: {
variant: {
primary: { backgroundColor: '$blue10' },
},
},
})
```
Use in apps: `import { Button } from '@repo/ui'`.
## Running and Testing the Setup
```bash
yarn turbo run dev
```
This spins up web at localhost:3000 and native via Expo. Cursor's AI can debug issues like path aliasing or theme mismatches instantly.
Linting with ESLint: Create `packages/eslint-config` and reference in apps.
## Optimization and Best Practices
- **Caching**: Turbo caches builds; invalidate with `--force`.
- **TypeScript Paths**: Ensure consistent resolution.
- **Theming**: Use tokens for responsive design (e.g., `size: { true: 16, lg: 20 }`).
- **Performance**: Tamagui extracts CSS, reducing bundle size by 70% vs. Emotion.
Real-world example: [Tamagui's monorepo app example](https://github.com/tamagui/website/tree/main/examples/tamagui-monorepo-app) demonstrates a full web/native setup. Scale to enterprise apps like dashboards shared across platforms.
## Troubleshooting Common Issues
- **Path Errors**: Verify `tsconfig paths` and `next.config transpilePackages`.
- **Native Linking**: Run `expo install` after plugin adds.
- **Turbo Cache Misses**: Clear with `yarn turbo run build --force`.
Cursor excels here—prompt it with "Fix Tamagui path alias in monorepo" for instant resolutions.
## Scaling Your Monorepo
Add more packages like `animations/` or `icons/`. Integrate Storybook for component docs:
```bash
yarn workspace @repo/ui add -D @tamagui/storybook
```
For CI, use GitHub Actions with Turbo cache.
This setup empowers efficient, performant cross-platform UIs. Experiment in Cursor to iterate rapidly.
<div style="text-align: center; margin-top: 2rem;">
<a href="https://cursor.directory/monorepo-tamagui" target="_blank" rel="noopener noreferrer" class="view-full-resource-btn" style="display: inline-block; background-color: #f97316; color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; font-weight: 600; transition: background-color 0.2s;">View Full Resource</a>
</div>