📚🎬 知行合一AI实验室

这是我用 AI 从零搭建的个人 AI 应用实验室,书影/生活追踪只是目前跑在里面的第一个功能。完整内容登录后才能看到,这里是公开的开发更新日志。

登录

这个网站是怎么做出来的

🤖 AI 开发模式(这个网站的实际流程)
💬
跟 Claude
对话提需求
🤖
Claude Code
写代码
🐙
推送到
GitHub
🚂
Railway
自动部署
网站更新
上线
⏱ 一个想法到上线:几分钟到几小时
🧑‍💻 传统开发模式(对比)
📋
写需求
文档
🧑‍💻
工程师
手写代码
🧪
写测试
跑测试
👀
Code
Review
🔄
CI/CD
自动部署
上线
⏱ 同样一个想法到上线:通常数天到数周

全程不用手写一行代码,我只负责提需求和验收;每次改动的细节都记录在下面的更新日志里。源代码在 GitHub →

网站的技术架构

🖥️📱 浏览器 / 手机 PWA HTTPS 🌍 Railway 边缘 CDN 全球多节点,图片/静态资源边缘缓存 未命中 / 动态请求 → 转发源站 🐳 源站容器 · Railway(新加坡) gunicorn:1 进程 + 4 线程,共享内存态数据 ⚙️ Flask 应用(app.py) 🔐 路由 + 登录鉴权 🧩 Jinja2 服务端渲染 🖼️ Pillow 图片 / ffmpeg 视频处理 🗜️ Gzip / Brotli 压缩 📊 请求耗时统计 💾 持久化存储 Railway Volume · /data • tracker.db(书影 / 动态 / 小说 数据) • uploads/(动态上传的照片) • novel_media/(小说封面 / 立绘 / 视频) • cover_cache/(豆瓣封面缓存) 🔌 外部服务 运行时对外请求 • 豆瓣网页抓取 + 封面代理 • Claude API(AI 截图识别,可选)

服务端是一个 Flask + SQLite 的单体应用,没有独立前端构建,页面都是服务端用 Jinja2 直接渲染出来的; 用 gunicorn(1 进程 4 线程)跑在 Railway 新加坡区域的一个 Docker 容器里。图片用 Pillow 处理(生成分享图、 压缩上传图片),视频用 ffmpeg 压缩并抽封面帧。数据库、用户照片、小说封面/立绘/视频、豆瓣封面缓存都存在 Railway 的持久化 Volume 里,图片和静态资源通过边缘 CDN 缓存;豆瓣书影信息靠抓取网页拿到,AI 截图识别接的 是 Anthropic 的 Claude API。

Changelog

中文

A record of this site's development from scratch to now (screenshots are freshly regenerated to reflect the current UI, not the original at the time of each change).

AugSepOctNovDecJanFebMarAprMayJunJulAug
11 active days in the past year, 91 updates, ~10637 lines of code changed

Code volume: entries from before this session (marked "estimated") are rough figures reconstructed in hindsight; every entry from this one onward is measured precisely at the time of the change.

2026-08-04

1 updates · ~15 lines that day
  • Chapter editor now matches the reader view's width and font size

    +15 lines

    The chapter content textarea was using the generic form style, capped at 560px wide -- much narrower than the actual reading page, making it hard to judge real layout while writing. Now the editor and the reader view line up on width, font size, and line height (both 870px wide, 16px text, 1.9x line height), so what you see while editing is close to what readers will see. Hit a CSS specificity snag along the way: the new font-size rule was silently overridden by an earlier, more specific generic rule (`.form textarea`) until switched to a more specific selector.