- 移除 vercel.json 中不存在的 Secret 引用 (@database_url) - 在 CLAUDE.md 中添加 Neon 数据库配置说明 - 环境变量应直接在 Vercel Dashboard 中设置 Co-Authored-By: Claude <noreply@anthropic.com>
7.7 KiB
7.7 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Development Commands
Build & Run
pnpm dev # Start development server (Next.js 15)
pnpm build # Build for production
pnpm start # Start production server
pnpm lint # Run ESLint
Testing
pnpm test # Run Vitest unit tests
pnpm test:e2e # Run Playwright E2E tests
Database
pnpm prisma migrate dev # Run database migrations
pnpm prisma migrate dev --name init # Create initial migration
pnpm prisma db seed # Seed database (uses ts-node)
pnpm prisma studio # Open Prisma Studio for database inspection
Architecture Overview
This is a Next.js 15 multilingual AI project navigation website using the App Router architecture with the following key components:
i18n Architecture (next-intl)
- Locales:
zh(default) anden - Route pattern:
/{locale}/path(always prefixed with locale) - Middleware:
src/middleware.tshandles locale detection and routing - i18n config:
src/i18n/request.tsloads locale messages fromsrc/messages/{locale}.json - Messages: Translation files at
src/messages/zh.jsonandsrc/messages/en.json
App Router Structure
src/app/
├── [locale]/ # Locale-scoped routes
│ ├── page.tsx # Home page
│ ├── projects/ # Projects listing and details
│ │ ├── page.tsx # Projects list
│ │ └── [id]/ # Individual project details (slug-based)
│ └── layout.tsx # Locale layout (header, footer)
├── api/ # API routes (no locale prefix)
│ └── webhook/projects/route.ts # Webhook for project ingestion
└── layout.tsx # Root layout
Database (Prisma + PostgreSQL)
- Provider: Neon (serverless PostgreSQL)
- Schema:
prisma/schema.prismadefines models:Project,Tag,ExternalLink,ProjectTag - Enums:
ProjectStatus(ACTIVE/ARCHIVED),LinkType(WEBSITE/GITHUB/HUGGINGFACE/PAPER) - Client singleton:
src/lib/prisma.tsexports Prisma client instance - Multilingual fields: Most models have
name/nameEn,description/descriptionEn,content/contentEnpairs - Cascade deletions:
ExternalLinkandProjectTaguseonDelete: Cascade- deleting a project automatically cleans up its links and tag connections - Key constraints:
Project.slug: UniqueTag.name: Unique (tag names are globally unique)Tag.slug: UniqueExternalLink:@@unique([projectId, url])(each project can't have duplicate URLs)
- Indexes:
idx_project_status_createdAt,idx_project_slug,idx_tag_slug,idx_link_projectId,idx_link_type,idx_link_type_url(composite for efficient URL-based deduplication)
Neon Database Setup
- Dashboard: https://console.neon.tech
- Connection String Format:
postgres://[user]:[password]@[host]/[database]?sslmode=require - Vercel Integration: Set
DATABASE_URLenvironment variable in Vercel Dashboard (do NOT usevercel.jsonenv references) - Free Tier: 0.5GB storage, 300 hours compute/month
- Run Migrations: After deployment, run
pnpm prisma db pushor use Neon's SQL Editor to create tables
Webhook Deduplication Strategy
The webhook at src/app/api/webhook/projects/route.ts implements a multi-level deduplication strategy to prevent duplicate projects:
- GitHub URL exact match (highest priority) - via
ExternalLinktable usingidx_link_type_urlindex - Website URL exact match - via
ExternalLinktable usingidx_link_type_urlindex - slug match (fallback) - via
Project.slugfield
When updating an existing project, the webhook:
- Updates all project fields (name, description, content, status, source)
- Replaces all tags (deletes old
ProjectTagconnections viaProjectTagtable, creates new ones) - Replaces all links (deletes old
ExternalLinkentries, creates new ones)
Tag handling special case: Due to Tag.name unique constraint, tag upsert follows:
- First try to find existing tag by name
- If not found, try upsert by slug
- If slug conflicts, use the existing tag with that slug
Data Fetching (Server-Side)
- Location:
src/hooks/useProjects.ts(server functions, not React hooks) - Functions:
getProjects(),getProjectBySlug(),getAllTags(),getTagsWithProjectCounts() - Usage: Directly called in Server Components and route handlers
- Query transformation:
getProjects()andgetProjectBySlug()flatten theProjectTagjunction table structure to return tags directly - ISR: Project detail pages use
export const revalidate = 300(5 minutes) atsrc/app/[locale]/projects/[id]/page.tsx
Validation (Zod)
- Schemas:
src/lib/validations.tsdefines all Zod schemas ProjectInputSchema: Validates incoming project data (1-10 tags, 1-10 links required)WebhookPayloadSchema: Validates webhook requests with API key (1-100 projects per request)ProjectQuerySchema: Validates query parameters (search, tags, status, page, limit)
Styling (Tailwind CSS)
- Neo-brutalism design: Sharp corners (0px radius), bold borders (4px shadows), hard edges
- Theme colors:
- Primary: Gold (#FFD700)
- Secondary: Orange (#ff6f00)
- Background light: #F5F2EB, dark: #121212
- Surface light: #FFFFFF, dark: #1E1E1E
- Typography: Space Mono (headings), Inter (body)
- Dark mode: Class-based with
dark:prefix - Config:
tailwind.config.tsextends theme with custom colors, shadows, and animations
Content Rendering
- Markdown: Project content fields support Markdown via
react-markdown - Plugins:
rehype-raw,rehype-sanitize,rehype-shiki,remark-gfm - Usage:
ProjectDetailcomponent renderscontent/contentEnas Markdown
UI Components
- Radix UI primitives:
@radix-ui/react-slot,@radix-ui/react-navigation-menu,@radix-ui/react-dropdown-menu,@radix-ui/react-separator - Lucide React icons: Used throughout the app (package imports optimized via
experimental.optimizePackageImports) - Custom components:
src/components/organized by domainlayout/: Header, Footer, AnnouncementBarlocale/: LocaleSwitcherproject/: ProjectCard, ProjectList, ProjectDetail, ProjectSidebar, RelatedProjects, TagCloud, ExternalLinkCard, ShareButtons, MarkdownContent, GitHubBadges, GitHubTextStatsCardsearch/: SearchBarui/: Base UI components (buttons, cards, etc.)
Next.js Configuration
- next.config.js:
next-intlplugin wrapper for i18n- Image domains: localhost, *.anthropic.com
- Lucide-react package import optimization
- tsconfig.json: ES2022 target, strict mode enabled
- Testing: Vitest for unit tests, Playwright for E2E tests (configured but not extensively used yet)
MCP Servers Usage (按需使用)
- context7: 不确定 API 用法时查阅最新文档
- chrome-devtools-mcp: 查看页面效果、调试 UI 修复 BUG
- web-search-prime: 默认联网搜索工具
- vision-mcp-server: 图片/视频理解
Git Commits
提交信息主要使用中文,使用描述性的提交格式。
Development Workflow
- Before viewing the page, check if there's already a project running at localhost:3000. If yes, access it directly; if no, then run
pnpm dev - The dev server runs with hot-reload enabled for fast iteration
- The middleware handles locale detection and routing automatically - no manual locale configuration needed
- When adding new translations, update both
src/messages/zh.jsonandsrc/messages/en.json - Database changes require running
pnpm prisma migrate devto update the schema