From 53e1faab891d60998bad03da74f7bbc3db74437a Mon Sep 17 00:00:00 2001 From: mzaxd Date: Sun, 1 Feb 2026 14:57:43 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E7=94=9F=E6=88=90=E5=B1=82=E6=AC=A1?= =?UTF-8?q?=E5=8C=96=20AGENTS.md=20=E6=96=87=E6=A1=A3=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 258 +++++++++++++++++++++++++++++++++++++++ src/app/AGENTS.md | 46 +++++++ src/components/AGENTS.md | 60 +++++++++ src/hooks/AGENTS.md | 49 ++++++++ src/lib/AGENTS.md | 66 ++++++++++ 5 files changed, 479 insertions(+) create mode 100644 AGENTS.md create mode 100644 src/app/AGENTS.md create mode 100644 src/components/AGENTS.md create mode 100644 src/hooks/AGENTS.md create mode 100644 src/lib/AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..9250bee --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,258 @@ +# PROJECT KNOWLEDGE BASE + +**Generated:** 2026-02-01 +**Commit:** N/A (new generation) +**Branch:** main + +## OVERVIEW + +Next.js 15 multilingual AI project navigation website with App Router, TypeScript, Prisma ORM, and Tailwind CSS neo-brutalism design. Features automated project discovery and quarterly AI keyword cloud system. + +## STRUCTURE + +``` +agent_park/ +├── src/ +│ ├── app/ # Next.js App Router (locale-prefixed routes) +│ │ ├── [locale]/ # Internationalized routes (zh/en) +│ │ │ ├── projects/ # Project listing and details +│ │ │ ├── keyword-cloud/ # Quarterly AI trends +│ │ │ └── layout.tsx # Header/footer/Announcement +│ │ ├── api/ # API routes (no locale prefix) +│ │ │ ├── webhook/ # Project ingestion +│ │ │ ├── discovery/ # Automated exploration tasks +│ │ │ ├── search/ # AI-powered search +│ │ │ └── keyword-cloud/ # Keywords API +│ │ ├── components/ # React components (organized by domain) +│ │ ├── lib/ # Validation, utilities, Prisma client +│ │ ├── hooks/ # Server-side data fetching +│ │ └── i18n/ # next-intl configuration +│ └── layout.tsx # Root layout (locale default: zh) +├── prisma/ +│ └── schema.prisma # Database models (multilingual support) +├── .claude/ +│ ├── agents/ # Custom Claude agents +│ └── commands/ # Claude commands +├── scripts/ # Seed/test scripts +├── public/ # Static assets +└── CLAUDE.md # This file (existing) +``` + +## WHERE TO LOOK + +| Task | Location | Notes | +| ------------------- | ------------------------ | ------------------------------------------- | +| Add new page | `src/app/[locale]/` | Follow locale routing pattern | +| Create API endpoint | `src/app/api/` | Use `crypto.timingSafeEqual()` for auth | +| Add component | `src/components/` | Neo-brutalism: 0px radius, bold borders | +| Database migration | `prisma/schema.prisma` | Run `pnpm prisma migrate dev` after changes | +| Add validation | `src/lib/validations.ts` | Follow existing Zod schema patterns | +| Fetch data | `src/hooks/` | Server functions, NOT React hooks | +| Webhook | `src/app/api/webhook/` | Multi-level deduplication strategy | +| Discovery task | `src/app/api/discovery/` | Task management API | +| i18n messages | `src/messages/` | Update BOTH `zh.json` AND `en.json` | + +## CODE MAP + +``` +Main Entry Points: +├── src/app/[locale]/layout.tsx → Root layout (header/footer) +├── src/app/[locale]/page.tsx → Home page (ISR 5min) +├── src/app/layout.tsx → Root layout (fonts, locale) +└── src/middleware.ts → Locale detection (next-intl) + +Data Layer: +├── src/hooks/useProjects.ts → Projects/tags/search +├── src/hooks/useKeywordCloud.ts → Keywords/quarters/rules +└── src/lib/prisma.ts → Prisma client singleton + +API Routes: +├── src/app/api/webhook/projects/route.ts → Project ingestion +├── src/app/api/discovery/tasks/route.ts → Task CRUD +├── src/app/api/search/ai/route.ts → AI search +└── src/app/api/keyword-cloud/[...]/route.ts → Keywords API + +Complex Components: +├── src/components/project/MarkdownContent.tsx (269 lines) → Markdown renderer +├── src/app/api/discovery/lib/discovery-service.ts → Deduplication logic +└── src/app/api/webhook/projects/route.ts → Webhook handler +``` + +## CONVENTIONS + +### Multilingual Architecture + +- **Default locale**: Chinese (`zh`), not English +- **Route pattern**: `/{locale}/path` (locale prefix ALWAYS required) +- **Field naming**: Dual-language pairs (`name`/`nameEn`, `description`/`descriptionEn`) +- **Content selection**: `locale === 'en' && fieldEn ? fieldEn : field` +- **Translation files**: Update BOTH `src/messages/zh.json` AND `src/messages/en.json` + +### Type Safety + +- **Strict mode**: Enabled with `noUncheckedIndexedAccess`, `noImplicitReturns`, `noFallthroughCasesInSwitch` +- **Path aliases**: `@/*` maps to `./src/*` +- **Validation**: All API inputs via Zod schemas in `src/lib/validations.ts` + +### Database Patterns + +- **Multi-level deduplication**: GitHub URL → Website URL → slug match (highest → lowest priority) +- **Cascade deletion**: `ExternalLink` and `ProjectTag` auto-delete on project delete +- **Composite indexes**: Optimized for frequent queries (`status+createdAt`, `type+url`) +- **Constraints**: `Project.slug` unique, `Tag.name` unique, `ExternalLink(projectId, url)` unique + +### API Authentication + +- **Method**: `crypto.timingSafeEqual()` for timing-safe comparison (prevents timing attacks) +- **Key location**: Request body (NOT headers) +- **Validation**: WEBHOOK_API_KEY (32+ chars) + +### Design System (Neo-Brutalism) + +- **Corners**: 0px radius (sharp) +- **Shadows**: 4px solid borders (`shadow-neo` class) +- **Colors**: Primary gold (#FFD700), secondary orange (#ff6f00) +- **Typography**: Space Mono (headings), Inter (body) +- **Dark mode**: Class-based with `dark:` prefix + +### Git Commits + +- **Format**: `: ` (Chinese lowercase types) +- **Types**: `feat` (新功能), `fix` (修复), `refactor` (重构), `chore` (杂项) +- **Examples**: + - `feat: 新增项目发现任务系统` + - `fix: 修复 ESLint 错误` + +## ANTI-PATTERNS (THIS PROJECT) + +### Environment Variables + +- **NEVER** use `vercel.json` for env vars (use Vercel Dashboard) +- **NEVER** commit `.env.local` files or environment variables +- **ALWAYS** verify API responses with `WEBHOOK_API_KEY` when testing endpoints + +### Database Operations + +- **NEVER** modify schema without running migrations +- **ALWAYS** run `pnpm prisma migrate dev --name ` after schema changes +- **ALWAYS** run `pnpm prisma generate` after migrations + +### Development Workflow + +- **NEVER** skip pre-commit hooks (no `--no-verify`, `--no-gpg-sign` flags) +- **NEVER** commit unless explicitly requested by orchestrator +- **ALWAYS** run `pnpm build` before committing +- **MUST** use chrome-devtools-mcp to verify frontend changes + +### Content Standards + +- **NEVER** include dynamic data (star/fork counts) in project content +- **ALWAYS** use GitHub Badge for dynamic stats +- **NEVER** use mechanical translation - write naturally for each locale +- **ALWAYS** avoid marketing terminology in descriptions + +### Security + +- **NEVER** use string comparison for API keys (timing attacks) +- **ALWAYS** use `crypto.timingSafeEqual()` for authentication +- **ALWAYS** validate inputs with Zod schemas +- **NEVER** log raw API keys or sensitive data + +## UNIQUE STYLES + +### Project Discovery System + +- **Architecture**: Dual-agent system (`content-explorer-agent` + `api-submitter-agent`) +- **Workflow**: URL input → PENDING tasks → batch processing → COMPLETED/FAILED +- **Deduplication**: Multi-level strategy (GitHub → Website → slug) +- **Retry logic**: Exponential backoff, max 3 attempts +- **Environment**: `WEBHOOK_API_KEY` required for submitter agent +- See: `src/app/AGENTS.md` for app-specific patterns + +### Keyword Cloud System + +- **Workflow**: n8n automation → API → PostgreSQL → Next.js +- **Data**: Quarterly snapshots with visual style rules +- **API**: Rate-limited, requires API key +- **Error logging**: `KeywordCloudErrorLog` table +- See: `src/app/AGENTS.md` for app-specific patterns + +### Component System + +- **Design**: Neo-brutalism with 0px corners, 4px solid borders, gold/orange theme +- **Organization**: layout/locale/project/search/ui (4 domains), project/ (11 files, highest) +- **Largest component**: `MarkdownContent.tsx` (269 lines) with complex react-markdown overrides +- **See**: `src/components/AGENTS.md` for component-specific patterns + +### Data Access Layer + +- **Validation**: Centralized Zod schemas in `src/lib/validations.ts` +- **Utilities**: Class merging (`cn()`), slug generation, Prisma client singleton +- **GitHub integration**: Badge-based approach, cached API stats (5min) +- **See**: `src/lib/AGENTS.md` for library patterns + +### Server-Side Hooks + +- **Purpose**: Server functions for data fetching, NOT React hooks +- **Query optimization**: N+1 prevention, selective loading, index utilization +- **ISR strategy**: 5-minute revalidation on project details +- **See**: `src/hooks/AGENTS.md` for data fetching patterns + +## COMMANDS + +```bash +pnpm dev # Start dev server (Next.js 15) +pnpm build # Production build +pnpm start # Start production server +pnpm lint # ESLint check +pnpm test # Vitest unit tests +pnpm test:e2e # Playwright E2E tests +pnpm prisma migrate dev # Run migrations +pnpm prisma db seed # Seed database +pnpm prisma studio # Database inspector +``` + +## NOTES + +### Project Discovery Gotchas + +- Tag upsert follows: 1) Find by name, 2) Try upsert by slug, 3) Use existing if slug conflicts +- Webhook updates ALL project fields, replaces ALL tags/links (no partial updates) +- Deduplication logic in `src/app/api/discovery/lib/discovery-service.ts:16-80` + +### i18n Gotchas + +- Missing translation keys display as `missing_key_name` in UI +- All new UI text requires BOTH `zh.json` AND `en.json` updates +- Test both locales: `/{zh}/path` and `/{en}/path` + +### Database Gotchas + +- `Project.slug` globally unique - use existing project if slug conflicts +- `Tag.name` globally unique - upsert handles conflicts via slug fallback +- Run `pnpm prisma studio` to inspect state during development + +### Performance Considerations + +- **ISR**: Project detail pages revalidate every 5 minutes (`revalidate = 300`) +- **Indexes**: Composite on `(status, createdAt)`, `(type, url)` for optimized queries +- **N+1 prevention**: Batch tag queries in webhook (`useProjects.ts`) + +### Missing CI/CD + +- No GitHub Actions workflows (rely on Vercel deployment) +- No automated testing in CI pipeline +- Test frameworks configured (Vitest, Playwright) but not extensively used + +### LSP Errors + +- Missing Prisma models in `src/hooks/useKeywordCloud.ts` and `scripts/seed-keyword-cloud.ts`: + - Run `pnpm prisma migrate dev` to generate keyword cloud tables + - Models: `Quarter`, `Keyword`, `VisualStyleRule`, `keywordCloudErrorLog` + +### Subdirectories + +- **src/app/**: App Router architecture, locale routing, API structure (see `src/app/AGENTS.md`) +- **src/components/**: Neo-brutalism design system, component organization (see `src/components/AGENTS.md`) +- **src/lib/**: Validation layer, utilities, GitHub integration (see `src/lib/AGENTS.md`) +- **src/hooks/**: Server-side data fetching, query optimization (see `src/hooks/AGENTS.md`) diff --git a/src/app/AGENTS.md b/src/app/AGENTS.md new file mode 100644 index 0000000..5c24028 --- /dev/null +++ b/src/app/AGENTS.md @@ -0,0 +1,46 @@ +# src/app/ - App Router Implementation + +## OVERVIEW + +Next.js 15 App Router with next-intl locale routing and multilingual project discovery platform + +## STRUCTURE + +- `[locale]/` - Locale-scoped routes (zh/en), home, projects, keyword-cloud +- `api/` - API endpoints (webhook, discovery, keyword-cloud, search) +- `globals.css` - Tailwind + neo-brutalism styles +- `layout.tsx` - Root layout + +## WHERE TO LOOK + +- **Locale routing**: `src/middleware.ts`, `src/app/[locale]/layout.tsx` +- **API patterns**: `src/app/api/webhook/projects/route.ts` +- **ISR configuration**: `src/app/[locale]/projects/[id]/page.tsx:93` +- **Discovery system**: `src/app/api/discovery/tasks/route.ts` + +## CONVENTIONS + +- **Middleware**: `createMiddleware({ locales: ['zh', 'en'], defaultLocale='zh', localePrefix='always' })` +- **Route params**: Always `params: Promise<{...}>`, await before use +- **Locale setup**: `setRequestLocale(locale)` in layouts/pages +- **Translations**: `getTranslations('namespace')` for server-side +- **API auth**: `crypto.timingSafeEqual()` for timing-safe API key validation +- **Webhook**: Partial success mode - continue processing if individual items fail +- **Deduplication**: Multi-level (GitHub URL → Website URL → slug) via `discovery-service` +- **ISR**: Export `revalidate = N` constant in page files +- **Parallel queries**: `Promise.all()` for independent data fetching +- **N+1 prevention**: Batch queries with `findMany({ where: { field: { in: [...] } } })` +- **Content selection**: `locale === 'en' && fieldEn ? fieldEn : field` pattern + +## ANTI-PATTERNS + +- NEVER bypass locale routing (API routes excluded) +- NEVER use `crypto.compare()` or string comparison for API keys (timing attacks) +- NEVER skip Zod validation in API routes +- NEVER embed API keys in error responses (log only) +- NEVER process webhook without partial success mode +- NEVER run queries in loops (N+1 problem) +- NEVER use client-side translations in server components +- NEVER skip `setRequestLocale()` in locale routes +- NEVER omit ISR for dynamic content (5+ minute revalidation) +- NEVER return raw database errors to clients diff --git a/src/components/AGENTS.md b/src/components/AGENTS.md new file mode 100644 index 0000000..7d426b4 --- /dev/null +++ b/src/components/AGENTS.md @@ -0,0 +1,60 @@ +# Component System Architecture + +## Neo-Brutalism Design Principles + +**Visual Identity:** + +- Sharp corners (0px radius) - no rounded edges +- Bold borders (4px solid shadows) for depth +- High contrast colors with hard edges +- Gold (#FFD700) primary, Orange (#ff6f00) secondary +- Space Mono headings, Inter body text + +**Component Styling:** + +```tsx +// Base button pattern - no border-radius, hard shadows +className="border-4 border-black shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] + hover:translate-x-1 hover:translate-y-1 hover:shadow-[2px_2px_0px_0px_rgba(0,0,0,1)]" +``` + +## Component Organization + +``` +src/components/ +├── layout/ # Layout primitives (Header, Footer, AnnouncementBar) +├── locale/ # I18n utilities (LocaleSwitcher) +├── project/ # Project-specific components (ProjectCard, ProjectDetail) +├── search/ # Search functionality (SearchBar) +└── ui/ # Base UI components (Button, Card, Badge) +``` + +## Component Patterns + +### Composition Pattern + +- Build complex components from small reusable primitives +- Example: `ProjectCard` = `Card` + `Badge` + `ExternalLink` + +### Server Components First + +- Default to Server Components for data fetching +- Use Client Components (`"use client"`) only for interactivity +- Pass server data via props to client components + +### Responsive Design + +- Mobile-first Tailwind classes: `grid-cols-1 md:grid-cols-2 lg:grid-cols-3` +- Breakpoints: md (768px), lg (1024px) + +### Accessibility + +- Semantic HTML elements +- Keyboard navigation support +- ARIA labels where needed + +## State Management + +- Server state: Prisma queries in Server Components +- Client state: React hooks (useState, useEffect) for interactivity +- Global state: Context providers for locale, theme diff --git a/src/hooks/AGENTS.md b/src/hooks/AGENTS.md new file mode 100644 index 0000000..0b0c227 --- /dev/null +++ b/src/hooks/AGENTS.md @@ -0,0 +1,49 @@ +# src/hooks/ - Server-Side Data Fetching + +**Purpose**: Server-side data fetching functions (NOT React hooks). Exported functions for use in Server Components and API routes. + +## Architecture + +- **Server Functions Only**: No React hooks, no client-side state +- **Direct Prisma Queries**: ORM queries with optimization patterns +- **ISR Support**: Used by Next.js App Router for incremental static revalidation + +## Key Functions + +### Project Data (`useProjects.ts`) + +- `getProjects()`: List projects with tags, pagination, filtering (search/tags/status) + - Flattens `ProjectTag` junction table to return tags directly + - Optimized for list queries with selective field loading +- `getProjectBySlug(slug)`: Get single project by slug + - Used by ISR pages with 5-min revalidation + - Includes all tags and external links +- `getAllTags()`: All tags with project counts +- `getTagsWithProjectCounts()`: Tags sorted by popularity (count DESC) + +### Keyword Cloud (`useKeywordCloud.ts`) + +- `getAllQuarters()`: List all quarters with metadata +- `getQuarterByQuarter(quarter)`: Single quarter with keyword count +- `getKeywordsByQuarter(quarter)`: All keywords for a quarter +- `getVisualStyleRules()`: Visual style configuration for word cloud + +## Query Optimization Patterns + +**N+1 Prevention**: Batch queries for related data (tags, links) +**Selective Loading**: Only fetch required fields via Prisma `select` +**Index Utilization**: Leverages database indexes (status+createdAt, slug, etc.) +**Pagination**: Limit/offset to prevent large result sets + +## ISR Strategy + +- **Revalidation**: 5-minute revalidate on project detail pages +- **Stale Data Acceptable**: Project listings tolerate slight staleness +- **Cache Busting**: Use `revalidatePath()` when data changes via webhook + +## Best Practices + +- Always import via `@/hooks/use*` (not relative paths) +- Return plain objects/arrays, never Prisma model instances +- Handle errors at route level, not in these functions +- Add new functions to existing files or create new `use*.ts` files diff --git a/src/lib/AGENTS.md b/src/lib/AGENTS.md new file mode 100644 index 0000000..01e8e04 --- /dev/null +++ b/src/lib/AGENTS.md @@ -0,0 +1,66 @@ +# src/lib/ - Core Utilities + +## Overview + +Shared utilities and infrastructure layers used across the application. + +## Key Files + +### Validation Layer (`validations.ts`) + +**Purpose**: Input validation and type safety using Zod schemas + +- `ProjectInputSchema`: Project data validation (1-10 tags, 1-10 links) +- `WebhookPayloadSchema`: Webhook request validation with API key auth +- `KeywordInputSchema`: Keyword cloud data with visual config +- `ProjectQuerySchema`: Query parameter validation (search, tags, status, pagination) +- `ExternalLinkSchema`: URL validation with http/https protocol check +- `TaskStatusEnum`: Discovery task states (PENDING/IN_PROGRESS/COMPLETED/FAILED) + +### Prisma Client (`prisma.ts`) + +**Purpose**: Singleton database client pattern + +```typescript +import { prisma } from "@/lib/prisma"; +``` + +### Utilities + +- `utils.ts`: `cn()` - Tailwind class merging with clsx/twMerge +- `slug.ts`: `generateSlug()` - URL-friendly slug generation (prefers English, max 100 chars) + +### GitHub Integration + +- `github/api.ts`: `getGitHubStats()` - Fetch repo stats (stars, forks, license) with 5min cache +- `github/badges.ts`: `parseGitHubUrl()`, `getGitHubStarsBadgeUrl()`, `getAllGitHubBadgeUrls()` + +## Usage Patterns + +**Validation**: + +```typescript +import { ProjectInputSchema } from "@/lib/validations"; +const validated = ProjectInputSchema.parse(inputData); +``` + +**Database**: + +```typescript +import { prisma } from "@/lib/prisma"; +const projects = await prisma.project.findMany(); +``` + +**GitHub Badges**: + +```typescript +import { getGitHubBadgesFromLinks } from "@/lib/github/badges"; +const { stars } = getGitHubBadgesFromLinks(project.externalLinks); +``` + +## Key Design Decisions + +- Singleton Prisma client prevents connection pool exhaustion in dev +- All enums use Zod for runtime type checking +- API key minimum length: 32 characters +- URL validation enforces http/https protocol only