# AGENTS.md — blog Articles collection + content use cases (get article, list articles, create, publish, unpublish). Provides the Articles Payload collection and tRPC procedures for content management and retrieval. ## What it owns - **Entities** — Article type, article-related errors (ArticleNotFound, InvalidSlug) - **Use cases** — Get article, list articles, create, publish, unpublish, delete - **Repository interface** — `IArticlesRepository` for article persistence - **Mock repository** — In-memory article store for tests - **Payload repository** — Real Payload-backed article repository (constructor-injected at boot) - **Payload collection** — Articles collection definition + hooks (publish timestamp, slugify) - **tRPC router** — Procedures for list, get-by-slug, create, publish - **DI container** — Per-feature InversifyJS container with blog symbols - **UI components** — Article-specific components (ArticleCard, ArticleList, etc.) ## Public exports From `package.json`: - `.` — Article type + blog errors + UI components - `./api` — tRPC router (`blogRouter`) - `./cms` — Payload Articles collection - `./di/bind-production` — `bindProductionArticles()` to wire Payload repo at boot ## What it must NOT import - Any other feature package (`@repo/auth`, `@repo/media`, etc.) - Any app package - `@repo/core-api`, `@repo/core-cms`, `@repo/core-trpc`, `@repo/core-ui` directly; only import from `@repo/core-shared` and use DI for Payload config ## Layer rules ### `src/` files use relative imports Avoid `@/` in source code: ```typescript // ✓ Correct import type { IArticlesRepository } from "../repositories/articles.repository.interface.js"; // ✗ Wrong (don't do this in src/) import { Article } from "@/entities/article.js"; ``` ### Tests use @/ alias Test files use `@/`: ```typescript // ✓ Correct import { getArticleUseCase } from "@/application/use-cases/get-article.use-case.js"; ``` ### DI container is per-feature Tests rebind their own container: ```typescript import { container as blogContainer, BLOG_SYMBOLS } from "@/di/container.js"; import { MockArticlesRepository } from "@/infrastructure/repositories/mock-articles.repository.js"; beforeEach(() => { blogContainer.unbindAll(); blogContainer.bind(BLOG_SYMBOLS.IArticlesRepository).to(MockArticlesRepository); }); ``` ## Test conventions - **Unit tests** colocated with source: `*.test.ts` suffix - **Feature tests** in `tests/` folder: `*.feature.test.ts` suffix (cross-layer tests like publish flow) - **Vitest environment** — `node` - **Alias** — `@/` resolves to `src/` - **Run** — `pnpm test --filter @repo/blog` Covered areas: article CRUD use cases, slug validation, publish/unpublish flows, DI container binding. ## Tests - **Factories:** `src/__factories__/article.factory.ts` — use `articleFactory.build({ overrides })` to construct test data with stable defaults. - **Contract suite:** `src/__contracts__/articles-repository.contract.ts` — runs against every repository implementation (mock + payload). - **Unit tests:** colocated as `*.test.ts` next to the source file. - **Feature integration:** `tests/articles.feature.test.ts` — full slice through tRPC router → controller → use case → mock repo. ```bash pnpm test --filter @repo/blog # all tests for this feature pnpm test --filter @repo/blog -- --watch # watch mode ``` See `docs/guides/tdd-workflow.md` for the cycle. ## Structure ``` src/ entities/ article.ts # Article schema + type errors.ts # ArticleNotFound, InvalidSlug, etc. application/ repositories/ articles.repository.interface.ts use-cases/ get-article.use-case.ts list-articles.use-case.ts publish-article.use-case.ts infrastructure/ repositories/ payload-articles.repository.ts # constructor-injected: Config mock-articles.repository.ts di/ symbols.ts # BLOG_SYMBOLS container.ts # blogContainer bind-production.ts # bindProductionArticles(container, config) interface-adapters/ controllers/ articles.controller.ts # input validation integrations/ cms/ collections/ articles.ts # Payload CollectionConfig hooks/ after-publish.ts # revalidate, effects index.ts api/ router.ts # tRPC procedures index.ts ui/ article-card.tsx article-list.tsx query.ts # typed tRPC query helpers index.ts # re-exports: Article, UI components tests/ publish-article.feature.test.ts ```