Cinematic Portfolio
单页作品集,深色基调,灵感来自剪辑师和VFX艺术家的作品集:人物照片后方有一个巨大的水印文字,姓名显示在前方,标题为双色设计(白色+强调色)。页面加载时,30个AI代理会逐步构建各个模块(技能agent-build-effect,已内置于template/vendor/中)。
template/
index.html 页面框架,无需修改
data.js 所有内容,只需修改此文件
styles.css 界面样式;可通过CSS变量或`data.js`中的`accent`更改颜色
portfolio.js 从data.js构建页面,然后启动代理效果
vendor/ agent-build.js + .css
assets/ 抠图人物照片 + 技能卡片图片(示例:6张深色/红色图片)
scripts/cutout.py 人物照片抠图(rembg)
references/image-prompts.md 技能卡片图片提示词,风格统一
工作流程
1. 在制作前询问足够信息
一次性简洁询问用户尚未提供的内容:
- 用于大号显示的简短名称(最好是一个单词),全名,职位,一句话介绍。
- 人物照片:半身或全身照,背景不要太杂乱,稍微侧身。真人照片或3D渲染图均可。
- 3到6个想要展示的技能或项目(名称、一句话描述、技术栈)。如果有真实项目及链接,请为卡片设置
href。 - 职业历程(工作经历、教育背景)、技能、工作流程、引用语。
- 荣誉或媒体报道(如果没有,则省略整个部分)。
- 联系方式:电子邮件、所在地区、号召性按钮。
- 页面语言、强调色(默认为红色
#ff3b30)、水印文字(默认为PORTFOLIO)。
不要编造数据、奖项或媒体报道。如果用户没有某个部分,请从data.js中删除该部分,页面将自动隐藏该模块。
2. 复制模板
将整个template/文件夹复制到用户指定的位置(例如./my-portfolio/)。请勿修改技能中的原始模板。
3. 人物照片抠图
pip install rembg pillow
python -I <skill>/scripts/cutout.jpg original-photo.jpg my-portfolio/assets/photo.webp
默认模型isnet-general-use较轻量(约180 MB,只需下载一次)。仅在机器内存充足时尝试birefnet-portrait:此模型约1 GB,并且曾在1440px图片上出现内存不足的情况。在灰色背景上检查一次(使用PIL合成灰色背景后读取图片)。必须保留头发、眼镜和手持物品。将hero.photo设置为assets/photo.webp。
4. 技能卡片图片
模板已提供6张深色/红色图片(代理、自动化、Web、聊天机器人、电子表格、视频)。如果与卡片内容匹配,可直接复用。如果需要自定义图片,请按照references/image-prompts.md操作:保持风格风格后缀不变,仅更改主体。如果更改强调色,请同时更改提示词中的颜色代码。在批量生成图片前询问用户(会消耗他们的账户额度)。
如果没有匹配的图片,请移除该卡片的image字段,卡片仍会美观地显示(无图)。不要对两个内容不同的卡片使用同一张图片。
5. 填写data.js
hero.name:一个单词,自动转为大写。名称超过7个字符,请在.pf-name中减小字号。hero.stats:仅填写真实数据(技能数量、工作年限、技术栈数量等)。- 章节标题包含
title(白色)和accent(强调色)。两部分应简短有力:"Not just code." / "Solutions that run." agents.labels:根据页面语言翻译。例如中文:{ status: "{agents}个代理 · {edits}次修改", building: "正在构建页面", done: "构建完成", skip: "跳过" }。- 文本通过
textContent插入,因此无法嵌入HTML(这是有意为之,以保证安全性)。
6. 检查(先检查数字,后检查图片)
直接在浏览器中打开index.html(file://协议即可运行)或运行任意静态服务器。使用Playwright在1440×900和390×844分辨率下,附加?agents参数:
({
sections: document.querySelectorAll(".pf-section").length,
overflowX: document.documentElement.scrollWidth > innerWidth, // 必须为false
photo: document.querySelector(".pf-photo img")?.naturalWidth, // > 0
waiting: document.querySelectorAll('[data-ab="wait"]').length, // 滚动完成后应为0
})
使用window.scrollTo每次滚动600像素,每步等待约1秒,然后检查waiting是否为0且控制台无错误。在每个分辨率下拍摄一张英雄区域截图以评估视觉效果。注意:介绍文字不应遮挡人物,在手机上脸部不应被文字覆盖。
7. 部署上线
项目文件夹为静态网站:可拖拽到Netlify Drop、vercel deploy、GitHub Pages或Cloudflare Pages。无需构建步骤。
集成到现有Next.js / React项目中
复用styles.css,将:root改为.pf。将渲染部分重写为服务端组件,保持类名不变。使用技能agent-build-effect中的AgentBuild.tsx附加效果,targets列表与portfolio.js中的相同。制作Next版本时已遇到以下问题:
- 固定头部:为页面设置负的
margin-top(等于头部高度),使英雄区域能够穿透到头部下方。 next/image使用fill时,父容器需要设置position: relative,否则图片会覆盖整个页面。- Anton字体包含越南语字符集。自行托管时,需加载latin、latin-ext、vietnamese三个子集。
- Turbopack开发服务器有时会错过通过
sed修改的CSS更改。使用编辑工具或直接写入文件,它才能识别更改。