发布于 更新于 约 5 分钟读完 · 1,794 字

本文目录 8 节
  1. 一句话
  2. 背景:顺序罗列的必然崩坏
  3. 律一 · 两层数据驱动结构
  4. 技术二 · 无头卡片量产(HTML → Chrome 截图)
  5. 踩过的坑(可迁移)
  6. 二次验证 ⭐⭐(2026-06-24 · 反诈柜台多端发布)
  7. 适用边界
  8. 关联文档

长期更新展示站:两层结构 + 无头卡片量产

入档:2026-06-19 来源:给《目标是成为 Prompt 大师》学员站(GitHub Pages)加第 2 期时的结构升级 性质:可迁移的内容站架构律 + 卡片量产技术


一句话

任何「长期一期一期往里加」的展示型站点(作品集 / 教程系列 / 案例库),首页都不要顺序罗列全文——改成「分类封面墙 + 详情」两层,数据驱动;配图卡用「HTML 复用站点 CSS → Chrome 无头截图」量产,不依赖图像生成或手绘。


背景:顺序罗列的必然崩坏

第 1 期时,index.html 把整期内容(封面卡 + 拆解卡 + 原图 + 操作区)平铺在一页里。一期没问题,但这是会持续更新的系列:到第 10、20 期,首页会变成一条几十屏的长卷,读者要找某一期得一路滚,首页也越来越重。

判据:只要内容是「单调增长」的,顺序罗列就是一颗定时炸弹。第一期就该按「将来有 50 期」来设计结构。


律一 · 两层数据驱动结构

把单页拆成两个视图,中间用 URL hash 路由切换:

  1. 首页 = 封面墙(catalog):一格一期,只放封面卡缩图 + 期号 + 分类标签。紧凑、恒定高度,不随期数变长。顶部一排分类筛选 chip,按主题筛(本例:抽象词破题 / 物件与尺度)。
  2. 详情页(detail):点封面进入 #ep02,才渲染该期的完整内容(双卡 + 原图 + 一键复制 + 笔记弹窗 + 点赞)。一次只加载一期,互不干扰。

关键:数据驱动,不是手抄 HTML。 把每期抽成一个 JS 清单数组(manifest)里的一条对象:

var EPISODES = [
  { id:"ep02", no:"第 2 期", title:"《童话镇里的纸飞机》", cat:"object",
    sub:"...", folder:"02_纸飞机",
    cover:"...封面卡.png", breakdown:"...拆解卡.png", original:"...原图.png",
    note:"...笔记.md", xhs:"https://...", prompt:"..." }
];

封面墙、详情页、筛选、路由全部由这个数组渲染。于是「新增一期 = 建一个文件夹放资产 + 在数组里加一条对象」——再不用复制粘贴一大块 <article> HTML,也不会漏改 id / data-target / 计数 key 这类唯一标识(旧的「复制 <article> 区块」做法每次都得手动改 5 处占位,极易出错)。

反直觉点:很多人升级时第一反应是「拆成多个 HTML 页面」。但静态站(GitHub Pages、无构建)下,单文件 + 数据数组 + hash 路由维护成本最低:公共的灯箱 / 弹窗 / 脚本只留一份,新增期零改动公共逻辑。


技术二 · 无头卡片量产(HTML → Chrome 截图)

系列每期要两张 3:4 卡(封面卡 + prompt 四层拆解卡),用作站内展示 + 小红书发布。产出方式:

  1. 用站点同一套 CSS 变量(四色系统、字体、留白)写一个卡片 HTML,html,body 固定成目标尺寸(如 600×800),overflow:hidden。
  2. Chrome 无头截图导出 PNG:
chrome --headless --disable-gpu --hide-scrollbars \
  --force-device-scale-factor=2 --window-size=600,800 \
  --screenshot="封面卡.png" "file:///绝对路径/card.html"

