Monorepo Architecture
Understanding the monorepo structure, build orchestration, and development workflow.
The VibeFast project uses a modern monorepo architecture powered by Turborepo and PNPM. Practically, this just means you open one repo and get the mobile app, the web app, and the backend in one place.
Why a Monorepo?
A monorepo architecture provides several key benefits for mobile app development:
- Shared Code: Common packages (UI components, utilities) can be shared across applications
- Atomic Commits: Changes to multiple packages can be committed together
- Efficient Development: Single command to work with all parts of the project
- Consistent Dependencies: Centralized dependency management avoids version conflicts
- Scalability: Easy to add new applications (web, admin panel, etc.) to share existing packages
Core Architecture Components
Turborepo: Build Orchestration
Turborepo is the backbone of our monorepo, providing intelligent caching and task orchestration.
{
"$schema": "https://turbo.build/schema.json",
"ui": "tui",
"tasks": {
"build": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**", "**/*.d.ts"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}Key Features:
- Caching: Intelligent caching of build outputs to speed up subsequent builds
- Task Dependencies: Automatic handling of inter-package dependencies
- Parallel Execution: Multiple tasks run in parallel when possible
- Selective Builds: Build only packages that changed
PNPM Workspaces: Package Management
PNPM provides efficient package management with workspace support:
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"Benefits:
- Disk Efficiency: Shared dependencies stored once
- Fast Installation: Faster than npm/yarn for monorepos
- Strict Dependencies: Prevents phantom dependencies
Workspace Structure
Applications (apps/)
Applications are runnable entry points for each platform.
apps/
├── native/ # Expo + React Native mobile app (iOS & Android)
│ ├── src/ # Platform-specific source code
│ ├── assets/ # Shared mobile assets and fonts
│ ├── app.config.ts # Expo configuration (and EAS presets)
│ └── package.json # Mobile-only dependencies
├── web/ # Next.js web app (marketing, docs, admin, etc.)
│ ├── app/ # File-based routes powering the web experience
│ ├── public/ # Static web assets
│ └── package.json # Web-only dependencies and scripts
└── integrations/ # Experimental or partner integrations (optional)Packages (packages/)
Packages are reusable code that can be shared across applications.
packages/
├── backend/ # @vibefast/backend
│ ├── convex/ or supabase/ # Backend code (depends on your choice)
│ ├── index.ts # Package exports
│ └── package.json # Backend dependencies
└── ui/ # Shared UI components
├── components/ # Reusable components
├── index.ts # Package exports
└── package.json # UI dependenciesRoot Configuration
The root contains shared configuration and workspace-level tools:
. # Root directory
├── turbo.json # Turborepo configuration
├── pnpm-workspace.yaml # PNPM workspace configuration
├── package.json # Workspace scripts and dev dependencies
├── eslint.config.mjs # Shared linting configuration
└── tsconfig.json # Shared TypeScript configurationDevelopment Workflow
Running Applications
# Start all applications in development mode
pnpm dev
# Start only the native app
pnpm dev:native
# Start only the backend
pnpm dev:server
# Start with specific environment
APP_ENV=staging pnpm dev:nativeBuilding Applications
# Build all applications
pnpm build
# Build specific application
pnpm build:native
# Build backend package
pnpm build:backendTesting
# Run tests for all packages
pnpm test
# Run tests for specific package
pnpm --filter native test
# Run E2E tests
pnpm native:e2e-test
# Type checking
pnpm check-types
# Linting
pnpm lintPackage Management
Adding Dependencies
Dependencies are added to specific packages or workspace-wide:
# Add to specific package
pnpm --filter native add react-native-some-lib
# Add to all packages
pnpm add -W typescript@latest
# Add dev dependency to workspace
pnpm add -D -W @types/nodeInternal Dependencies
Packages can depend on each other using workspace references:
// apps/native/package.json
{
"dependencies": {
"@vibefast/backend": "workspace:*",
"ui": "workspace:*"
}
}Environment Management
The monorepo supports multiple environments with specific configurations:
Environment Files
# Environment-specific configurations
.env.local # Local development
.env.staging # Staging environment
.env.production # Production environmentEnvironment Variables
Key environment variables are used across the workspace:
# App environment
APP_ENV=local|staging|production
# Backend URLs
CONVEX_SITE_URL=http://localhost:3001
CONVEX_DEPLOYMENT=...
# API keys
OPENAI_API_KEY=...
GOOGLE_GENERATIVE_AI_API_KEY=...Build Orchestration
Task Pipeline
Turborepo orchestrates tasks based on dependencies:
1. Install dependencies (pnpm install)
2. Build shared packages (ui, backend)
3. Build applications (native)
4. Run tests (if needed)Caching Strategy
- Build Outputs: Cached in
.turbodirectory - Dependencies: Cached based on
package.jsonchanges - Environment Variables: Considered in cache keys when specified
- Source Changes: Triggers selective rebuilds
Publishing and Deployment
Application Deployment
Each application can be deployed independently:
# Deploy native app
pnpm native:build:production
# Deploy with specific profile
pnpm native:build:stagingPackage Publishing
Packages can be published to npm registries:
# Build package
pnpm --filter backend build
# Publish package
pnpm --filter backend publishBest Practices
1. Package Boundaries
- Keep packages focused on single responsibilities
- Minimize cross-package dependencies
- Use explicit exports rather than deep imports
2. Development Efficiency
- Use
pnpm devfor full-stack development - Leverage Turborepo caching for faster builds
- Run
pnpm check-typesbefore committing
3. Code Organization
- Group related features within packages
- Use barrel exports (
index.ts) for clean imports - Follow consistent naming conventions
4. Testing Strategy
- Unit tests in individual packages
- Integration tests across packages
- E2E tests for complete applications
Troubleshooting
Common Issues
Dependency Conflicts:
# Clear all caches and reinstall
rm -rf node_modules .turbo
pnpm installBuild Cache Issues:
# Clear Turborepo cache
pnpm turbo cleanWorkspace Resolution:
# Verify workspace setup
pnpm ls --depth=0Environment Variables:
# Check current environment
echo $APP_ENV
# List environment files
ls -la .env*This monorepo architecture provides a solid foundation for scaling your mobile application development while maintaining code quality and development efficiency.
Found an issue or bug in the docs?
Help me improve! If you spot any errors, typos, or have suggestions, please let me know.
Reach out on X/Twitter @zafarbuildzz