blog test

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

构建命令

  • pnpm dev – 启动开发服务器(turbo 模式)
  • pnpm build – 生产环境构建
  • pnpm start – 启动生产服务器
  • pnpm lint – 运行 ESLint
  • pnpm test – 运行所有测试 (Vitest)
  • pnpm test:watch – 监听模式运行测试
  • pnpm vitest run __tests__/lib/utils.test.ts – 运行单个测试文件
  • pnpm vitest run -t "test name" – 运行指定名称的测试

架构概览

基于 Next.js 16 App Router 和 TypeScript 的 Headless WordPress 启动模板。

数据层 (lib/wordpress.ts)

  • 所有 WordPress REST API 交互集中在此
  • 类型定义在 lib/wordpress.d.ts (Post, Page, Category, Tag, Author, FeaturedMedia)
  • 两种获取模式: wordpressFetch (出错时抛出异常) vs wordpressFetchGraceful (返回降级值)
  • WordPressAPIError 类用于统一的错误处理
  • 缓存标签用于细粒度的重新验证: ['wordpress', 'posts', 'post-{id}', 'posts-page-{n}']
  • 通过 getPostsPaginated() 实现分页,返回 { data, headers: { total, totalPages } }
  • 默认缓存: 1 小时 (revalidate: 3600)
  • 优雅降级: 即使 WordPress 不可用,构建也能成功

路由

  • 动态路由: /posts/[slug]/pages/[slug]
  • 归档页面: /posts/posts/authors/posts/categories/posts/tags
  • API 路由: /api/revalidate (webhook), /api/og (OG 图片)

数据获取模式

  • 服务器组件使用并行的 Promise.all() 调用
  • generateStaticParams() 使用 getAllPostSlugs() 进行静态生成
  • 基于 URL 的搜索/过滤状态通过 searchParams 实现
  • SearchInput 组件中使用防抖搜索(300ms)
  • Next.js 15+ 异步参数模式: params: Promise<{ slug: string }>

重新验证流程

  1. WordPress 插件发送 webhook 到 /api/revalidate
  2. 验证 x-webhook-secret 请求头与 WORDPRESS_WEBHOOK_SECRET 匹配
  3. 针对特定内容类型调用 revalidateTag() (posts, categories, tags, authors)
  4. 同时调用 revalidatePath("/", "layout") 刷新整个站点

配置文件

  • site.config.ts – 站点元数据(域名、名称、描述)
  • menu.config.ts – 导航菜单结构 (mainMenucontentMenu)
  • next.config.ts – 图片 remotePatterns、/admin 重定向到 WordPress、standalone 输出

布局组件 (components/craft.tsx)

craft-ds (v0.3.2) 的本地副本,提供布局原语:

  • Section – 带垂直内边距的页面区块
  • Container – 带水平内边距的最大宽度容器
  • Article – WordPress 内容的 prose 容器 (max-width prose)
  • Prose – 富文本排版样式
  • Box – 支持响应式属性的 flex/grid 布局

工具函数

  • lib/utils.ts – cn() 函数用于合并 Tailwind 类名 (clsx + tailwind-merge)
  • lib/metadata.ts – generateContentMetadata() 用于 SEO 元数据, stripHtml() 用于摘录清理

测试 (__tests__/) {#测试-tests data-source-line=”64″}

  • 使用 Vitest,@ 路径别名与 tsconfig.json 匹配
  • 测试文件镜像源代码结构: __tests__/lib/utils.test.ts 测试 lib/utils.ts
  • 测试覆盖: lib/utilslib/metadatalib/wordpressapi/revalidate
  • WordPress API 测试通过 mock global.fetch 避免外部调用

代码风格

TypeScript

  • 使用 lib/wordpress.d.ts 中的接口进行严格类型检查
  • 异步参数: params: Promise<{ slug: string }> (Next.js 15+ 模式)

命名规范

  • 组件: PascalCase (PostCard.tsx)
  • 函数/变量: camelCase
  • 类型/接口: PascalCase

文件结构

  • 页面: /app/**/*.tsx
  • UI 组件: /components/ui/*.tsx (shadcn/ui)
  • 功能组件: /components/posts/*.tsx/components/theme/*.tsx
  • WordPress 函数必须包含缓存标签

环境变量

WORDPRESS_URL="https://example.com"      # 完整的 WordPress URL
WORDPRESS_HOSTNAME="example.com"          # 用于 Next.js 图片优化
WORDPRESS_WEBHOOK_SECRET="secret-key"     # Webhook 验证

核心依赖

  • Next.js 16 with React 19
  • Tailwind CSS v4 with @tailwindcss/postcss
  • shadcn/ui 组件 (Radix primitives)
  • craft-ds 布局组件 (SectionContainerArticleProse)