docs: add project architecture showcase page

This commit is contained in:
Codex
2026-06-21 23:43:02 +08:00
parent bed86ac454
commit 4f48956757
2 changed files with 785 additions and 0 deletions
+681
View File
@@ -0,0 +1,681 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>GEO 智能文章优化器 | 项目架构展示</title>
<style>
:root {
color-scheme: dark;
--bg: #08111f;
--panel: #101b2d;
--panel-soft: #14243a;
--line: rgba(148, 163, 184, 0.24);
--text: #f7fafc;
--muted: #a8b3c7;
--soft: #d9e3f0;
--blue: #45aaf2;
--green: #2dd4bf;
--yellow: #f6c65b;
--red: #f87171;
--shadow: 0 24px 80px rgba(0, 0, 0, 0.34);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background:
radial-gradient(circle at top left, rgba(69, 170, 242, 0.22), transparent 34rem),
linear-gradient(180deg, #08111f 0%, #0c1424 48%, #08111f 100%);
color: var(--text);
font-family:
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
"PingFang SC", "Microsoft YaHei", sans-serif;
line-height: 1.65;
}
a {
color: inherit;
}
.page {
width: min(1180px, calc(100% - 40px));
margin: 0 auto;
}
.hero {
min-height: 72vh;
display: grid;
align-items: center;
padding: 72px 0 52px;
}
.eyebrow {
width: fit-content;
margin: 0 0 18px;
padding: 7px 12px;
border: 1px solid rgba(45, 212, 191, 0.36);
border-radius: 999px;
color: #b5fff3;
background: rgba(45, 212, 191, 0.08);
font-size: 13px;
font-weight: 700;
}
h1,
h2,
h3,
p {
margin-top: 0;
}
h1 {
max-width: 880px;
margin-bottom: 20px;
font-size: clamp(42px, 7vw, 86px);
line-height: 1.04;
letter-spacing: 0;
}
.hero-copy {
max-width: 780px;
margin-bottom: 30px;
color: var(--soft);
font-size: clamp(18px, 2.2vw, 25px);
}
.tag-row,
.metric-row {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.tag {
padding: 8px 12px;
border: 1px solid rgba(148, 163, 184, 0.26);
border-radius: 999px;
background: rgba(255, 255, 255, 0.05);
color: #dce8f6;
font-size: 14px;
font-weight: 650;
}
.metric-row {
margin-top: 34px;
}
.metric {
min-width: 150px;
padding: 18px;
border: 1px solid var(--line);
border-radius: 8px;
background: rgba(16, 27, 45, 0.78);
box-shadow: var(--shadow);
}
.metric strong {
display: block;
color: var(--green);
font-size: 28px;
line-height: 1;
}
.metric span {
display: block;
margin-top: 8px;
color: var(--muted);
font-size: 13px;
}
section {
padding: 58px 0;
border-top: 1px solid var(--line);
}
.section-head {
display: grid;
grid-template-columns: minmax(0, 0.92fr) minmax(280px, 0.62fr);
gap: 36px;
align-items: end;
margin-bottom: 28px;
}
h2 {
margin-bottom: 10px;
font-size: clamp(28px, 4vw, 44px);
line-height: 1.15;
letter-spacing: 0;
}
.section-head p,
.section-note {
color: var(--muted);
font-size: 16px;
}
.grid {
display: grid;
gap: 16px;
}
.two-col {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.three-col {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.card {
border: 1px solid var(--line);
border-radius: 8px;
background: linear-gradient(180deg, rgba(20, 36, 58, 0.92), rgba(16, 27, 45, 0.92));
box-shadow: 0 18px 52px rgba(0, 0, 0, 0.2);
}
.card-pad {
padding: 20px;
}
.card h3 {
margin-bottom: 8px;
color: #ffffff;
font-size: 19px;
}
.card p,
.card li {
color: var(--muted);
}
.problem-list,
.plain-list {
margin: 0;
padding: 0;
list-style: none;
}
.problem-list {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
}
.problem-list li,
.plain-list li {
position: relative;
padding-left: 22px;
}
.problem-list li::before,
.plain-list li::before {
content: "";
position: absolute;
left: 0;
top: 0.78em;
width: 8px;
height: 8px;
border-radius: 999px;
background: var(--blue);
box-shadow: 0 0 18px rgba(69, 170, 242, 0.64);
}
.solution-card {
border-color: rgba(45, 212, 191, 0.3);
background: linear-gradient(180deg, rgba(45, 212, 191, 0.12), rgba(16, 27, 45, 0.9));
}
.solution-card .plain-list li::before {
background: var(--green);
box-shadow: 0 0 18px rgba(45, 212, 191, 0.66);
}
.flow-wrap {
padding: 22px;
}
.flow {
display: flex;
flex-wrap: wrap;
gap: 14px;
align-items: center;
}
.node {
min-height: 72px;
flex: 1 1 145px;
display: grid;
align-content: center;
gap: 4px;
padding: 14px;
border: 1px solid rgba(148, 163, 184, 0.28);
border-radius: 8px;
background: rgba(255, 255, 255, 0.05);
}
.node strong {
color: #ffffff;
font-size: 15px;
}
.node span {
color: var(--muted);
font-size: 12px;
}
.arrow {
color: var(--green);
font-size: 22px;
font-weight: 800;
}
.loop-note {
margin: 18px 0 0;
padding: 14px 16px;
border-left: 3px solid var(--yellow);
border-radius: 0 8px 8px 0;
background: rgba(246, 198, 91, 0.1);
color: #ffe5a6;
}
.layer-card {
display: grid;
grid-template-columns: 132px minmax(0, 1fr);
gap: 16px;
align-items: start;
}
code {
display: inline-block;
padding: 3px 7px;
border: 1px solid rgba(148, 163, 184, 0.22);
border-radius: 6px;
background: rgba(3, 7, 18, 0.38);
color: #caf4ff;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
font-size: 0.92em;
}
.badge {
width: fit-content;
padding: 6px 9px;
border-radius: 7px;
background: rgba(69, 170, 242, 0.13);
color: #bfe7ff;
font-weight: 750;
}
.highlight {
min-height: 176px;
}
.highlight h3 {
display: flex;
gap: 10px;
align-items: center;
}
.index {
display: inline-grid;
width: 28px;
height: 28px;
place-items: center;
border-radius: 999px;
background: rgba(45, 212, 191, 0.16);
color: var(--green);
font-size: 13px;
}
.qa-strip {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
margin-top: 18px;
}
.qa {
padding: 14px;
border-radius: 8px;
background: rgba(255, 255, 255, 0.05);
}
.qa strong {
display: block;
margin-bottom: 4px;
}
.pass strong {
color: var(--green);
}
.warn strong {
color: var(--yellow);
}
.fail strong {
color: var(--red);
}
.roadmap {
counter-reset: roadmap;
}
.roadmap li {
position: relative;
margin-bottom: 12px;
padding: 16px 16px 16px 54px;
border: 1px solid var(--line);
border-radius: 8px;
background: rgba(255, 255, 255, 0.04);
color: var(--soft);
list-style: none;
}
.roadmap li::before {
counter-increment: roadmap;
content: counter(roadmap);
position: absolute;
left: 16px;
top: 15px;
display: grid;
width: 24px;
height: 24px;
place-items: center;
border-radius: 999px;
background: var(--green);
color: #05201b;
font-size: 13px;
font-weight: 900;
}
.footer {
padding: 40px 0 64px;
color: var(--muted);
text-align: center;
}
@media (max-width: 860px) {
.page {
width: min(100% - 28px, 720px);
}
.hero {
min-height: auto;
padding-top: 44px;
}
.section-head,
.two-col,
.three-col,
.problem-list,
.qa-strip {
grid-template-columns: 1fr;
}
.layer-card {
grid-template-columns: 1fr;
}
.arrow {
transform: rotate(90deg);
}
}
</style>
</head>
<body>
<main class="page">
<section class="hero" aria-labelledby="page-title">
<div>
<p class="eyebrow">客户展示版 | Project Architecture Showcase</p>
<h1 id="page-title">GEO 智能文章优化器</h1>
<p class="hero-copy">
一个以事实卡为约束、以质量门禁为闭环的 AI 内容优化工作流。它不是普通改写器,
而是把“事实确认、内容优化、风险检查、定向修复、交付导出”串成可控流程的本地 MVP。
</p>
<div class="tag-row" aria-label="核心能力">
<span class="tag">事实卡约束</span>
<span class="tag">多节点 Agent 工作流</span>
<span class="tag">QA 质量门禁</span>
<span class="tag">定向重写</span>
<span class="tag">Markdown / Word / JSON 导出</span>
</div>
<div class="metric-row" aria-label="项目指标">
<div class="metric">
<strong>10</strong>
<span>类内容质量门禁</span>
</div>
<div class="metric">
<strong>2</strong>
<span>轮失败项定向重写</span>
</div>
<div class="metric">
<strong>3</strong>
<span>种可下载交付物</span>
</div>
</div>
</div>
</section>
<section aria-labelledby="problem-title">
<div class="section-head">
<div>
<p class="eyebrow">Why It Matters</p>
<h2 id="problem-title">先解决客户最担心的内容风险</h2>
</div>
<p>
GEO 内容优化的核心不是“写得更像 AI”,而是让文章在事实、语气、结构和平台适配上更可靠。
当前项目把常见风险转成可执行的工作流节点和质量检查。
</p>
</div>
<div class="grid two-col">
<article class="card card-pad">
<h3>典型问题</h3>
<ul class="problem-list">
<li>行业漂移,文章越改越偏。</li>
<li>公司全称、简称、品牌名不一致。</li>
<li>图片主题与正文描述不匹配。</li>
<li>官方文章里出现第三方口吻。</li>
<li>平台语气和文章类型不匹配。</li>
<li>标题或正文语义不顺。</li>
<li>虚构资质、年限、案例或能力。</li>
<li>产品、服务、年限前后冲突。</li>
</ul>
</article>
<article class="card card-pad solution-card">
<h3>解决路径</h3>
<ul class="plain-list">
<li>先从原文提取候选事实。</li>
<li>由用户确认或编辑事实卡。</li>
<li>所有优化都受已确认事实约束。</li>
<li>优化后运行结构化质量门禁。</li>
<li>只针对失败项进行定向重写。</li>
<li>硬性失败清除后再允许导出。</li>
</ul>
</article>
</div>
</section>
<section aria-labelledby="workflow-title">
<div class="section-head">
<div>
<p class="eyebrow">Workflow Architecture</p>
<h2 id="workflow-title">从文章输入到可交付结果的闭环</h2>
</div>
<p>
项目内部拆成多个职责明确的节点。每个节点只处理自己的任务,最终由编排器串联成完整优化流程。
</p>
</div>
<div class="card flow-wrap">
<div class="flow" aria-label="工作流架构">
<div class="node"><strong>Article Input</strong><span>标题、正文、图片、平台</span></div>
<span class="arrow"></span>
<div class="node"><strong>InputNormalizer</strong><span>规范化输入结构</span></div>
<span class="arrow"></span>
<div class="node"><strong>FactExtractor</strong><span>提取候选事实卡</span></div>
<span class="arrow"></span>
<div class="node"><strong>UserConfirmedFactCard</strong><span>用户确认硬约束</span></div>
<span class="arrow"></span>
<div class="node"><strong>ArticleOptimizer</strong><span>受约束内容优化</span></div>
<span class="arrow"></span>
<div class="node"><strong>QualityInspector</strong><span>执行 QA 门禁</span></div>
<span class="arrow"></span>
<div class="node"><strong>TargetedRewriter</strong><span>只修复失败项</span></div>
<span class="arrow"></span>
<div class="node"><strong>Exporter</strong><span>导出交付文件</span></div>
</div>
<p class="loop-note">
当质量检查出现硬性失败时,<strong>TargetedRewriter</strong>
会把失败项送回 <strong>QualityInspector</strong> 复检,最多进行两轮定向修复,避免整篇文章被盲目重写。
</p>
</div>
</section>
<section aria-labelledby="layers-title">
<div class="section-head">
<div>
<p class="eyebrow">Code Architecture</p>
<h2 id="layers-title">清晰分层,方便测试、替换与扩展</h2>
</div>
<p>
当前仓库不是把所有逻辑塞进页面,而是把 UI、API、领域模型、工作流、模型供应商和本地存储拆开。
</p>
</div>
<div class="grid two-col">
<article class="card card-pad layer-card">
<span class="badge"><code>src/app</code></span>
<p>Next.js 页面与 API 路由,负责创建任务、确认事实卡、触发优化和下载导出文件。</p>
</article>
<article class="card card-pad layer-card">
<span class="badge"><code>src/components</code></span>
<p>输入表单、事实卡编辑器、优化预览、QA 报告面板,各自专注一个用户界面区域。</p>
</article>
<article class="card card-pad layer-card">
<span class="badge"><code>src/lib/domain</code></span>
<p>共享 TypeScript 类型与 Zod 校验,统一文章输入、事实卡、优化结果和质量报告的数据契约。</p>
</article>
<article class="card card-pad layer-card">
<span class="badge"><code>src/lib/workflow</code></span>
<p>包含规范化、事实提取、文章优化、质量检查、定向重写、导出和编排器,是核心 Agent 流程层。</p>
</article>
<article class="card card-pad layer-card">
<span class="badge"><code>src/lib/llm</code></span>
<p>隔离 DeepSeek 与 OpenAI-compatible 模型调用,提供统一的文本生成、JSON 生成和供应商状态接口。</p>
</article>
<article class="card card-pad layer-card">
<span class="badge"><code>src/lib/db</code></span>
<p>本地 SQLite 连接、schema 和 repository,支持任务、事实卡、优化结果和导出记录持久化。</p>
</article>
<article class="card card-pad layer-card">
<span class="badge"><code>tests</code></span>
<p>Vitest 与 Playwright 覆盖领域校验、数据库、工作流、API 和 MVP 端到端行为。</p>
</article>
</div>
</section>
<section aria-labelledby="highlights-title">
<div class="section-head">
<div>
<p class="eyebrow">Technical Highlights</p>
<h2 id="highlights-title">让客户放心的关键设计</h2>
</div>
<p>
这些亮点都来自当前代码结构和产品流程,重点是降低幻觉风险、提高可控性,并保留后续扩展空间。
</p>
</div>
<div class="grid three-col">
<article class="card card-pad highlight">
<h3><span class="index">1</span>事实先确认</h3>
<p>候选事实不会自动成为真相。公司名、产品名、行业、年限和核心声明必须进入已确认事实卡后,才会约束后续优化。</p>
</article>
<article class="card card-pad highlight">
<h3><span class="index">2</span>质量门禁结构化</h3>
<p>检查结果统一为 <code>pass</code><code>warn</code><code>fail</code>,硬性失败会阻止导出,避免问题内容直接交付。</p>
</article>
<article class="card card-pad highlight">
<h3><span class="index">3</span>失败项精准重写</h3>
<p>标题问题改标题,公司名问题改事实一致性,图片问题提示确认;避免一次失败就重新生成整篇文章。</p>
</article>
<article class="card card-pad highlight">
<h3><span class="index">4</span>模型供应商可替换</h3>
<p>LLM 调用集中在 provider client,当前支持 DeepSeek 和 OpenAI-compatible 配置,后续可替换模型而不改工作流。</p>
</article>
<article class="card card-pad highlight">
<h3><span class="index">5</span>本地可演示可测试</h3>
<p>缺少 API Key 时仍有确定性本地 fallback,配合 SQLite 本地存储,适合内网演示、测试和客户评审。</p>
</article>
<article class="card card-pad highlight">
<h3><span class="index">6</span>导出面向交付</h3>
<p>通过 Markdown / Word / JSON 同时服务人工审稿、客户交付和系统集成,QA 报告也能作为质量依据留档。</p>
</article>
</div>
<div class="qa-strip" aria-label="QA 状态含义">
<div class="qa pass"><strong>Pass</strong><span>可进入预览与导出。</span></div>
<div class="qa warn"><strong>Warn</strong><span>允许导出,但提示人工复核。</span></div>
<div class="qa fail"><strong>Fail</strong><span>触发重写或阻止导出。</span></div>
</div>
</section>
<section aria-labelledby="boundary-title">
<div class="section-head">
<div>
<p class="eyebrow">MVP Boundary</p>
<h2 id="boundary-title">边界清楚,才方便下一步投入</h2>
</div>
<p>
当前版本聚焦验证“事实约束 + QA 闭环”的主链路,不提前引入批量队列、权限系统或发布平台集成。
</p>
</div>
<div class="grid two-col">
<article class="card card-pad">
<h3>当前 MVP 边界</h3>
<ul class="plain-list">
<li>仅支持粘贴文本,不直接解析 .docx。</li>
<li>仅使用本地 SQLite 存储。</li>
<li>暂无账号权限与多人协作。</li>
<li>暂无发布平台 API 集成。</li>
<li>暂无批量队列。</li>
<li>Word 导出为基础版式。</li>
</ul>
</article>
<article class="card card-pad solution-card">
<h3>自然扩展方向</h3>
<ol class="roadmap">
<li>.docx 解析与模板化 Word 导出。</li>
<li>多品牌事实卡库与复用策略。</li>
<li>批量优化队列与任务看板。</li>
<li>团队审稿、确认和发布审批流程。</li>
<li>对接官网、媒体号或其他发布平台。</li>
<li>行业专属质量门禁与规则包。</li>
</ol>
</article>
</div>
</section>
<section aria-labelledby="summary-title">
<div class="section-head">
<div>
<p class="eyebrow">Customer Takeaway</p>
<h2 id="summary-title">这套架构的价值</h2>
</div>
<p>
它把 AI 内容生成从“不可控的一次性改写”变成“可确认、可检查、可修复、可交付”的工程化流程。
</p>
</div>
<div class="card card-pad">
<p class="section-note">
对客户来说,这意味着更低的事实风险、更清晰的质量依据和更稳定的交付结果。
对技术团队来说,这意味着每个节点都可以独立测试、替换和扩展,后续接入更多模型、更多规则和更多发布场景时,
不需要推翻当前主流程。
</p>
</div>
</section>
</main>
<footer class="footer">
GEO Agent Article Optimizer · Architecture Showcase · Static HTML
</footer>
</body>
</html>
@@ -0,0 +1,104 @@
# Project Architecture Showcase HTML Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Build a standalone Chinese HTML page that presents the GEO Agent Article Optimizer architecture, business value, technical highlights, MVP boundaries, and expansion paths for customer demonstrations.
**Architecture:** Implement a single static HTML document under `docs/` with embedded CSS and no external dependencies. The document will use semantic sections, responsive CSS grid/flex layouts, and CSS-only diagrams to show the workflow and system layers.
**Tech Stack:** HTML5, embedded CSS, no JavaScript required, no external assets.
---
## File Structure
- Create: `docs/project-architecture-showcase.html`
- Self-contained customer-facing presentation page.
- Includes all copy, layout, and responsive CSS in one file.
- Opens directly in a browser without Next.js, CDN assets, or network access.
## Task 1: Create Static Showcase Page
**Files:**
- Create: `docs/project-architecture-showcase.html`
- [ ] **Step 1: Create the standalone HTML skeleton**
Add a complete HTML5 document with:
- `lang="zh-CN"`.
- UTF-8 charset.
- Responsive viewport meta tag.
- Page title: `GEO 智能文章优化器 | 项目架构展示`.
- Embedded `<style>` block.
- Body sections for hero, customer problems, workflow architecture, code architecture, highlights, MVP boundary, and expansion roadmap.
- [ ] **Step 2: Add customer-facing Chinese content**
Add the approved content from `docs/superpowers/specs/2026-06-16-project-architecture-showcase-html-design.md`:
- Hero positioning: `一个以事实卡为约束、以质量门禁为闭环的 AI 内容优化工作流`.
- Capability labels: `事实卡约束`, `多节点 Agent 工作流`, `QA 质量门禁`, `定向重写`, `Markdown / Word / JSON 导出`.
- Customer problems: industry drift, company-name inconsistency, image-text mismatch, official-voice mismatch, platform mismatch, grammar quality, hallucinated claims, and claim inconsistency.
- Solution loop: extract candidate facts, confirm fact card, optimize under confirmed facts, run quality gates, rewrite failed sections, export after hard failures are cleared.
- Actual workflow nodes: `Article Input`, `InputNormalizer`, `FactExtractor`, `UserConfirmedFactCard`, `ArticleOptimizer`, `QualityInspector`, `TargetedRewriter`, `Exporter`.
- Code layers: `src/app`, `src/components`, `src/lib/domain`, `src/lib/workflow`, `src/lib/llm`, `src/lib/db`, tests.
- Technical highlights, MVP limits, and expansion paths from the design spec.
- [ ] **Step 3: Add responsive presentation styling**
Add embedded CSS that:
- Uses a dark professional background with restrained blue/green accents.
- Keeps text legible on desktop and mobile.
- Uses cards for repeated units only.
- Uses CSS-only flow chips and arrows for the architecture diagram.
- Uses responsive grids for problem/solution, module layers, and highlight sections.
- Avoids external fonts, images, icons, and scripts.
## Task 2: Verify The Static Page
**Files:**
- Verify: `docs/project-architecture-showcase.html`
- [ ] **Step 1: Confirm the file exists and has no external resources**
Run:
```bash
test -f docs/project-architecture-showcase.html
rg -n "https?://|<script|@import|cdn|fonts.googleapis" docs/project-architecture-showcase.html
```
Expected:
- `test -f` exits successfully.
- `rg` returns no matches.
- [ ] **Step 2: Confirm required project terms are present**
Run:
```bash
rg -n "GEO 智能文章优化器|InputNormalizer|FactExtractor|UserConfirmedFactCard|ArticleOptimizer|QualityInspector|TargetedRewriter|Exporter|src/lib/workflow|DeepSeek|SQLite|Markdown / Word / JSON" docs/project-architecture-showcase.html
```
Expected:
- All required architecture terms appear in the HTML.
- [ ] **Step 3: Confirm the HTML can be opened directly**
Run:
```bash
open docs/project-architecture-showcase.html
```
Expected:
- The operating system opens the static HTML file in a browser.
- No local dev server is required.