用Seed-2.1-pro从零搭建沉香小镇数字门面:前端实战与AI协作全记录
发布时间:2026/10/14 18:05:58 锦皓数字建站

沉香这东西外行看是木头内行看是时间跟菌丝较劲的结果。我老家那个镇子祖上三代做香的人家一抓一大把可这些年年轻人往外跑好东西卖不上价游客来了拍两张照就走连个能看的地方都没有。去年秋天我回去待了半个月看着镇上那几家老作坊门口堆着料心里不是滋味。后来我琢磨着能不能用自己吃饭的手艺——写前端——给村子搭一个像样的数字门面。正好那阵子在用 Seed-2.1-pro 做代码辅助就想着干脆拿它当主力把整个站从零到一撸出来。这篇文章就是那次折腾的完整记录从需求拆解、技术选型、AI 协作方式到实际写 HTML、CSS、site.js 时踩的坑全都摊开讲。不管你是刚学前端想找个真实项目练手还是想给自家小生意做个展示页这篇应该都能让你少走点弯路。1. 先想清楚一个乡镇展示站到底要解决什么问题1.1 不是做官网是做数字门面很多人一听给村子做网站第一反应是套个企业模板放几张图、写段简介就完事。我一开始也差点这么干后来发现完全不对。镇上的香农不需要一个关于我们的页面他们需要的是让外面的人隔着屏幕就能闻到那股味道。这就决定了整个站的核心不是信息罗列而是氛围营造加信任建立。具体拆下来需求其实就三条。第一让人一眼知道这里是沉香产地不是随便哪个卖香的地方。第二让人相信这里的香是真材实料有作坊、有工序、有人。第三让人能联系上不管是询价还是想来实地看。这三条听着简单但落到页面上每一条都对应着不同的设计决策。我见过太多乡镇展示页打开就是一张大横幅下面三段文字配三张图再下面一个联系方式完事。这种页面不是不能用但它传递不出任何这个地方值得信任的信号。沉香这个品类尤其特殊客单价高、真假难辨买家最怕的就是被坑。所以页面的每一个细节从配色到字体到图片的呈现方式都得往真实、克制、有质感这个方向靠。1.2 为什么不用现成的建站工具有人肯定要问现在建站工具那么多拖拖拽拽不就完了何必自己写代码。这个问题我认真想过结论是对于这个场景自己写反而更省事。建站工具的问题在于它的模板逻辑是通用的你想改一个细节往往要跟它的框架较劲。比如我想做一个鼠标移入时香炉图标缓慢旋转的效果或者让页面滚动到某个位置时文字渐显这些在通用工具里要么做不了要么得装插件装完还拖慢加载。而自己写 HTML 加 CSS 加一点原生 JS这些效果都是几行代码的事而且完全可控。另一个原因是加载速度。镇上网络条件一般游客在山上信号也不一定好页面必须轻。建站工具生成的页面往往塞了一堆用不上的库和样式一个首页动辄几兆。我自己写的版本整个站压缩后不到 300KB图片单独优化首屏基本秒开。这个差距在真实使用场景里是决定性的。还有一点自己写代码意味着我可以把 site.js 写得非常克制只做必要的交互不引入任何框架。对于这种展示型站点React、Vue 这些完全是杀鸡用牛刀原生 JS 足够而且没有构建步骤改完直接传服务器维护成本极低。镇上要是以后想找人接手改随便一个懂点前端的年轻人都能看懂。1.3 技术栈的最终选择与理由最终定下来的技术栈非常朴素HTML5 负责结构CSS3 负责视觉原生 JavaScript 写在一个 site.js 里负责交互。没有框架没有构建工具没有 npm 依赖。这个选择背后有几个考虑。第一部署简单。整个站就是一堆静态文件传到任何一台服务器或者静态托管上都能跑不需要 Node 环境不需要打包。第二可维护。三年后我要是忘了当时怎么写的打开文件从头读一遍就懂了不存在这个配置是哪个插件生成的这种问题。第三性能好。浏览器直接解析没有运行时开销。Seed-2.1-pro 在这个环节帮了我大忙。我不是让它直接生成整个站而是把它当成一个随时在线的结对伙伴。比如我要写一个 CSS 涟漪光圈扩散效果我会先描述清楚我要什么让它给个基础实现然后我再根据实际效果调参数。这种方式比纯自己写快很多又比直接复制粘贴靠谱因为每一行代码我都过了一遍知道它在干什么。2. 用 Seed-2.1-pro 协作写代码的正确姿势2.1 别把它当代码生成器当结对伙伴我一开始用 Seed-2.1-pro 的方式是错的。我直接丢一句帮我写一个沉香展示网站它确实给我吐了一大段代码但那段代码没法用——结构是通用的配色是默认的交互是模板化的跟我脑子里的画面完全对不上。后来我改了策略把它当成一个反应很快、知识面很广、但需要我把需求说清楚的搭档。具体怎么操作我把整个站拆成一个个小任务每个任务单独跟它对话。比如我要做一个横向排列的图片和文字图片在左文字在右宽度 1440px 的容器里图片占 40%文字占 60%中间留 40px 间距用 flex 实现这种颗粒度的描述它给出来的代码基本可以直接用。然后我再在这个基础上改颜色、改字体、改间距。这个转变很关键。AI 编程工具最大的价值不是替你写代码而是替你消灭查文档和试错的时间。你知道要做什么但不确定某个 CSS 属性怎么写问它它秒回。你不需要去翻 MDN不需要在 Stack Overflow 上翻半天。但前提是你得知道你要做什么这个它替不了你。2.2 提示词怎么写才能拿到能用的代码踩了几天坑之后我总结出一套写提示词的方法。核心就一句话把上下文、约束、期望输出三样东西说全。上下文是指这个代码要放在什么环境里。比如这是一个静态站点没有构建工具不要用任何 npm 包不要用 import 语法。约束是指具体的尺寸、颜色、行为要求。比如容器宽度固定 1440px高度自适应主色调用深褐 #3E2723辅助色用米白 #F5F0E8。期望输出是指你要它给什么。比如给我完整的 HTML 结构和对应的 CSSCSS 用类选择器不要用 ID。我举个实际例子。当时我要做一个数字加载动画就是页面打开时中间有个香炉图标下面有个进度条慢慢走。我的提示词是这样的写一个纯 CSS 的加载动画中间是一个圆形图标我用 SVG 占位图标下方有一条 200px 宽的进度条进度条从 0 到 100% 用 2 秒走完走完后整个加载层淡出。不要用 JavaScript 控制动画纯 CSS animation 实现。给我 HTML 和 CSS。它给出来的代码一次就基本能用我只调了动画时长和淡出的缓动函数。这种效率是纯手写比不了的。2.3 多 AI 协作的实际工作流标题里提到多 AI 协作这不是噱头是我实际用的工作流。Seed-2.1-pro 负责主力代码生成和逻辑梳理但有些具体问题我会换别的工具问。比如 CSS 字体渐变这种偏视觉的效果我会用另一个更擅长视觉描述的模型先给我几个方案我再拿方案去让 Seed-2.1-pro 实现成代码。还有一个场景是调试。有时候代码跑出来效果不对我把现象描述给 Seed-2.1-pro它给的分析不一定准。这时候我会把同样的现象描述给另一个模型两个答案对比着看往往能更快定位问题。这不是不信任某一个工具而是不同模型的训练数据侧重不同交叉验证能提高准确率。但要注意多 AI 协作不等于让它们互相打架。我的原则是主逻辑只由一个模型负责保证代码风格统一辅助问题可以多问几个但最终决策权在我手里。代码是我写的出了问题也是我担这个责任不能推给工具。3. 页面骨架HTML 结构怎么搭才经得起改3.1 从!doctype html开始的每一个决策很多人写 HTML 是从html开始随手写写到哪算哪。我这次刻意慢下来把结构想清楚再动手。因为展示型站点后期改版是常态结构乱了改一个地方牵动全身。第一行!doctype html是必须的它告诉浏览器用标准模式渲染。少了这行浏览器会进入怪异模式盒模型的计算方式都不一样后面所有布局都可能出问题。这个坑我早年踩过一个页面怎么调都对不齐最后发现就是少了 doctype。html langzh-cn里的 lang 属性也别省。它影响的不只是 SEO还影响浏览器选择什么字体来渲染中文。设成 zh-cn浏览器会优先用适合简体中文的字体不设的话可能用日文字体来渲染某些汉字字形会不对。这个细节很小但专业度就体现在这些地方。head里面meta charsetutf-8必须放在最前面。中文站点如果编码声明晚了可能出现乱码。然后是 viewportmeta nameviewport contentwidthdevice-width, initial-scale1.0虽然我们主容器是 1440px 固定宽度但移动端还是要能正常缩放查看不能禁止缩放那是反用户的。3.2 语义化标签不是摆设我见过太多人整个页面全是 div问就是反正都能用。能用是能用但语义化标签带来的好处是实打实的。搜索引擎能读懂你的结构屏幕阅读器能正确朗读你自己后期维护也能一眼看出哪块是哪块。这个站我用的结构是这样的顶部header放 logo 和导航主体用main包起来里面按区块分section每个 section 有自己的标题。底部footer放联系方式和版权。图片统一用figure加figcaption这样图片和说明文字在语义上是关联的。特别说一下section和article的区别。section 是页面中的一个区块article 是一篇独立完整的内容。我们这个站里作坊介绍那块每个作坊可以是一个 article因为它们各自独立、可以单独拿出来看。而关于沉香那块是一个 section因为它是页面整体叙事的一部分。这个区分不是死规定但想清楚了结构自然就清晰。3.3 图片和文字一行排列的 HTML 写法标题热词里有个图片和文字一行 css这确实是展示型站点最常见的布局需求。我在作坊介绍那块就用了这个布局左边是作坊实拍图右边是文字介绍。HTML 结构上我用一个容器 div 包住图片和文字图片用img文字用一个 div 包起来。这里有个细节图片一定要写 width 和 height 属性或者用 CSS 的 aspect-ratio 固定比例。不写的话图片加载完成前容器高度是 0加载完成的瞬间页面会跳一下体验很差。这个叫布局偏移是性能指标里明确要避免的。div classworkshop-row div classworkshop-image img srcimages/workshop-01.jpg alt老作坊内景 width560 height420 /div div classworkshop-text h3陈记香坊/h3 p始于上世纪八十年代三代人只做一件事……/p /div /divalt 属性也别偷懒。它不只是图片加载失败时的替代文字更是无障碍访问的关键。写 alt 的时候描述图片内容不要写图片两个字那等于没写。4. CSS 视觉层让页面有沉香的味道4.1 配色和字体先定调子再写代码写 CSS 之前我先花了一个下午定配色和字体。这个顺序很重要先定视觉基调再写代码不然写到一半发现颜色不对改起来就是灾难。沉香给人的感觉是沉稳、温润、有年头。所以主色调我选了深褐 #3E2723接近老木头的颜色。辅助色用米白 #F5F0E8像宣纸的底色。点缀色用暗金 #B8860B用在按钮和重点强调上但不能多用多了就俗。背景大面积留白让内容呼吸。字体方面中文用系统默认的衬线字体栈font-family: Songti SC, SimSun, serif衬线字体更有书卷气。标题可以稍微加粗正文用常规字重。字号上正文 16px 起步行高 1.8这个组合在中文阅读里最舒服。标题按层级递减h1 用 36pxh2 用 28pxh3 用 22px。这里有个经验中文的行高要比英文大。英文 1.5 就够了中文因为字形方正、笔画密集1.8 甚至 2.0 读起来才不累。这个细节很多从英文教程学前端的人会忽略做出来的中文页面挤成一团。4.2 容器宽度 1440px 的适配策略热词里提到宽 1440px这是设计稿的基准宽度。但实际用户的屏幕宽度千差万别不能写死 1440px。我的做法是主容器设max-width: 1440px然后margin: 0 auto居中。这样在大屏上最多 1440px小屏上自动收缩。.container { max-width: 1440px; margin: 0 auto; padding: 0 40px; box-sizing: border-box; }box-sizing 设成 border-box 是必须的不然 padding 会把容器撑出 1440px。这个属性我建议在全局重置里就设好*, *::before, *::after { box-sizing: border-box; }省得后面每个元素都要算。padding 左右各 40px 是为了在小屏上内容不贴边。大屏上因为容器有 max-width这 40px 就是内容区和容器边缘的呼吸空间。这个值不是随便定的40px 在 1440px 的容器里大约占 2.8%视觉上刚好太小显得挤太大显得空。4.3 鼠标移入事件与流光边框的实现热词里有css 鼠标移入事件和流光边框 css这两个我在作坊卡片的交互上都用到了。鼠标移入卡片时卡片微微上浮同时边框出现一道流光扫过。先说移入上浮。用 CSS 的:hover伪类加transform: translateY(-8px)和transition就能实现。关键是 transition 的时长和缓动函数。时长 0.3s 比较合适太快显得突兀太慢显得拖沓。缓动函数用ease-out开始快后面慢符合物理直觉。.workshop-card { transition: transform 0.3s ease-out, box-shadow 0.3s ease-out; } .workshop-card:hover { transform: translateY(-8px); box-shadow: 0 12px 32px rgba(62, 39, 35, 0.15); }流光边框稍微复杂一点。思路是用一个伪元素覆盖在卡片边框位置用linear-gradient做一个渐变色带然后通过background-position的动画让它移动起来。这里要注意伪元素要设pointer-events: none不然它会挡住卡片的点击事件。.workshop-card::before { content: ; position: absolute; inset: 0; border-radius: inherit; padding: 2px; background: linear-gradient(90deg, transparent, #B8860B, transparent); background-size: 200% 100%; -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; opacity: 0; transition: opacity 0.3s; pointer-events: none; } .workshop-card:hover::before { opacity: 1; animation: flow 1.5s linear infinite; } keyframes flow { from { background-position: 200% 0; } to { background-position: -200% 0; } }这段代码里的 mask 技巧是关键它让渐变只显示在边框区域不覆盖内容。这个写法我第一次是从 Seed-2.1-pro 那里问来的它给了基础版本我调了颜色和动画速度。4.4 涟漪光圈扩散与数字加载动画css 涟漪光圈扩散这个效果我用在了页面顶部的 logo 上。logo 是一个香炉图标鼠标移上去的时候从图标中心向外扩散一圈涟漪像水波一样。实现思路是用一个伪元素做圆环初始状态transform: scale(0)且opacity: 1hover 时transform: scale(2)且opacity: 0配合 transition 就形成了扩散消失的效果。.logo { position: relative; } .logo::after { content: ; position: absolute; inset: -10px; border: 2px solid #B8860B; border-radius: 50%; transform: scale(0); opacity: 0; transition: transform 0.6s ease-out, opacity 0.6s ease-out; } .logo:hover::after { transform: scale(1.8); opacity: 0; }数字加载动画我在前面提过就是页面打开时的加载层。这里补充一个细节加载动画的时长要跟实际资源加载时间匹配。如果动画 2 秒走完但资源 5 秒才加载好用户会看到动画结束后白屏 3 秒体验很差。我的做法是用 JS 监听window.onload资源加载完成后才触发加载层淡出动画本身设成循环这样不管加载多久用户看到的都是连贯的动画。5. site.js 里那些不起眼但很关键的交互5.1 一键返回顶部的完整实现html 一键返回顶部算法这个需求看着简单但要做好有几个细节。最基础的版本是监听滚动超过一定距离显示按钮点击后window.scrollTo(0, 0)。但直接跳回去太生硬要用平滑滚动。const backToTop document.querySelector(.back-to-top); window.addEventListener(scroll, () { if (window.scrollY 600) { backToTop.classList.add(visible); } else { backToTop.classList.remove(visible); } }); backToTop.addEventListener(click, () { window.scrollTo({ top: 0, behavior: smooth }); });600px 这个阈值是我试出来的。太小了按钮频繁出现消失太大了用户滚很久才看到。600px 大约是一屏半的高度用户开始想返回顶部的时候按钮刚好出现。还有个细节滚动监听要加节流。不加的话滚动事件触发频率极高虽然这个站内容不多感觉不出来但养成习惯是好的。简单的节流可以用requestAnimationFrame包一层。5.2 滚动渐显让内容有节奏地出现展示型站点最忌讳一打开所有内容都堆在眼前。我用 IntersectionObserver 做了一个滚动渐显元素进入视口时淡入上移。const observer new IntersectionObserver((entries) { entries.forEach(entry { if (entry.isIntersecting) { entry.target.classList.add(revealed); observer.unobserve(entry.target); } }); }, { threshold: 0.15 }); document.querySelectorAll(.reveal).forEach(el observer.observe(el));threshold 设 0.15 意思是元素露出 15% 就触发。这个值不能太大不然用户要滚到元素完全可见才触发感觉迟钝。也不能太小太小元素刚露个边就触发用户还没看到就动完了。0.15 是我试下来最自然的。observer.unobserve那行很重要元素显示后就不再观察避免重复触发也释放资源。5.3 图片懒加载与性能兜底镇上网络条件一般图片懒加载是必须的。现代浏览器原生支持loadinglazy直接在 img 标签上加就行不用写 JS。但要注意首屏图片不要加 lazy不然首屏加载会延迟。只有首屏以下的图片才加。img srcimages/workshop-02.jpg alt制香工序 loadinglazy width560 height420width 和 height 还是要写配合 lazy 使用浏览器能在图片加载前就预留好空间避免布局偏移。另外我加了一个兜底如果 JS 加载失败页面核心内容依然可见。因为渐显效果依赖 JS 添加 revealed 类如果 JS 挂了元素就一直是隐藏状态。我的做法是 CSS 里默认元素可见JS 加载后再通过添加类来触发动画。这样即使 JS 失败用户也能看到完整内容只是没有动画而已。这个思路叫渐进增强是前端的老智慧了。6. 踩过的坑和几条实在的经验6.1 CSS 文件到底要不要写style热词里有人问css 文件需要写style吗这个问题看着基础但确实有人搞混。答案是外部 CSS 文件里不写style标签直接写 CSS 规则。style标签是写在 HTML 里的用来内嵌 CSS。外部文件通过link relstylesheet hrefstyle.css引入。我这次用的是外部文件因为样式多内嵌会让 HTML 文件臃肿。但有个例外首屏关键 CSS 可以内嵌在 head 里这样浏览器不用等 CSS 文件下载完就能渲染首屏。这个叫关键 CSS 内联是性能优化手段。不过对于这个站CSS 文件本身不大直接外链就够了没必要搞那么复杂。6.2 字体渐变的兼容性处理css 字体渐变这个效果我用在了首页大标题上。实现方式是用background-clip: text配合-webkit-text-fill-color: transparent。.gradient-title { background: linear-gradient(135deg, #3E2723, #B8860B); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent; }这里要写两套前缀-webkit-那套是给 Safari 和旧版 Chrome 的标准写法是给新版浏览器的。color: transparent是兜底万一 background-clip 不支持文字至少是透明的而不是黑块。有个坑要注意字体渐变在文字换行时渐变是按整个元素计算的不是按每行。如果标题很长换行了第二行的渐变会接着第一行继续可能看起来不自然。解决办法是给每行单独包一个 span或者干脆标题不换行。我选择了控制标题长度不换行。6.3 原子性 CSS 与样式引入方式的选择热词里有原子性 css和css 样式引入方式这两个其实相关。原子性 CSS 是指每个类只做一件事比如.mt-20 { margin-top: 20px; }然后 HTML 里堆类名。这种方式在大型项目里有用但在这个站里我没用。原因很简单这个站规模小样式复用率不高用原子类反而让 HTML 变得难读。我采用的是语义化类名比如.workshop-card、.hero-title每个类对应一个具体的组件。这样 HTML 干净CSS 也好维护。样式引入方式有三种外链、内嵌、行内。外链适合大部分样式内嵌适合首屏关键样式行内只适合动态计算的样式比如 JS 算出来的位置。我这次 99% 用外链只有加载动画的初始状态用了内嵌因为要保证它在 CSS 文件加载前就生效。6.4 那些只有实际做过才知道的细节最后分享几个我在这个项目里踩出来的经验都是文档里不会写的。第一个图片格式。我一开始用 JPG后来发现作坊实拍图用 WebP 体积能小一半画质还更好。现在浏览器对 WebP 支持已经很好了可以放心用。但记得留 JPG 兜底用picture标签。第二个移动端测试。我一开始只在电脑上测觉得挺好。后来用手机一看导航栏挤成一团。原因是固定 1440px 的容器在手机上会溢出虽然浏览器会自动缩放但体验很差。后来我加了一个简单的媒体查询小屏下容器宽度改成 100%导航改成汉堡菜单。这个改动不大但体验提升明显。第三个表单。联系表单我一开始没做验证用户随便填都能提交。后来加了一个简单的前端验证邮箱格式不对就提示。但要注意前端验证只是提升体验真正的验证必须在后端做前端验证是可以被绕过的。这个站因为是静态的表单直接对接了第三方表单服务验证交给它处理。第四个也是最重要的一个内容比技术重要。我花了很多时间调 CSS 效果但最后让镇上人觉得这个站做得好的是那些作坊的实拍照片和老师傅的口述文字。技术是壳内容是核。如果让我重来一次我会先花更多时间收集内容再动手写代码。这个站上线到现在小半年了镇上几家作坊陆续接到了几个外地询价的电话虽然量不大但至少证明这个门面是有人看的。我自己最大的收获倒不是技术上的而是想明白了一件事写代码这件事最终还是要落到具体的人身上才有意思。给村子做站和给公司做项目技术难度可能差不多但那种这东西真的有人在用的感觉是完全不一样的。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。