Introduction To The Monorepo
What is a Monorepo?
A monorepo (monolithic repository) is a software development strategy where multiple related projects, packages, and applications are stored in a single version control repository. Unlike a multi-repo approach where each project has its own repository, a monorepo centralizes all code in one place while maintaining logical separation between different components.
Key Characteristics of Monorepos
- Single Source of Truth: All code, documentation, and configurations live in one repository
- Shared Dependencies: Common libraries and tools are shared across projects
- Atomic Changes: Cross-project changes can be made in a single commit
- Unified Tooling: Consistent build, test, and deployment processes
- Better Collaboration: Teams can easily see and coordinate changes across projects
How This Monorepo Works
Our nextjs-web monorepo is specifically designed to manage multiple Next.js applications and shared packages efficiently. Here's how the key components work together:
Repository Structure
nextjs-web/
├── apps/ # Multiple Next.js applications
│ ├── beacon-docs/ # Beacon design system documentation (Docusaurus)
│ ├── client-central/ # Client management system
│ ├── client.schwab.com/ # Client portal application
│ ├── docs/ # Technical documentation (this site)
│ ├── meganav-mfe/ # Mega navigation micro-frontend
│ ├── nextapi.schwab.com/ # API services
│ ├── nexttools.schwab.com/# Internal development tools
│ ├── sanity-next/ # Sanity CMS demo Next.js app (POC)
│ ├── sanity-studio/ # Sanity CMS admin interface
│ ├── storybook/ # Component library documentation
│ └── www.schwab.com/ # Main public website
├── packages/ # Shared libraries and utilities
│ ├── cli/ # Command-line tools
│ ├── fetch/ # HTTP client utilities
│ ├── mock-data/ # Test data and mocks
│ ├── processors/ # Data processing utilities
│ ├── schema/ # Data schemas and validation
│ ├── security/ # Security utilities and middleware
│ ├── server-actions/ # Next.js server actions
│ ├── test/ # Testing utilities and setup
│ ├── transformer/ # Code transformation utilities
│ ├── tsconfig/ # TypeScript configurations
│ ├── twconfig/ # Tailwind CSS configurations
│ ├── ui/ # React component library
│ └── utilities/ # Common utility functions
└── package.json # Root workspace configuration
Package Management with pnpm
We use pnpm workspaces to manage dependencies across the monorepo:
- Shared Dependencies: Common packages like React and Next.js are deduplicated
- Workspace Protocol: Internal packages reference each other using
workspace:* - Efficient Storage: pnpm's content-addressable storage reduces disk usage
- Fast Installs: Symlinks and hard links make installations lightning-fast
Build Orchestration with Turbo
Turborepo handles the complex task of building multiple interdependent packages:
- Dependency Graph: Automatically determines build order based on package dependencies
- Incremental Builds: Only rebuilds packages that have changed or depend on changed packages
- Parallel Execution: Builds multiple packages simultaneously when possible
- Intelligent Caching: Caches build outputs to skip redundant work
Integration with Vercel and Next.js
Our monorepo is optimized for deployment on Vercel with multiple Next.js applications:
Vercel Monorepo Support
Vercel provides first-class support for monorepos through:
- Project Configuration: Each application in
/appscan be deployed as a separate Vercel project - Build Detection: Vercel automatically detects Next.js applications and configures appropriate build settings
- Turbo Integration: Native support for Turborepo caching and build orchestration
- Environment Variables: Application-specific environment management
Next.js Application Architecture
Each Next.js application in our monorepo:
- Independent Deployment: Can be deployed separately with its own domain and configuration
- Shared Components: Imports UI components from
@schwab/uipackage - Common Utilities: Uses shared utilities for consistent functionality
- Unified Styling: Shares Tailwind CSS configurations via
@schwab/twconfig
Build and Deployment Flow
- Change Detection: When code changes, Turbo identifies affected packages
- Dependency Resolution: Builds packages in the correct order based on dependencies
- Application Building: Next.js applications are built with updated dependencies
- Deployment: Vercel deploys only the applications that need updates
Benefits in Our Context
For Development Teams
- Code Reuse: Shared components and utilities reduce duplication
- Consistent Standards: Unified linting, formatting, and TypeScript configurations
- Cross-Application Features: Easy to implement features spanning multiple applications
- Simplified Dependencies: Single
package.jsonmanages all external dependencies
For Deployment and Operations
- Atomic Releases: Related changes across applications can be deployed together
- Simplified CI/CD: Single pipeline handles multiple applications
- Version Synchronization: Ensures all applications use compatible dependency versions
- Reduced Infrastructure: Fewer repositories to manage and secure
For Next.js Specifically
- Shared Next.js Configuration: Common configurations in
next.config.jsfiles - Component Library: Shared React components with consistent styling
- API Route Sharing: Common API utilities and middleware
- Performance Optimization: Shared bundles and optimized builds
Getting Started
To work with this monorepo effectively:
- Install Dependencies:
pnpm installat the root installs all dependencies - Development: Use
pnpm dev-[app-name]to start specific applications - Building: Use
pnpm buildto build all applications, or target specific ones - Testing: Run
pnpm testto execute tests across all packages
Development Environment Setup
Schwab Scripts Directory (/home/schwab-scripts)
The monorepo development environment includes a dedicated scripts directory at /home/schwab-scripts that contains essential setup and maintenance scripts for the containerized development environment. These scripts automate the complex configuration required for working within Schwab's corporate infrastructure.
Key Components
- Container Setup: Automated environment initialization and configuration
- Git Configuration: Corporate SSL certificates, authentication, and repository setup
- Package Manager Setup: PNPM configuration for internal registries and proxy settings
- Quality Gates: Git hooks enforcing code quality standards before commits and pushes
- Utility Scripts: Port cleanup and maintenance tools
Integration with Monorepo
The scripts in /home/schwab-scripts are specifically designed to work with this monorepo:
- Repository Cloning: Automatically clones the
nextjs-webrepository with proper authentication - Dependency Installation: Runs
pnpm installto set up all monorepo dependencies - Git Hooks Installation: Installs quality gate hooks that run Turborepo commands:
- Pre-commit: Branch name validation
- Pre-push: Linting, type checking, conformance, testing, and building
- Development Server Support: Includes utilities for managing development server ports
Corporate Environment Integration
These scripts handle the complex corporate environment requirements:
- Proxy Configuration: Supports both ZScaler and BlueCoast proxy setups
- SSL Certificates: Configures Schwab's internal SSL certificates for secure connections
- Internal Registries: Configures access to Schwab's private npm registries for
@schwabpackages - Authentication: Handles GitHub tokens and internal registry authentication
For detailed information about these scripts, see the Startup Scripts documentation.
This monorepo structure, combined with the automated setup scripts, enables our team to maintain multiple Next.js applications efficiently while ensuring consistency, code reuse, and streamlined deployment processes through Vercel's platform.