Table of contents
- What is a monorepo?
- Example structure for frontend and backend
- Tooling essentials for monorepos
- Best practices for pull requests in a monorepo
- How Graphite helps with monorepo PRs
- Example workflow with Graphite
- Additional best practices
- Summary
What is a monorepo?
A monorepo is a single Git repository that contains multiple related projects—such as frontend and backend—managed under the same root. This setup improves atomic changes, code reuse, dependency coordination, and cross-functional collaboration. Large companies like Google, Facebook, and Airbnb rely on monorepos for scale and maintainability.
Example structure for frontend and backend
Here's a simple directory layout for a monorepo that contains both frontend and backend apps:
/monorepo├── frontend│ ├── package.json│ └── src/├── backend│ ├── package.json│ └── src/└── packages└── shared/└── utils/
- Frontend and backend each live in their own isolated directories.
- Shared utilities go under
packages/shared/
to allow code reuse without introducing unnecessary dependencies.
Tooling essentials for monorepos
Use specialized tooling to manage scale and complexity:
- Dependency isolation: Use Yarn Workspaces, pnpm, or Lerna to handle local packages and shared dependencies.
- Build tools: Consider Vite or Webpack for frontend, and a language-appropriate bundler for backend (e.g., esbuild for TypeScript, or just native Go/Python compilation).
- CI orchestration: Use Turborepo, Nx, or Bazel to define task pipelines and only rebuild/test the parts of the codebase that changed.
Best practices for pull requests in a monorepo
Keep PRs small and focused
Avoid "mega PRs" that touch both frontend and backend at once unless necessary. For example:
- ✅ Add a new shared utility and update its usage across frontend/backend.
- ❌ Refactor frontend routing + backend auth + some unrelated linter changes.
Use stacked pull requests
Break work into dependent PRs that build on each other:
PR #1: Introduce new API in shared/utilsPR #2: Use new API in frontendPR #3: Use new API in backend
This makes code easier to review and reduces merge conflicts.
Automate merge and rebase flows
Use merge queues and automation tools to keep things flowing:
- Avoid manual rebasing.
- Gate merges behind passing CI.
- Prevent conflicts by merging base PRs first.
How Graphite helps with monorepo PRs
Graphite is built to streamline code review and merging in monorepos. It provides:
Stacked pull request support
Graphite turns a sequence of related changes into a clear stack. You can:
- Push stacks with
gt stack submit
. - Review them top-to-bottom in a unified UI.
- Merge in the correct order.
This is especially helpful when a change spans shared packages, frontend, and backend.
Graphite Merge Queue
Graphite's merge queue automatically:
- Rebases your PRs onto the trunk.
- Runs CI only where needed.
- Merges PRs safely and sequentially.
This reduces the need for manual intervention and flaky test reruns.
CI optimization
Graphite understands which packages are affected and skips unnecessary jobs. For example, if only the frontend was touched, backend tests are skipped.
Developer notifications and team workflows
Graphite also integrates with Slack to notify reviewers when stacks are blocked or ready to review. Its shared inbox UI helps distributed teams triage reviews faster.
Example workflow with Graphite
Create three PRs:
- PR 1: Add utility to
shared/utils
- PR 2: Update frontend
- PR 3: Update backend
- PR 1: Add utility to
Submit them as a stack with Graphite:
Terminalgt stack submitReviewers use Graphite's interface to review all PRs in one pass.
Once approved, Graphite handles CI, rebasing, and merges in order.
This makes large cross-cutting changes safe and efficient.
Additional best practices
- Use feature flags to ship changes incrementally across frontend/backend.
- Split CI pipelines: Only run frontend tests if frontend code changes.
- Enforce shared linting across packages with ESLint, Prettier, etc.
- Use path aliases to avoid long relative imports across packages.
- Define ownership boundaries: Use CODEOWNERS or team labels to control review responsibility.
Summary
Managing frontend and backend in a single monorepo enables better code sharing, easier atomic changes, and centralized tooling—but requires discipline. With the right structure, clear PR strategy, and tools like Graphite, teams can stay fast, organized, and confident even as the codebase grows.