In modern full-stack projects, frontend, backend, shared libraries, and utility scripts are often tightly interwoven. As features grow and teams expand, using multiple independent repositories (polyrepo) can lead to several challenges:
- Inconsistent versions of shared modules
- Confusing imports and mismatched types
- Difficulty keeping cross-project refactors consistent
- Scattered and hard-to-maintain configuration
Against this backdrop, Monorepo—keeping multiple sub-projects in a single repository—becomes an attractive solution.
However, it’s a misconception that Monorepo fits all projects. In this article, we will cover:
- Suitable scenarios for Monorepo
- Why PawHaven chose Monorepo
- Architecture design and directory structure
- Configuration reuse practices
1. When is Monorepo Suitable?
Monorepo has clear boundaries for its effectiveness. The following scenarios benefit the most:
Scenario | Reason |
---|---|
Multiple tightly-coupled sub-projects/modules | Need to share types, DTOs, utilities, etc. |
Frequent cross-module changes/refactoring | One commit can update multiple packages simultaneously |
Team coordination is manageable | Frequent inter-module collaboration |
Desire for unified CI/CD pipelines | Shared pipelines, caching, and dependency management |
Want to reuse configuration and toolchains | Centralized management for ESLint, tsconfig, styles |
Reduce version conflicts | Shared dependencies are easier to align in one repo |
Situations where Monorepo may not be suitable:
- Small projects with simple module relationships
- Modules with almost no shared logic
- Significantly different tech stacks making unified config difficult
- Distributed teams requiring strict permission separation
Challenges to be aware of:
As the repository grows, build, clone, and CI times may increase.
Access control, dependency boundaries, and tooling also become more complex.
✅ Conclusion: Monorepo isn’t inherently “better” or “advanced”; it should be adopted after carefully weighing the benefits against the added complexity.
2. Why PawHaven Chose Monorepo
PawHaven is a full-stack project consisting of React frontend + NestJS backend + shared libraries. The decision to adopt Monorepo was driven by several factors:
1. Shared Types, DTOs, and Utilities
Interfaces, constants, and types shared between frontend and backend can be maintained in a single repository. TypeScript path aliases or workspace references avoid duplicate maintenance.
2. Unified Configuration Management
Centralized management of ESLint, tsconfig, Tailwind, etc., allows sub-packages to inherit configurations directly, maintaining consistency and reducing maintenance costs.
3. Cross-Package Changes in a Single Commit
When shared components, DTOs, or backend interfaces need synchronized updates, a single PR can handle all changes, ensuring compatibility.
4. Centralized CI/CD Pipeline
Build, test, and deployment processes are defined once at the repo level, with shared caching and toolchains, simplifying continuous integration.
5. Dependency Hoisting and Version Consistency
Using pnpm's hoist mechanism, all sub-packages share the same dependency versions, minimizing conflicts.
6. Single Entry Point Reduces Communication Overhead
For an open-source project, having one repository means developers, documentation, and promotional materials only need to focus on a single source, reducing coordination overhead across multiple repos.
3. Monorepo Structure Design & PawHaven Example
Design Principles
- Separation of business and non-business code: Clearly distinguish deployable apps from shared libraries
- Centralized configuration: ESLint, tsconfig, Tailwind maintained in independent config packages
-
Consistent structure: Each sub-package follows uniform directory conventions (
src/
,tsconfig.json
,package.json
) - Simplified imports: Use alias/workspace references instead of deep relative paths
- Toolchain compatibility: Build, type-check, and lint processes cover cross-package paths
🧭 PawHaven Directory Structure
├─ pnpm-lock.yaml
├─ pnpm-workspace.yaml
├─ apps
│ ├─ backend
│ │ ├─ gateway
│ │ ├─ ms-auth
│ │ ├─ ms-document
│ │ └─ ms-pawhaven
│ └─ frontend
│ ├─ user
│ └─ admin
├─ packages
│ ├─ shared-frontend
│ ├─ i18n
│ ├─ shared-backend
│ ├─ theme
│ └─ ui
├─ libs
│ └─ configs
│ ├─ eslint-config
│ └─ tsconfig
├─ .vscode/
│ ├─ settings.json
│ └─ extensions.json
Directory Explanation:
-
apps/
: Independent frontend and backend business modules -
packages/
: Shared modules related to business (UI, theme, i18n, shared types) -
libs/
: Utility and configuration libraries, can be independently published
4. Unified Configuration (ESLint / tsconfig / Tailwind)
1️⃣ ESLint
Goal: Provide consistent rules for both Web and Node environments.
Implementation:
- Centralized ESLint configs in
libs/configs/eslint/
- Separate configs for Web (
eslint-config-web
) and Node (eslint-config-node
) - Sub-packages inherit and can override rules as needed
📦 Reference: PawHaven/libs/eslint
2️⃣ tsconfig
Goal: Unified TypeScript compilation options with support for multiple targets (Web/Node).
Implementation:
- Base configuration in
libs/configs/tsconfig/base.json
with environment-specific extensions - Sub-packages only override output paths, rootDir, or other necessary options
📦 Reference: PawHaven/libs/tsconfig
3️⃣ Tailwind Design System
Goal: Ensure consistent styling across all frontend packages and UI components.
Implementation:
- Centralized design tokens and global Tailwind config in
packages/theme/
- Shared theme between UI library and frontend apps
- Ensure content scanning paths include shared component files
📦 Reference: PawHaven/packages/theme
5. Conclusion
PawHaven’s Monorepo architecture enables:
- Centralized multi-module management and collaboration
- Unified ESLint, TypeScript, and Tailwind configurations
- Shared types and consistent dependencies between frontend and backend
- Improved development efficiency and maintainability
✅ Key Takeaway: Monorepo is not about being “advanced” but about achieving coordination.
Careful evaluation of project scale, team structure, and maintenance costs is essential before adoption.
💡 Further Reading & Open Source Practice
For more enterprise-level full-stack, frontend, backend, and Monorepo practices, you can Star or Watch the repository:
👉 https://github.com/aoda-zhang/PawHaven
Top comments (0)