Full-Stack Monorepo
Aligns frontend, backend, shared packages, workspace commands, and ownership rules across a monorepo.
Scenario
You maintain a production full-stack monorepo containing multiple applications and shared packages.
The repository contains:
- Next.js web application;
- Node.js API;
- background worker;
- shared UI library;
- shared TypeScript packages;
- pnpm workspaces.
Different areas have different development and validation requirements.
A single large root AGENTS.md would force every coding agent to load instructions that may not apply to its task.
Instead, the repository uses scoped AGENTS.md files.
Repository Structure
platform/
├── AGENTS.md
├── apps/
│ ├── web/
│ │ ├── AGENTS.md
│ │ └── src/
│ ├── api/
│ │ ├── AGENTS.md
│ │ └── src/
│ └── worker/
│ └── src/
├── packages/
│ ├── ui/
│ │ ├── AGENTS.md
│ │ └── src/
│ ├── database/
│ │ └── src/
│ └── shared/
│ └── src/
├── pnpm-workspace.yaml
└── package.json
AGENTS.md
The root AGENTS.md contains rules that apply across the repository.
# Repository Instructions
## Workspace
- Use `pnpm` for dependency management.
- Run workspace commands from the repository root unless package-specific instructions say otherwise.
- Do not create npm or Yarn lockfiles.
## Repository Structure
- Applications live under `apps/`.
- Shared libraries live under `packages/`.
- Do not import application code from another application.
- Move genuinely shared functionality into an appropriate package.
## Dependencies
- Declare dependencies in the package that directly uses them.
- Do not add dependencies to the workspace root only to make them available to child packages.
- Reuse existing workspace packages when they already provide the required functionality.
## Validation
- Run validation for every affected package.
- If a shared package changes, validate its affected consumers.
The web application adds frontend-specific instructions.
apps/web/AGENTS.md:
# Web Application Instructions
## Architecture
- Use the Next.js App Router.
- Prefer Server Components unless client-side behavior is required.
- Keep reusable product components outside route folders.
## Shared UI
- Reuse components from `packages/ui` when an appropriate shared component exists.
- Do not duplicate shared design-system components inside the web application.
## Validation
For web changes, run:
- `pnpm --filter web lint`
- `pnpm --filter web typecheck`
- `pnpm --filter web test`
The API has different requirements.
apps/api/AGENTS.md:
# API Instructions
## Architecture
- Keep HTTP controllers thin.
- Put business logic in the existing service layer.
- Access persistence through the repository/data-access layer.
## API Changes
- Validate request input at the HTTP boundary.
- Preserve the existing error-response format.
- Update API tests when endpoint behavior changes.
## Validation
For API changes, run:
- `pnpm --filter api lint`
- `pnpm --filter api typecheck`
- `pnpm --filter api test`
The shared UI package defines its own boundary.
packages/ui/AGENTS.md:
# Shared UI Instructions
## Components
- Components in this package must remain application-agnostic.
- Do not import from `apps/`.
- Do not include product-specific business logic.
## Public API
- Export public components through the package's existing public entry point.
- Avoid exposing internal component utilities unless they are intentionally part of the package API.
## Validation
For UI package changes, run:
- `pnpm --filter ui lint`
- `pnpm --filter ui typecheck`
- `pnpm --filter ui test`
What This Does
This structure separates repository-wide rules from area-specific rules.
The root file establishes rules such as:
package manager
workspace organization
dependency ownership
cross-application boundaries
shared-package validation
Nested files then provide instructions relevant to their area.
For example:
apps/web/AGENTS.md
does not need to explain API controller architecture.
Likewise:
apps/api/AGENTS.md
does not need instructions about React Server Components.
This keeps instructions closer to the code they govern.
What This Does NOT Do
Nested files should not repeat the entire root file.
For example, this would be unnecessary in every nested file:
- Use `pnpm`.
- Applications belong in `apps/`.
- Packages belong in `packages/`.
Those rules already apply repository-wide.
The structure also does not require an AGENTS.md in every directory.
For example:
apps/worker/
packages/database/
packages/shared/
do not automatically need their own files.
A nested file should exist because that scope has meaningful instructions that differ from or extend the broader scope.
Why These Instructions Matter
A monorepo creates boundaries that may not be obvious from individual files.
Suppose an agent working in:
apps/web/
needs a formatting utility.
It could create:
apps/web/src/utils/formatCurrency.ts
But if the same functionality is already used by the API and worker, the correct location may be:
packages/shared/
The root instruction:
- Move genuinely shared functionality into an appropriate package.
encourages the agent to consider the repository boundary before introducing duplication.
Another example is the UI package.
Without:
- Do not import from `apps/`.
an agent might accidentally make a shared package depend on application-specific code.
That reverses the intended dependency direction.
Key Decisions
Put universal rules at the root
Rules that genuinely apply everywhere belong in:
/AGENTS.md
Examples include:
- package manager;
- workspace layout;
- dependency ownership;
- global repository boundaries.
Put specialized rules near specialized code
Next.js instructions belong with the web application.
API layering instructions belong with the API.
Shared-component constraints belong with the UI package.
This follows a useful principle:
Place an instruction at the broadest scope where it remains universally true.
Nested files should add information
A nested file should usually answer:
What does an agent need to know here that it did not already learn from the broader instructions?
If the answer is "nothing," a nested file probably isn't necessary.
Validate affected consumers
Shared packages introduce another concern.
Suppose:
packages/ui
changes.
Its own tests may pass while:
apps/web
fails because the application consumes the changed component.
That is why the root file explicitly says:
- If a shared package changes, validate its affected consumers.
This is a repository-specific workflow rule that an agent may not safely infer.
When to Use This Pattern
Use this pattern for repositories where:
- multiple applications share one repository;
- packages have different architectural responsibilities;
- different areas require different validation commands;
- dependency boundaries matter;
- putting every instruction in one root file would create noise.
Do not introduce nested AGENTS.md files simply because the repository is a monorepo.
Start with root instructions.
Add narrower files when a package or application has enough specialized rules to justify its own scope.