--window-size 决定版面尺寸,--force-device-scale-factor=2 出 2 倍高清(600×800 → 实际 1200×1600)。截图尺寸 = window-size × scale,所以让 body 尺寸严丝合缝等于 window-size,就能得到精确比例、无白边、无滚动条的卡。

为什么用它而不是 Pillow 逐像素画 / 图像生成模型:

  • 卡和网站共用 CSS,视觉天然一致,改配色一处改两处生效;
  • 排版用 HTML/flex,中文换行、下划线分段(给 prompt 按层上色)比 Pillow 画框算坐标省事得多;
  • 完全确定、可复现、零 API 成本,不像生成模型会漂移。

(系列原有的 make_cards.py(Pillow)仍可用;HTML→无头 是同等有效、改版式更快的替代路径,二选一。)


踩过的坑(可迁移)

  • 中文文件名上线要 URL 编码:纸飞机_原图.png 在 GitHub Pages 上的 URL 是 %E7%BA%B8...。验证线上可达要用编码后的 URL curl 看 200。
  • 本地 file:// 下 fetch() 会被 CORS 拦:站点的「笔记弹窗」是 fetch 本地 .md,本地直接打开 index.html 测不了——纯 DOM 渲染(封面墙、详情排版)可用无头截图本地验证,fetch 类功能要等上线后测。
  • MSYS/Git Bash 会改写 /tmp 路径:传给 Chrome 的 --screenshot=/tmp/x.png 会被映射到 Windows temp。统一用 Windows 绝对路径(E:/.../x.png)最稳。详见 Windows下编码与DPI的所见非真相_v1。
  • GitHub Pages 重建有延迟:push 后约 30–60 秒才生效,且可能命中 CDN 缓存;轮询线上时加随机 query(?cb=$RANDOM)绕缓存确认。
  • 外站跳小红书会被反外链拦:从自己站点点击 xhslink 跳转,浏览器带 Referer,小红书弹「当前笔记暂时无法浏览 / 扫码查看」;地址栏直接打开却正常(无 referer)。解法:出站链接加 referrerpolicy="no-referrer"(配 rel="noopener noreferrer")。这类「带来源被反爬 / 被拦」对外链平台通用。

二次验证 ⭐⭐(2026-06-24 · 反诈柜台多端发布)

把一个 H5 小游戏铺到自有站时,本律两条各二次成立、并有延伸:

  • 数据驱动入口再验:在 Astro 站首页做”可玩 · Plays”作品墙,加一个游戏 = 在 games.js 数组加一条(title / path / tags / accent…),卡片自动出现——和系列站”新增一期 = 数组加一条”是同一招,换了内容类型照样成立。游戏本体直接丢进 Astro public/<slug>/ 原样托管到 /<slug>/(见 知识库网站免备案上线_香港轻量服务器方案_v1 用例扩展)。
  • 无头出图扩到 SVG + 真机截图:
    • SVG→PNG:把 SVG 内联进 HTML(外链 <img src=.svg> 不会应用网页字体)再截,即得带 Fraunces / Inter 的高清图;本地没 cairosvg / magick / inkscape 时这是最稳的出图路。
    • 用 --headless=new + --virtual-time-budget=8000 等字体 / 网络就绪再截,避免字体没加载就截空。
    • 真机感截图:给渲染页注入一段 auto-play 脚本(可读同页顶层 let 全局变量,自动点”正确答案”凑画面)+ 用手机视口(≤600px)触发移动布局,批量抓”像手机实拍”的游戏截图,免手动操作。

适用边界

  • 适合条目化、单调增长的展示内容(系列、作品集、案例库)。一次性单页、或条目间强耦合需要同屏对比的,不必拆两层。
  • 无头截图卡适合版式固定、批量同款的设计稿;每张都要独特艺术构图的,还是回到图像生成 / 手绘。
  • 数据驱动单文件到几百条会偏大,届时再考虑拆数据文件 / 上构建;百条以内单文件最省心。

关联文档

类型/协作工具链