项目矩阵 内容应用 Eecho · 5 分钟 AI
EEagle 主维护 · 内容应用 · 2026 H1

echo

面向公众号作者的 5 分钟 AI 写作平台 · Phase 化迭代

公众号写作的现状是八股化、风格漂移、A/B 改写反复覆盖原文;市面工具又普遍要密码注册 + 切站登录折腾人。echo 是给中小公众号运营者 / 个人写作者的一站式平台:writing-kit 模板 + 5 步向导 + Azure OpenAI 流式改写串成一条线,从选题、草稿、A/B 改写、排版到发布全在一个页面内闭环,改写永远给两版让作者手选、不默认覆盖原文。登录走微信公众号扫码(经 wx-gateway)— 关注即注册,公众号 openid 本身就是上下文,免密码、免邮箱、免第三方账号。整套系统按 Phase 2.0 → 2.1 → 2.2 → 2.3 → 2.5 → 8M 节奏稳健迭代,已生产部署在 echo.mvp.restry.cn

访问 echo.mvp.restry.cn Restry/echo · private · v0.1.0 受众:中小公众号运营者
6
Phase 迭代节奏
9
drizzle 表 · ec_*
22
commits · Phase 1 → 8M
1
已上线生产域

核心能力 · Five Capabilities

5 件事,把"写一篇公众号"从一上午压到 5 分钟

所有能力围绕一条主线:账号(pubaccount) → writing-kit 模板 → 5 步向导 → 流式 AI 双稿 → 发布。账号本身即上下文,作者从扫码进站到点发送全程不离开 echo。

Phase 化迭代
小步稳健
2.0 底座 → 2.1 内容中心 → 2.2 三栏编辑器 → 2.3 流式改写 → 2.5 扫码登录 → 8M 图生 batch。每个 phase 独立可上线、不挡下一步。
22 commits / 6 phases · main 干净
writing-kit 模板
5min-ai 风格锁定
5 步向导(选题 → 草稿 → A/B 改写 → 排版 → 发布)+ 禁词表 + CTA 模板 + 历史样稿,全部 vendor 进仓库,服务器零依赖外部目录。
scripts/writing-kits/5min-ai/ · seed:kits
Azure OpenAI 流式
改写给两版让你挑
SSE 默认 message 事件流式渲染,改写永远给 A/B 两个版本,作者手选,不默认覆盖原文 — 这是父父定的硬规则。
gpt-5.4 (text) · gpt-image-2 (img) · SSE
微信扫码登录
免密码 · 关注即注册
登录走 wx-gateway 业务方 echo,公众号扫码即认证;openid 本身就是账号上下文,不需要邮箱 / 密码 / 第三方 OAuth。
next-auth 5 beta · wx-gateway /wx/qr/echo
Drizzle + Postgres
SQL-first 工具链
9 张 ec_* 表覆盖用户 / 账号 / 文章 / writing-kit / 素材 / 设置;drizzle-kit migrate → seed:kits → next build 一条链路硬绑死。
drizzle 0.45 · pg shared host · multi-schema

架构 · Users → echo → 3 deps

一张图看清:用户两路入口 → echo 单实例 → 三依赖横排

受众通过两个入口进:微信内置浏览器(扫码登录后留在公众号生态)或桌面浏览器(直接访问域名)。echo 单实例对接三个外部依赖:AI 推理、微信登录、部署 / 数据库 host。

Users · 两路入口
微信内置浏览器扫码登录
桌面浏览器直接访问
HTTPS · session cookie
echo · Next.js 单实例
Production
echo
echo.mvp.restry.cn :3795 · /opt/mvp-apps/echo/
Next 16 · App Router React 19 next-auth 5 beta Drizzle ORM Tailwind v4 shadcn/ui · Base UI @uiw/react-md-editor
外部依赖 (HMAC / SSE / SQL)
External Dependencies
Azure OpenAI
gpt-5.4 文本 + gpt-image-2 图
SSE 流式
wx-gateway
业务方 echo
扫码登录 + openid 绑定
mvp-deployer
zip → build → drizzle migrate
共享 PG host · Caddy HTTPS

关键里程碑 · Timeline

Phase 1 → 8M · 6 个结构性 phase 一条线

从 Phase 1 脚手架到 8M batch 图生上线,每个 phase 独立可发布。⭐ 标记的是结构性里程碑:Phase 2.0 schema 落地 / 2.3 AI 流式接入 / 2.5 微信扫码登录 / 8M 图生 batch。

