Production-Ready Full-Stack Project
Combines deployment, security, testing, data, and operational guidance for a full stack application.
Scenario
You maintain a production full-stack SaaS application.
The system includes:
- Next.js frontend;
- Node.js API;
- PostgreSQL;
- background jobs;
- external integrations;
- authentication and authorization;
- generated API types;
- CI/CD;
- automated testing.
The repository has enough complexity that AGENTS.md must help agents understand not only coding conventions but also the system's operational invariants.
This example combines patterns from throughout the course.
Repository Structure
platform/
├── AGENTS.md
├── apps/
│ ├── web/
│ │ ├── AGENTS.md
│ │ └── src/
│ ├── api/
│ │ ├── AGENTS.md
│ │ └── src/
│ └── worker/
│ └── src/
├── packages/
│ ├── ui/
│ ├── database/
│ ├── contracts/
│ └── config/
├── migrations/
├── openapi/
├── tests/
│ ├── integration/
│ └── e2e/
├── .github/
│ └── workflows/
├── pnpm-workspace.yaml
└── package.json
AGENTS.md
Root AGENTS.md:
# Production Repository Instructions
## Development
- Use `pnpm`.
- Follow existing workspace boundaries.
- Inspect local architecture before introducing new patterns.
- Keep changes focused on the requested behavior.
## Workspace Ownership
- Applications live under `apps/`.
- Shared packages live under `packages/`.
- Put code in the workspace that owns the responsibility.
- Do not introduce cross-workspace deep imports when a public interface exists.
## Dependencies
- Declare dependencies in the workspace that directly uses them.
- Check existing repository capabilities before adding packages.
- Avoid unrelated dependency upgrades during targeted work.
## Security
- Never commit or log secrets, tokens, passwords, or private credentials.
- Preserve authentication, authorization, tenant isolation, and audit controls.
- Do not weaken security controls merely to make a feature or test pass.
## Database
- Make production schema changes through new migrations.
- Do not rewrite already-applied migrations.
- Consider existing data and deployment compatibility.
- Use transactions when multiple writes form one atomic business operation.
## Generated Code
- Do not manually edit generated artifacts.
- Identify and modify their authoritative source.
- Regenerate using repository commands and inspect the resulting diff.
## External Integrations
- Use existing integration modules.
- Preserve timeout, retry, webhook-verification, and idempotency behavior.
- Do not assume a failed network response means an external operation did not occur.
## Background Jobs
- Assume retryable jobs may execute more than once.
- Preserve idempotency and deduplication mechanisms.
- Keep job payloads explicit and serializable.
## Testing
- Add or update tests when behavior changes.
- Add regression tests for reproducible bugs when practical.
- Use the lowest test level that provides useful confidence.
- Use E2E tests for critical user journeys.
## Validation
During development, prefer targeted validation.
Before completing substantial or cross-cutting changes, run:
- `pnpm lint`
- `pnpm typecheck`
- `pnpm test`
- `pnpm build`
Validate affected consumers when changing shared packages or public contracts.
## Scope
- Do not combine unrelated refactors, dependency upgrades, or modernization with targeted feature work.
- Report important validation that could not be performed.
apps/web/AGENTS.md:
# Web Application Instructions
## Next.js
- Follow the existing App Router architecture.
- Prefer Server Components unless client behavior is required.
- Keep `"use client"` boundaries narrow.
- Do not expose server-only configuration to browser code.
## UI
- Reuse components from the shared UI package.
- Keep product-specific compositions inside the web application.
- Preserve accessibility and responsive behavior.
## API
- Use the generated API client or existing API abstraction.
- Do not duplicate API contracts manually.
## Validation
For web changes, run the relevant web tests and typecheck.
For critical user-flow changes, run the affected E2E tests.
apps/api/AGENTS.md:
# API Application Instructions
## Architecture
Keep responsibilities separated:
- routes/controllers handle HTTP;
- services handle business workflows;
- repositories handle persistence;
- integration modules handle external providers.
## Authorization
- Authenticate protected operations.
- Authorize access to the specific resource.
- Preserve tenant boundaries.
- Do not trust client-supplied ownership or role claims.
## Database
- Use existing repositories and transaction helpers.
- Do not execute ad hoc persistence logic from controllers.
- Preserve concurrency and idempotency controls.
## API Contracts
- Keep implementation and public API specifications synchronized.
- Consider existing consumers before introducing breaking changes.
## Validation
Run relevant API tests, integration tests, lint, and typecheck.
What This Does
This creates a layered instruction system.
The root answers repository-wide questions:
How do we manage dependencies?
How do we handle security?
How do migrations work?
What should never be edited manually?
What validation is expected?
The scoped application files answer more specific questions:
How should Next.js code be structured?
Where does API business logic belong?
How are authorization checks performed?
The result is not one enormous file containing every detail.
Instead:
Root
↓
repository invariants
Scoped files
↓
application-specific behavior
What This Does NOT Do
The instructions do not attempt to document the entire system.
They do not replace:
architecture diagrams
API documentation
runbooks
incident procedures
deployment documentation
product requirements
AGENTS.md should contain actionable guidance needed while changing the repository.
The file also does not say every change requires:
lint
typecheck
all tests
full build
E2E suite
during every iteration.
It explicitly distinguishes:
targeted development feedback
from:
broader completion validation
Why These Instructions Matter
Production failures often occur between components rather than inside one function.
For example:
Frontend
↓
API contract
↓
authorization
↓
service
↓
transaction
↓
database
↓
background job
↓
external provider
A feature can compile successfully while still violating an invariant somewhere in this chain.
Consider an account-upgrade workflow:
User requests upgrade
↓
API authorizes organization
↓
payment provider called
↓
subscription updated
↓
job sends confirmation
The implementation needs to consider:
authorization
payment idempotency
transaction boundaries
retry behavior
external failure
testing
observability
Production-oriented instructions help agents preserve these concerns while making local changes.
Key Decisions
Put invariants at the root
Rules that protect the entire repository belong at broad scope.
Examples include:
secret handling
migration policy
generated-code ownership
dependency discipline
general validation
Put architecture near the application
Next.js rules do not need to distract an agent working only on the API.
API controller/service/repository rules do not need to live in the web application's instructions.
Protect boundaries, not every implementation detail
Good instructions describe:
ownership
dependency direction
security boundary
validation expectation
source of truth
operational invariant
They do not attempt to dictate every function body.
Automate enforceable rules
Important invariants should use tooling where practical:
lint rules
type checking
tests
RLS
database constraints
CI
package boundaries
AGENTS.md guides the agent.
Automation verifies what can be mechanically verified.
Match validation to blast radius
Think:
What changed?
↓
What can it affect?
↓
What evidence gives confidence?
A local utility change and a shared authentication change should not automatically receive identical validation.
Keep instructions current
An outdated instruction can be worse than no instruction.
When architecture, commands, generated workflows, or package boundaries change, update the relevant AGENTS.md.
Prefer repository truth over generic advice
The best instruction is not:
- Follow best practices.
It is something actionable and repository-specific:
- Access persistence through repositories.
- Do not disable RLS to make a query succeed.
- Modify `openapi/openapi.yaml` instead of generated client files.
- Use the existing transaction helper for atomic workflows.
When to Use This Pattern
Use this pattern when:
- a production repository contains multiple applications or packages;
- several technologies interact;
- security and data integrity matter;
- background processing exists;
- external services are integrated;
- generated artifacts exist;
- different scopes require different instructions;
- multiple developers or coding agents contribute regularly.
This example represents the main lesson of the course:
A strong AGENTS.md does not try to teach an agent everything about software engineering.
It gives the agent the repository-specific context needed to make safe decisions:
What owns this code?
What should I modify?
What should I not modify?
Which boundaries must I preserve?
What is the source of truth?
How should I validate the change?
When those questions are answered clearly, AGENTS.md becomes more than a list of commands.
It becomes an operational guide for changing the repository safely.