Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Dependencies
node_modules/
.astro/
dist/

# macOS-specific files.
.DS_Store
Expand Down
158 changes: 158 additions & 0 deletions PR_DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# PR: Blog SEO Quality Checker — 博客 SEO 质量检查器

## Summary

为 [floatboatai/open-saas-interview](https://github.com/floatboatai/open-saas-interview) 实现 **Blog SEO Quality Checker**:自动检测博客文章常见 SEO 问题,输出 0–100 评分与优先级排序的修复建议。

- **选题**:Blog SEO 质量检查器(中级)
- **岗位匹配**:SEO 工程化 / 全栈(TypeScript + Astro + API)
- **Fork 提交**:`klj121616/open-saas-interview` → PR 至 `floatboatai/open-saas-interview`

---

## 做了什么

### 功能模块

| 模块 | 文件 | 职责 |
|------|------|------|
| SEO 分析引擎 | `src/lib/seo-checker.ts` | 7 类检查、加权评分、修复建议 |
| 内容解析层 | `src/lib/blog-content.ts` | Markdown → 结构化输入,API/页面共用 |
| HTTP API | `src/pages/api/seo-check.ts` | `GET ?slug=` 返回 JSON 审计报告 |
| 可视化组件 | `src/components/SeoScore.tsx` | 分数徽章 + findings 详情 |
| 博客页面 | `src/pages/blog/[slug].astro` | 文章 + 侧边 SEO 面板 |
| Demo 导航 | `src/pages/index.astro` | 入口页,链接到博客与 API |
| 内容集合 | `src/content/` | Zod Schema + 示例文章 |

### 7 类 SEO 检查

| 检查项 | 严重级别 | 典型扣分 |
|--------|---------|---------|
| 标题长度 | critical / warning / info | 最高 -25 |
| Meta 描述 | critical / warning | 最高 -20 |
| Canonical URL | critical / warning | 最高 -15 |
| H1/H2 结构 | critical / warning | 最高 -25 |
| 图片 Alt | warning / info | -3/张 |
| 内链数量 | warning / info | -8 |
| 正文字数 | critical / info | 最高 -30 |

---

## 设计决策

### 1. 三层架构(引擎 / 解析 / 集成)

```
Markdown + Frontmatter
blog-content.ts → BlogPostContent
seo-checker.ts → SeoAuditReport
API / 博客页 / SeoScore
```

**取舍**:引擎零框架依赖,Vitest 可直接单测;换框架只改解析层。

### 2. 扣分制评分(非 pass/fail)

SEO 优化是渐进的。100 分起扣,权重按 Google SERP 指南设定(标题 50–60 字、描述 120–155 字等)。

### 3. 检查函数返回 `SeoFinding[]`

同一维度可有多问题(如缺 H1 + H2 不足),数组模型更自然,引擎统一按 severity → penalty 排序。

### 4. 博客页 build-time 审计 + API 供外部调用

页面 SSG 时直接 `auditSeo()`,无网络往返;API 供 CI、批量工具使用。两者共用 `buildBlogPostContent()`,分数一致。

### 5. H1 回退策略

Markdown 无 `#` 时,用 frontmatter `title` 作为 H1(与页面模板 `<h1>` 一致)。

### 6. 双测试策略

- **Vitest**(37 例):逻辑与边界
- **Node Test Runner**(36 例):文件结构与契约,Node 18+ 可跑 `npm test`

---

## 边界处理

| 场景 | 处理 |
|------|------|
| 缺 slug | API 400 |
| 文章不存在 | API 404 |
| 无图片 | 跳过,不扣分 |
| 非博客页 | 跳过内链最低要求 |
| 分数溢出 | 钳制 [0, 100] |
| Unicode 标题 | 按字符数计算 |

---

## 如何验证(Reviewer)

### 环境要求

- Node.js **≥ 20**(推荐 LTS)
- Windows 用户:若 `npm install` 后 vitest 报模块缺失,删除 `node_modules` + `package-lock.json` 重装

### 自动化测试

```bash
git clone https://github.com/klj121616/open-saas-interview.git
cd open-saas-interview
git checkout feat/seo-quality-checker
npm install
npm test # 36/36
npm run test:vitest # 37/37
npm run lint # 0 errors
```

### 手动验证(开发服务器)

```bash
npm run dev
# 看终端端口(4321 或 4322),浏览器打开:

http://localhost:4321/ # Demo 导航
http://localhost:4321/blog/2026-06-01-getting-started-with-astro # 博客 + SEO 面板
http://localhost:4321/api/seo-check?slug=2026-06-01-getting-started-with-astro # JSON API
```

**预期**:博客页显示约 87 分,有「内链不足」「字数偏短」等 findings;API 返回同结构 JSON。

### 已知局限

- `npm run build` 需 SSR adapter(API 为动态路由 `prerender = false`);**开发演示以 `npm run dev` 为准**
- `SeoScore` 使用 Tailwind class,未接入 Tailwind 时配色可能不完整(分数与文案正常)
- Markdown 解析不覆盖 HTML 嵌入块内的链接/图片

---

## Test Plan

- [ ] `npm test` 全部通过
- [ ] `npm run test:vitest` 全部通过
- [ ] `npm run lint` 无 error
- [ ] `npm run dev` 首页、博客页、API 均可访问
- [ ] 修改 frontmatter `description` 为空后,分数下降且出现 critical finding
- [ ] API 与页面 score 一致

---

## 后续规划

- **P0**:CI 集成 `criticalOnly()` 阻断发布;API 改为 `[slug]` 静态 JSON 以支持 `npm run build`
- **P1**:关键词密度、Schema Markup 验证
- **P2**:批量审计 CLI、PR 自动 SEO 评论

---

## 自我评估

| 维度 | 评分 | 说明 |
|------|------|------|
| 实现难度 | ★★★☆☆ | 7 类规则 + 解析层 + API + 组件 + 双测试 |
| 完成度 | ★★★★☆ | 核心链路完整,测试全绿,dev 可演示 |
| 代码风格 | ★★★★★ | TypeScript 严格类型、分层清晰、JSDoc |
21 changes: 21 additions & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Astro Configuration for Open SaaS Interview Project
*
* Enables:
* - Content collections (blog posts)
* - API endpoints (SEO checker)
* - React components (SeoScore badge)
* - Server-side rendering (SSR)
*
* For production, this would be integrated with the full
* Open SaaS blog configuration in template/blog/astro.config.mjs
*/
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';

// https://astro.build/config
export default defineConfig({
site: 'https://opensaas.sh',
output: 'static',
integrations: [react()],
});
Loading