Phase 2.0 ★ 里程碑writing-kits + article-assets schema 落地 + 5min-ai writing-kit seed(f7464ba)— 内容域基础数据模型从这里定型。
Phase 2.0 部署修复:drizzle/seed env fallback + build 链路串 migrate + seed(9a12dd6)— 解决"少一步就炸"的硬绑死顺序。
Phase 2.1 内容中心 master-detail list + preview 三栏雏形(fa57997)— 文章列表 / 预览初版。
Phase 2.2 内容编辑器三栏定型(列表 / 编辑 / AI 面板)+ AI 改写占位(21cd8c8)。
Phase 2.3 ★ 里程碑writing-kit 关联 + Azure OpenAI 流式改写接入(d3ba0c7)— AI 双稿能力首次跑通,SSE 渲染落地。
Phase 2.5 ★ 里程碑微信公众号扫码登录上线(接 wx-gateway,935ad0f)— 至此告别密码,关注公众号即注册。
Phase 2.5+ 496dedb finalize redirect 用 NEXTAUTH_URL 替代 req.url;be8bdb0 SSE 改成默认 message 事件 — 扫码登录稳态的"双拳"修复。
2026-05 8052769 移动端响应式重构 + jwt 按需 DB 刷新拿 name/image;64f3568 dashboard 侧栏用户身份徽章 + 移动端 header。
2026-05 e9b829b 5 步公众号写作向导(选题 → 草稿 → A/B 改写 → 排版 → 发布) + 发布格式适配 — 5min-ai 主流程贯通。
8M batch ★ 里程碑8M 大批次:图生 + 设置页 + UX 清理(fdae06b)— gpt-image-2 进编辑器,省去切到外部出图工具的来回。
收尾 1a83b66 接入门神 vault(所有密钥不再读 ~/.credentials/.env) · dc1f1a9 dark SVG 架构图 · 56a7f17 .hermes/memory.md 落盘。

名场面 · 1 个最值钱的坑(深度)

微信扫码登录 SSE 在生产永远 pending — 一根因压不住,实际是双拳

Phase 2.5 扫码登录刚接上 wx-gateway 那天,本地完美、桌面 Chrome 完美,一进微信内置浏览器立刻挂 — 扫码后状态条永远 pending,从不进 confirmed。最初以为是 SSE 命名事件没监对,改完发现还有第二拳:反代后 req.url 拼回调直接拼成内网 URL。

HALL OF FAME · echo Phase 2.5 双拳

SSE 默认事件名 + 反代后 req.url 不可信

症状
扫码登录在生产微信内置浏览器表现:二维码刷新正常、用户扫码后微信 toast 确认成功,前端 SSE 状态条永远 pending,从不切到 confirmed,也不重定向。本地 dev / 桌面 Chrome 全绿。
根因 1
前端用 eventSource.addEventListener('confirmed', ...) 监听命名事件。但 wx-gateway 那边 SSE 发出来的是 默认 message 事件(payload 里带 type 字段区分),根本没写 event: confirmed 这一行。命名 listener 永远收不到,自然永远 pending。
修法 1
统一改成 onmessage + payload 内部分发:e => JSON.parse(e.data).type === 'confirmed' && finalize()(be8bdb0)。
根因 2
修完命名事件,confirmed 收到了,可 finalize 后重定向到内网 IP。原因是 callback 用 new URL(path, req.url) 拼 absolute URL,反代后 Next 看到的 req.urlhttp://127.0.0.1:3795/...,不是外网域。
修法 2
改用 process.env.NEXTAUTH_URL 显式拼绝对 URL(496dedb),反代环境下 req.url 一律视为不可信。
// 拳 1 — 前端 SSE 监听:别用命名事件
- eventSource.addEventListener('confirmed', e => ...)
+ eventSource.onmessage = e => {
+   const m = JSON.parse(e.data)
+   if (m.type === 'confirmed') finalize(m)
+ }

// 拳 2 — 拼回调 URL:别信反代后的 req.url
- return NextResponse.redirect(new URL('/dashboard', req.url))
+ const base = process.env.NEXTAUTH_URL!
+ return NextResponse.redirect(new URL('/dashboard', base))
沉淀:这两个坑组合起来在生产微信内置浏览器 100% 复现,但本地 dev / 桌面浏览器 100% 复现不出来 — 必须真在反代后的微信 webview 才能撞上。已沉淀进 hermes skill nextjs-reverse-proxy-redirect-leaksse-default-message-event-default:下次任何 Next + SSE + 反代项目接微信登录,这两条先翻一遍。

📊 当前现状 · Status

五个维度,每条都对应可 grep 的真实事实

不写"运行良好 / 反馈正面"这类空话。下面五个分组每条都能在 git log / src/db/schema.ts / .hermes/memory.md 里 grep 到。

生产部署

  • 域名:echo.mvp.restry.cn · 已上线 · HTTPS by Caddy
  • PM2 进程:echo · 端口 3795 · /opt/mvp-apps/echo/
  • 部署链路:mvp-deployer zip → 异步 build → drizzle migrate → seed:kits
  • build 顺序硬绑死:drizzle-kit migrate → pnpm seed:kits → next build,少一步炸
  • env 切换:postDeploy ln -sf .env .env.local(drizzle.config.ts 读 .env.local)

