Monorepos And Root Directories
A monorepo is a single repository that contains more than one project or package. A team might keep a marketing site, dashboard app, admin app, shared UI package, API helpers, and documentation in one repository. Vercel can deploy projects from monorepos, but you need to tell each Vercel project which part of the repository it owns.
The beginner mistake is importing a monorepo as though it were a single app at the repository root. That can make Vercel run the wrong build command, install from the wrong directory, miss shared packages, or redeploy apps that were not affected by a change.
Why Monorepos Exist
Monorepos help teams share code and coordinate changes. A design system package can be used by multiple apps. A shared TypeScript config can keep projects consistent. A marketing site and product app can update together when a brand or API contract changes.
A simple monorepo might look like this:
apps/web
apps/admin
apps/docs
packages/ui
packages/config
package.json
pnpm-workspace.yaml
Each app may become its own Vercel project. The web app can deploy to the public domain. The admin app can deploy to a protected domain. The docs app can deploy to a documentation domain. They share packages, but they are not the same deployment.
Root Directory
The Root Directory setting tells Vercel where the app lives inside the repository. If the app is in apps/web, the Vercel project should use that as its root. Build commands, framework detection, output settings, and environment expectations are evaluated relative to that project configuration.
Root Directory is one of the first settings to check when a monorepo deployment fails. If Vercel looks at the repository root but the app lives in a subdirectory, it may not find the framework, scripts, or package files it expects.
A practical review asks:
Which app does this Vercel project deploy?
What is its root directory?
Where is its package.json?
Which lockfile and package manager are used?
Which shared packages does it import?
Which domain should it own?
Write those answers down for the team.
Multiple Vercel Projects
A monorepo often maps to multiple Vercel projects. One repository can contain several apps, and each app can have its own project settings, domains, Environment Variables, Deployment Protection, analytics, and build behavior.
This separation is useful. The admin app may need stricter protection than the marketing site. The docs site may use different environment variables than the dashboard. A small UI package may not deploy directly at all.
Do not copy settings blindly between projects. A public marketing site and a private admin app should not necessarily share the same domains, environment variables, protection settings, or build rules.
Shared Packages
Shared packages are a major reason to use a monorepo. A UI package might export buttons, forms, and layout components. A config package might export lint or TypeScript settings. A utilities package might hold shared validation code.
Shared packages create build dependencies. If apps/web imports packages/ui, the build must be able to install and compile both. The package manager workspace configuration matters. The lockfile matters. The build cache should understand when shared package changes affect each app.
A common mistake is changing a shared package and expecting only one app to be affected. If three apps import the package, all three may need testing. Preview Deployments make that review easier, but only if each Vercel project is configured correctly.
Ignored Build Steps
Monorepos can trigger too many builds if every commit redeploys every project. Ignored build steps let a project skip deployment when a change does not affect it. This can reduce build minutes, noise, and review clutter.
Use ignored build logic carefully. If the rule is too broad, a project may skip a deployment that it actually needed. Shared package changes are the tricky case. A change outside the app root may still affect the app if it touches a dependency.
Before enabling ignored builds, list the paths that affect the project:
its app directory
shared packages it imports
root package manager files
lockfiles
build configuration
shared environment or tooling files
A good ignored-build rule is conservative and documented.
Environment Variables In Monorepos
Each Vercel project has its own Environment Variables. In a monorepo, that is usually what you want. The web app, admin app, and docs app may use different public API URLs, tokens, feature flags, or storage resources.
Avoid using one giant shared set of secrets for every project. If the docs site does not need a payment secret, do not give it one. Smaller access reduces damage when a project is misconfigured or compromised.
Preview and Production separation still matters. A preview of the admin app should not casually write to production data because it lives in the same repository as production code.
Build Commands And Package Managers
Monorepos often use npm workspaces, pnpm, Yarn, Bun, Turborepo, Nx, or another task runner. Vercel can support common monorepo workflows, but the commands must match the repository.
Do not paste a build command from a different project. Check how the app is built locally. A Turborepo project may build through a root pipeline. A simple app may build from its own root directory. A package manager command may need a filter to build only one workspace.
The build should be reproducible from a clean checkout. If it only works because a developer has a global package, uncommitted file, or local environment variable, Vercel may fail.
Review Workflow
A monorepo pull request can affect multiple deployments. Reviewers should know which previews matter. If a shared UI package changes, open the previews for every app that imports it. If only docs changed, the production app may not need review.
A good pull request description for a monorepo names affected apps, preview URLs, and test scope. That saves reviewers from guessing which Vercel deployment to open.
Dependency Boundaries
A monorepo works best when dependencies flow in clear directions. An app can depend on a shared UI package. A shared UI package can depend on design tokens. But a shared package should not quietly import app-specific environment variables, production-only services, or code from one app's private directory. Those hidden dependencies make builds surprising.
Keep shared packages boring and reusable. If a package is meant to be shared by web and admin apps, it should not assume one app's domain, authentication provider, route structure, or storage bucket. Pass app-specific values through configuration or props. That keeps each Vercel project responsible for its own environment.
When a shared package needs a breaking change, treat it like a real dependency upgrade. Update affected apps deliberately, run their previews, and mention the impact in the pull request. The convenience of one repository does not remove the need to review cross-app changes.
Ownership And Access
Monorepos make ownership visible. Several teams may work in one repository, but each Vercel project still needs owners. The team that owns the admin app may need different deployment permissions than the team that edits marketing pages. The person who manages domains may not be the same person who manages database credentials.
Decide who can change project settings, Environment Variables, domains, and protection rules. A small Root Directory change can break production. A copied secret can overexpose a service. A domain change can route real users to the wrong app. These settings deserve review, especially for client and business projects.
For external clients, document which app maps to which domain and which team owns each deployment. Handoffs are much easier when the next developer can see that apps/web deploys the public site, apps/admin deploys the protected admin, and packages/ui does not deploy directly.
Local Development In Monorepos
Local development should mirror deployment closely enough to catch problems early. If the web app depends on a shared package, test changes from a clean install rather than relying only on a running dev server with cached modules. If the package manager uses workspaces, make sure the workspace files are committed and that the lockfile reflects the dependency graph.
When a build fails only on Vercel, compare the local command to the project build command. A developer may have run a root build that compiled every package, while Vercel ran only the app command. Or Vercel may have used the app root while the shared package expected root-level configuration. Aligning commands removes many monorepo surprises.
For long-lived projects, keep a short repository map in developer documentation. Name each app, its Vercel project, its domain, its owner, and the shared packages it depends on. That map pays for itself during incidents, onboarding, and client handoff.
Common Mistakes
The first mistake is setting the wrong Root Directory.
The second mistake is giving every project every secret.
The third mistake is ignoring shared package changes.
The fourth mistake is writing ignored-build rules that skip necessary deployments.
The fifth mistake is assuming one preview URL represents every app in the repository.
The sixth mistake is using a package manager command that only works on one developer machine.
Review Questions
- What does the Root Directory setting control?
- Why might one repository create multiple Vercel projects?
- How can shared packages affect deployment scope?
- Why are ignored build steps risky if written too broadly?
- Why should secrets be scoped per project?
- What should a monorepo pull request tell reviewers?