feat: add AGENTS.md for all packages and apps (9 files)
This commit is contained in:
18
apps/cms/AGENTS.md
Normal file
18
apps/cms/AGENTS.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# apps/cms — Payload CMS Admin Shell
|
||||||
|
|
||||||
|
Thin Next.js shell that imports config from `@repo/cms-core` and serves the Payload admin panel. Contains almost no custom code.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- All collections, hooks, globals, and payload.config.ts live in `@repo/cms-core`
|
||||||
|
- This app only contains Next.js routing boilerplate for the admin panel
|
||||||
|
- Import `@payload-config` which resolves to `@repo/cms-core/src/payload.config.ts`
|
||||||
|
- NEVER import from `@repo/core/infrastructure`
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm dev --filter @repo/cms # Starts on port 3001
|
||||||
|
```
|
||||||
|
|
||||||
|
Requires PostgreSQL running (via `docker compose up postgres`).
|
||||||
24
apps/storybook/AGENTS.md
Normal file
24
apps/storybook/AGENTS.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# apps/storybook — Centralized Storybook
|
||||||
|
|
||||||
|
Pulls stories from `packages/ui/src/**/*.stories.tsx`. Uses `@storybook/react-vite` with `@tailwindcss/vite` plugin.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm dev --filter @repo/storybook # Starts on port 6006
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
- `.storybook/main.ts` — Framework config, story globs, Tailwind vite plugin
|
||||||
|
- `.storybook/preview.ts` — Global CSS import, control matchers
|
||||||
|
|
||||||
|
## Story Organization
|
||||||
|
|
||||||
|
Stories are organized by Atomic Design level via title:
|
||||||
|
- `"Atoms/Button"`, `"Molecules/FormField"`, `"Organisms/DataTable"`
|
||||||
|
|
||||||
|
## MCP
|
||||||
|
|
||||||
|
When running, Storybook MCP is available at `http://localhost:6006/mcp`.
|
||||||
|
Install `@storybook/addon-mcp` to enable.
|
||||||
16
apps/web-next/AGENTS.md
Normal file
16
apps/web-next/AGENTS.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# apps/web-next — Next.js 15 Reference App
|
||||||
|
|
||||||
|
Thin Next.js app consuming `@repo/api-client` for data and `@repo/ui` for components.
|
||||||
|
|
||||||
|
## Key Files
|
||||||
|
|
||||||
|
- `src/app/api/trpc/[trpc]/route.ts` — tRPC HTTP endpoint (fetch adapter)
|
||||||
|
- `src/app/providers.tsx` — Wraps with `<ApiProvider>`
|
||||||
|
- `src/app/layout.tsx` — Root layout
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- Use `@repo/api-client` hooks for all data fetching
|
||||||
|
- Use `@repo/ui` components for all UI
|
||||||
|
- tRPC endpoint imports `appRouter` from `@repo/api`
|
||||||
|
- Payload instance initialization goes in `src/lib/payload.ts`
|
||||||
15
apps/web-tanstack/AGENTS.md
Normal file
15
apps/web-tanstack/AGENTS.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# apps/web-tanstack — TanStack Start Reference App
|
||||||
|
|
||||||
|
TanStack Start app consuming `@repo/api-client` for data and `@repo/ui` for components.
|
||||||
|
|
||||||
|
## Key Files
|
||||||
|
|
||||||
|
- `src/routes/__root.tsx` — Root layout with `<ApiProvider>`
|
||||||
|
- `src/routes/index.tsx` — Home page
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- Use `@repo/api-client` hooks for all data fetching
|
||||||
|
- Use `@repo/ui` components for all UI
|
||||||
|
- File-based routing via TanStack Router (`src/routes/`)
|
||||||
|
- Payload instance initialization goes in `src/lib/payload.ts`
|
||||||
27
packages/api-client/AGENTS.md
Normal file
27
packages/api-client/AGENTS.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# @repo/api-client — Shared React Query Hooks
|
||||||
|
|
||||||
|
Framework-agnostic tRPC + React Query provider consumed by all apps.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- NEVER import framework-specific code (no next/, no tanstack/)
|
||||||
|
- NEVER put business logic in hooks
|
||||||
|
- Hooks use `useTRPC()` from `./trpc.ts`
|
||||||
|
- Both Next.js and TanStack Start apps use the same `<ApiProvider>`
|
||||||
|
|
||||||
|
## Usage in Apps
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { ApiProvider, useTRPC } from "@repo/api-client";
|
||||||
|
|
||||||
|
// Root layout:
|
||||||
|
<ApiProvider trpcUrl="/api/trpc">{children}</ApiProvider>
|
||||||
|
|
||||||
|
// In components:
|
||||||
|
const trpc = useTRPC();
|
||||||
|
const articles = trpc.content.listArticles.useQuery({});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding a New Hook (optional wrapper)
|
||||||
|
|
||||||
|
Custom hooks are optional — `useTRPC()` provides typed access to all procedures directly. Only create wrapper hooks if you need shared query logic across multiple components.
|
||||||
17
packages/api/AGENTS.md
Normal file
17
packages/api/AGENTS.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# @repo/api — tRPC Router Definitions
|
||||||
|
|
||||||
|
tRPC routers that call controllers from `@repo/core`. Each procedure validates input and delegates to a controller.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- NEVER put business logic in routers — delegate to controllers
|
||||||
|
- Input validation uses Zod schemas
|
||||||
|
- Each domain gets its own router file
|
||||||
|
|
||||||
|
## Adding a New tRPC Router
|
||||||
|
|
||||||
|
1. Create `src/router/{domain}.router.ts`
|
||||||
|
2. Import `router` and `publicProcedure` from `../trpc.js`
|
||||||
|
3. Define procedures (`.query()` for reads, `.mutation()` for writes)
|
||||||
|
4. Each procedure calls a controller from `@repo/core`
|
||||||
|
5. Add router to root `appRouter` in `src/router/index.ts`
|
||||||
39
packages/cms-client/AGENTS.md
Normal file
39
packages/cms-client/AGENTS.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# @repo/cms-client — Dual-Mode Payload Client
|
||||||
|
|
||||||
|
Provides typed access to Payload CMS via Local API (primary) or HTTP REST (fallback).
|
||||||
|
|
||||||
|
## THIS PACKAGE IS STANDALONE
|
||||||
|
|
||||||
|
- NEVER import from: `@repo/cms-core`, `@repo/core`, `apps/*`
|
||||||
|
- The Payload instance is INJECTED, not imported
|
||||||
|
- Types are generated via `payload generate:types`
|
||||||
|
|
||||||
|
## Initialization
|
||||||
|
|
||||||
|
| Context | Mode | How |
|
||||||
|
|---|---|---|
|
||||||
|
| apps/cms server | Local | `getPayload({config})` from @repo/cms-core |
|
||||||
|
| apps/web-next server | Local | `getPayload({config})` from @repo/cms-core |
|
||||||
|
| apps/web-tanstack server | Local | `getPayload({config})` from @repo/cms-core |
|
||||||
|
| Client-side (browser) | N/A | Goes through tRPC — server handles it |
|
||||||
|
| External services | HTTP | `createPayloadClient({mode:"http",baseURL})` |
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// In app startup (e.g., apps/web-next/src/lib/payload.ts):
|
||||||
|
import { getPayload } from "payload";
|
||||||
|
import { config } from "@repo/cms-core";
|
||||||
|
import { createPayloadClient } from "@repo/cms-client";
|
||||||
|
|
||||||
|
const payload = await getPayload({ config });
|
||||||
|
const client = createPayloadClient({ mode: "local", payload });
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Methods
|
||||||
|
|
||||||
|
All methods support full Payload query capabilities (where, sort, limit, depth, page, populate):
|
||||||
|
|
||||||
|
- `find(collection, options)` — paginated query
|
||||||
|
- `findByID(collection, id, options)` — single document
|
||||||
|
- `create(collection, data, options)` — create document
|
||||||
|
- `update(collection, id, data, options)` — update document
|
||||||
|
- `delete(collection, id)` — delete document
|
||||||
40
packages/cms-core/AGENTS.md
Normal file
40
packages/cms-core/AGENTS.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# @repo/cms-core — Payload CMS Definition
|
||||||
|
|
||||||
|
All Payload configuration lives here: payload.config.ts, collections, globals, hooks, access control. The `apps/cms` app is a thin shell that imports this config.
|
||||||
|
|
||||||
|
## Hook Rules
|
||||||
|
|
||||||
|
| Category | Location | Examples |
|
||||||
|
|---|---|---|
|
||||||
|
| CMS-operational | Stay in hook | Slugify, image resize, default values |
|
||||||
|
| Business logic | Delegate to use case | Notifications, validation, cross-domain updates |
|
||||||
|
|
||||||
|
### DO
|
||||||
|
|
||||||
|
- Keep hooks thin (max 5-10 lines)
|
||||||
|
- Import use cases from `@repo/core/application`
|
||||||
|
- Map Payload hook args to use case input types
|
||||||
|
|
||||||
|
### DON'T
|
||||||
|
|
||||||
|
- Import from `@repo/core/infrastructure`
|
||||||
|
- Put business validation in hooks
|
||||||
|
- Call external services directly from hooks
|
||||||
|
- Duplicate logic that exists in a use case
|
||||||
|
|
||||||
|
## Adding a New Collection
|
||||||
|
|
||||||
|
1. Create folder: `src/collections/{name}/`
|
||||||
|
2. Create: `index.ts` (CollectionConfig), `fields.ts`
|
||||||
|
3. Optionally: `hooks/`, `access/`
|
||||||
|
4. Import in `src/payload.config.ts` collections array
|
||||||
|
5. Export from `src/index.ts`
|
||||||
|
|
||||||
|
## Adding a Hook That Calls a Use Case
|
||||||
|
|
||||||
|
1. Create `src/collections/{name}/hooks/{hook-name}.ts`
|
||||||
|
2. Import use case from `@repo/core` (application layer only)
|
||||||
|
3. Map Payload's hook args to use case input
|
||||||
|
4. Call use case, return data
|
||||||
|
|
||||||
|
**Rule of thumb:** If deleting the hook would break a business requirement, the logic must be in a use case.
|
||||||
59
packages/ui/AGENTS.md
Normal file
59
packages/ui/AGENTS.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# @repo/ui — Atomic Design Component Library
|
||||||
|
|
||||||
|
shadcn/ui + Tailwind CSS v4 + Atomic Design. Components organized by level with co-located stories.
|
||||||
|
|
||||||
|
## Atomic Classification Guide
|
||||||
|
|
||||||
|
| Level | Definition | Examples |
|
||||||
|
|---|---|---|
|
||||||
|
| Atom | Single element, can't break down further | Button, Input, Label, Badge, Separator |
|
||||||
|
| Molecule | 2-3 atoms, single responsibility | FormField, SearchBar, Tooltip, Select |
|
||||||
|
| Organism | Complex section, self-contained | DataTable, Dialog, Header, Sidebar, Card |
|
||||||
|
| Template | Page layout, content-agnostic | DashboardLayout, AuthLayout |
|
||||||
|
| Page | Template + real data | **LIVES IN apps/, NOT HERE** |
|
||||||
|
|
||||||
|
## Import Rules
|
||||||
|
|
||||||
|
| Level | Can import from | NEVER import from |
|
||||||
|
|---|---|---|
|
||||||
|
| Atoms | lib/, hooks/, styles/ | molecules/, organisms/, templates/ |
|
||||||
|
| Molecules | atoms/, lib/, hooks/ | organisms/, templates/ |
|
||||||
|
| Organisms | atoms/, molecules/, lib/, hooks/ | templates/ |
|
||||||
|
| Templates | atoms/, molecules/, organisms/, lib/, hooks/ | (top level) |
|
||||||
|
|
||||||
|
## Component Rules
|
||||||
|
|
||||||
|
- **Atoms:** No margins/positioning, no state, no business logic
|
||||||
|
- **Molecules:** Single responsibility, minimal controlled state
|
||||||
|
- **Organisms:** Can have internal state and sub-components
|
||||||
|
- **Templates:** Use children/slots, NEVER hard-code content
|
||||||
|
- **All:** Co-locate `.stories.tsx` next to component
|
||||||
|
|
||||||
|
## shadcn/ui Workflow
|
||||||
|
|
||||||
|
1. `pnpm dlx shadcn@latest add [component]` — lands in atoms/ by default
|
||||||
|
2. Check classification guide above
|
||||||
|
3. If not atom → move to correct directory
|
||||||
|
4. Create `.stories.tsx` with title: `"{Level}/{ComponentName}"`
|
||||||
|
5. Update level's `index.ts` barrel
|
||||||
|
|
||||||
|
## Story Template
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import type { Meta, StoryObj } from "@storybook/react";
|
||||||
|
import { MyComponent } from "./my-component.js";
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: "{Level}/{ComponentName}",
|
||||||
|
component: MyComponent,
|
||||||
|
tags: ["autodocs"],
|
||||||
|
} satisfies Meta<typeof MyComponent>;
|
||||||
|
export default meta;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Storybook MCP
|
||||||
|
|
||||||
|
Before creating UI components, query Storybook MCP:
|
||||||
|
- `list-all-documentation` — check for existing components
|
||||||
|
- `get-documentation` — understand props/variants
|
||||||
|
- After creating: `run-story-tests` to validate
|
||||||
Reference in New Issue
Block a user