数据规模

  • 9 张 ec_*(src/db/schema.ts):ec_users · ec_sessions · ec_accounts_oauth · ec_verification_tokens
  • 内容域:ec_pubaccounts · ec_articles · ec_writing_kits · ec_article_assets · ec_settings
  • Postgres:本地 192.168.1.235:15432/echo · 生产 127.0.0.1:5432/echo(共享 host)
  • schema 状态机:ec_article_status · ec_asset_status · ec_asset_platform 三个 enum
  • writing-kit seed:5min-ai 模板已 vendor 进 scripts/writing-kits/5min-ai/(7e2e784)

接入依赖

  • wx-gateway:业务方 echo 已注册;扫码登录走 /wx/qr/echo + SSE poll
  • Azure OpenAI:文本 gpt-5.4 流式改写;图像 gpt-image-2(8M batch 接入)
  • 门神 vault:1a83b66 接入;所有密钥 vault project show echo,禁读 ~/.credentials/.env
  • mvp-deployer:zip-only 上传 + 异步 build + 共享 PG host

最近变动(8 条)

  • 56a7f17 docs(.hermes): project memory + SKILL prod status fix
  • 1a83b66 docs: 接入门神 vault;.env.local* 加 gitignore
  • dc1f1a9 docs: dark architecture diagram (SVG/HTML)
  • c6fd21d fix(delete): native confirm + router.replace+refresh
  • fdae06b feat(echo): 8M batch — 图生 + 设置页 + UX cleanup ★
  • be8bdb0 fix(wx-login): SSE uses default message event
  • e9b829b feat(ai-draft): 5 步公众号写作向导 + A/B 改写
  • 8052769 fix(mobile+session): 移动端响应式 + jwt 按需 DB 刷新

运维状态

  • Phase 2.5 扫码登录已稳定:命名事件 + 反代 URL 双拳修复后,生产微信内置浏览器登录链路一个月零工单
  • 8M batch 图生已上线:gpt-image-2 直接进编辑器,作者不再切到外部出图工具
  • 移动端响应式跑通:sidebar / dashboard / header 一套适配;jwt 按需 DB 刷新拿 name/image
  • main 干净:git status 无 stash 无 WIP,本地与生产同步
  • 已知警告:metadataBase 没配,next build 会 warn(P2 排期)

🚧 未结清债务 · Open Debt

7 条具体待办 · 每条带优先级 / 工作量 / 现状

来源:.hermes/memory.md TODO 段、SKILL.md 过时项、近 22 commits 标记。每条 4 列:优先级(P0 立刻 / P1 本周 / P2 排期) · 工作量(S < 0.5d · M 1-2d · L 3d+) · 待办 · 现状是什么

优先级 工作量 待办 现状(还差什么)
P1 S SKILL.md "未部署" 文案过时 .hermes/memory.md 已标注:.hermes/skills/echo/SKILL.md 里写"未部署",但 echo.mvp.restry.cn 早已上线。需改成"已上线"+ 端口 / 部署链路一句话。
P1 S TODO.md 清理 老 TODO 里列的 references / style-fingerprint 已落到 scripts/writing-kits/5min-ai/ 实际目录,TODO 文档没同步删掉。需逐项核对、删冗余。
P1 M 公众号定时推送 当前发布只支持"直接推 / 存草稿",Phase 3 列的定时推送没动:需 ec_articles.scheduled_at 字段 + cron 扫描 + wechat-publisher 调度链路。
P1 L 小红书一稿多投 Phase 3 主目标。ec_asset_platform enum 已留好 xhs 占位,但发布链路 + 排版适配 + 平台 token 接入全空。
P2 S metadataBase 配置 next build 持续 warn,OG image 拼绝对 URL 不准。一行 layout.tsxmetadataBase: new URL('https://echo.mvp.restry.cn') 就完。
P2 M 视频生成 Phase 3 三大目标之一。需调研短视频 AI 生成 API + 排版 + 公众号视频号发布链路,目前无任何代码。
P2 S 多账号真实接入 ec_pubaccounts 表 schema 已支持挂多个公众号,但目前只有一个真实账号在跑。新账号接入流程没走过一遍,可能有未发现的 hard-code。

🛠 技术栈 · Stack

RuntimeNext.js 16 · React 19 · pnpm · PM2 DBPostgres · Drizzle 0.45 · drizzle-kit Authnext-auth 5 beta · wx-gateway echo AIAzure OpenAI · gpt-5.4 · gpt-image-2 · SSE UITailwind v4 · shadcn/ui · @base-ui/react · lucide-react Editor@uiw/react-md-editor · next-themes Opsmvp-deployer · Caddy · vault QAVitest