Vibe Coding实践:周末用Next.js+Supabase打造个人简历管理系统

Vibe Coding实践:周末用Next.js+Supabase打造个人简历管理系统
1. 从“周末项目”到“简历管家”一个开发者的效率革命上周五晚上我盯着自己那份躺在硬盘角落、尘封了近两年的简历PDF突然意识到一个尴尬的现实每次求职或者想更新履历我都得重新打开那个陈旧的Word文档手动调整格式、补充项目、计算时间线整个过程繁琐且容易出错。更麻烦的是我手头还有几个朋友托我帮忙看看他们的简历格式五花八门信息更新不及时。一个念头冒了出来为什么不能有一个轻量、专注、完全由我自己掌控的简历维护系统它能让我和朋友们在一个地方集中管理简历信息一键生成不同风格的PDF甚至能追踪投递记录。这个想法并不新鲜市面上有无数在线的简历制作工具。但作为一个开发者我对那些需要注册、有订阅费用、并且数据存在别人服务器上的工具总有些抗拒。我想要的是完全的控制权数据在我自己的服务器甚至本地界面简洁到极致功能直击痛点——就是增删改查简历内容然后导出。按照传统的开发流程从设计数据库、搭建后端API、到编写前端界面和实现PDF生成没个一两周根本下不来周末两天想都别想。直到我尝试了最近在开发者圈子里热度颇高的Vibe Coding。它被许多人描述为一种“心流编码”或“氛围编码”的实践核心不在于某个具体的框架或工具而是一种高度聚焦、工具链深度整合、以结果为唯一导向的开发状态。简单说就是摒弃一切不必要的仪式感比如过度设计、纠结技术选型用最顺手、最高效的工具组合直奔最终可运行的产品。我决定用这个周末亲身实践一次“Vibe Coding”目标是周日晚上一个能跑起来的简历系统必须上线。2. Vibe Coding 心法极简主义的技术选型与组合拳Vibe Coding 不是魔法它不会自动生成代码。它的威力在于决策效率。在项目开始的头一个小时里我不再纠结于“用React还是Vue”、“后端是Go还是Node.js”而是快速问了自己几个问题并基于答案锁定了技术栈核心需求是什么管理简历数据CRUD、生成PDF。不需要实时协作不需要复杂权限。如何最快实现交互界面我需要一个能快速搭建表单、表格并且美观的UI框架。Shadcn/ui或基于Tailwind CSS的组件库是首选因为它们提供的是可直接复制粘贴的组件代码无需安装庞大的npm包风格现代且可定制性极强。如何最快实现后端逻辑和数据库为了极致简化我决定采用“全栈框架”思路。Next.js (App Router)成了不二之选。它允许我在同一个项目里写React前端和API路由内置了路由、渲染优化并且部署到Vercel等平台简单到令人发指。数据库方面为了免去自己搭建数据库服务的麻烦我选择了Supabase或Vercel Postgres。它们提供了云端的PostgreSQL数据库并有非常友好的JavaScript/TypeScript SDK从建表到查询几行代码就能搞定。如何生成PDF这是一个关键点。在浏览器端生成PDF体验好但库可能较重在服务端生成更稳定。我选择了react-pdf/renderer。这个库允许我使用React组件的方式来“声明式”地描述我的PDF文档结构就像写JSX一样然后在Node.js环境即Next.js的API路由中渲染成PDF文件。这种方式将UI设计和PDF生成完美统一维护起来特别方便。如何部署Vercel。它与Next.js是天作之合支持自动从Git仓库部署并提供预览环境、自动SSL证书。我写完代码git push一下几分钟后产品就上线了。这个选型过程可能只花了15分钟。没有画架构图没有写设计文档。Vibe Coding的核心心法就是基于最熟悉、社区最活跃、集成最顺畅的工具组合出一套能跑通最小闭环的“特遣队”。任何在这个闭环之外的技术诱惑比如“要不要试试新的状态管理库”都被我刻意忽略了。3. 核心实现从数据模型到一键生成的完整链路确定了“特遣队”接下来就是实现。我按照功能模块以“实现-测试-迭代”的微循环推进。3.1 定义数据模型Supabase表的五分钟设计简历数据相对结构化。我在Supabase控制台快速创建了一张profiles表用于存用户基本信息姓名、邮箱、电话等和一张resume_items表用于存工作经历、教育背景、项目经验等。表结构设计力求简单-- profiles 表 id (uuid, primary key) full_name (text) email (text) phone (text) linkedin_url (text) github_url (text) -- 其他基本信息... -- resume_items 表 id (uuid, primary key) profile_id (uuid, foreign key - profiles.id) item_type (text) -- ‘work’, ‘education’, ‘project’, ‘skill’ title (text) subtitle (text) -- 如公司名、学校名 description (text) -- 详细描述支持Markdown start_date (date) end_date (date) -- 可为空表示“至今” sort_order (integer) -- 用于自定义排序这里的一个Vibe Coding技巧是不过度设计。我没有把技能单独拆表而是用item_typeskill来区分描述字段里用逗号分隔技能项。初期够用就行复杂度是后来长出来的不是一开始设计进去的。3.2 构建管理后台Next.js Shadcn/ui 的闪电开发在Next.js项目中我使用npx shadcnlatest add button card dialog form input ...命令快速添加了所需的UI组件。然后在/app/dashboard/page.tsx下我开始搭建管理界面。数据获取在服务端组件中直接使用Supabase的Server Client获取当前用户的简历数据。得益于Next.js的Server Component我可以在组件函数顶部直接await数据库查询代码简洁安全。表单构建使用Shadcn/ui提供的Form、Input、Textarea、Button组件配合react-hook-form进行表单管理。为resume_items设计了一个动态表单可以添加、删除、排序多条经历。状态同步为了获得即时反馈的体验我使用了Optimistic Updates乐观更新。当用户点击“保存”时前端界面立即显示更新后的数据同时向后端发起请求。如果请求失败再回滚界面状态并提示错误。这个小小的技巧极大地提升了操作流畅感是Vibe Coding中注重用户体验的体现。// 示例乐观更新工作经历 const [items, setItems] useState(initialItems); const { mutate: updateItem } useMutation({ mutationFn: (updatedItem) api.updateItem(updatedItem), onMutate: async (newItem) { // 1. 在请求发出前立即更新本地状态 const previousItems items; setItems(items.map(item item.id newItem.id ? newItem : item)); return { previousItems }; }, onError: (err, newItem, context) { // 2. 如果失败回滚到之前的状态 setItems(context.previousItems); toast.error(更新失败); }, // onSuccess: 可选如果需要处理成功后的额外逻辑 });整个管理后台的页面大约只花了周六一个下午就完成了核心的增删改查和列表展示。界面清爽操作跟手。3.3 PDF生成引擎用React写PDF的艺术这是最有趣也最具挑战的一环。我在/app/api/generate-pdf/route.ts创建了一个API路由。设计模板组件我创建了一个ResumePDFDocument.tsx组件。这个组件不渲染在浏览器里它只被react-pdf/renderer使用。它接收profile和items作为props内部使用PDF库提供的Document,Page,View,Text,Image等组件来布局。这就像是在用React写一个打印专用的视图层。// ResumePDFDocument.tsx import { Document, Page, Text, View, StyleSheet } from react-pdf/renderer; const styles StyleSheet.create({ page: { padding: 30 }, name: { fontSize: 24, fontWeight: bold }, section: { marginBottom: 15 }, }); const ResumePDFDocument ({ profile, items }) ( Document Page sizeA4 style{styles.page} Text style{styles.name}{profile.full_name}/Text {/* 渲染联系方式、经历等 */} {items.map(item ( View key{item.id} style{styles.section} Text{item.title} {item.subtitle}/Text Text{item.description}/Text /View ))} /Page /Document );API路由实现在API路由中我查询数据库获取数据然后使用pdf对象的renderToStream方法将React组件渲染成PDF流最后通过Response返回。// app/api/generate-pdf/route.ts import { NextRequest } from next/server; import { renderToStream } from react-pdf/renderer; import ResumePDFDocument from /components/ResumePDFDocument; import { getProfileData } from /lib/supabase; export async function GET(request: NextRequest) { const profileId request.nextUrl.searchParams.get(profileId); const { profile, items } await getProfileData(profileId); const pdfStream await renderToStream( ResumePDFDocument profile{profile} items{items} / ); return new Response(pdfStream, { headers: { Content-Type: application/pdf, Content-Disposition: attachment; filename${profile.full_name}_Resume.pdf, }, }); }前端触发在管理后台一个“导出PDF”按钮直接链接到这个API端点或者用fetch调用后通过Blob对象触发浏览器下载。踩坑实录react-pdf/renderer的样式系统是自有的不完全等同于CSS。特别是布局它主要依赖Flexbox但属性名是驼峰式如flexDirection。最初我按Web CSS来写导致布局错乱。解决办法是仔细阅读其样式文档并先在浏览器中用类似的div结构模拟PDF布局确认后再移植到PDF组件中。3.4 身份认证与数据隔离轻量而安全的方案虽然初期可能自用但考虑到要给朋友用基础的安全和隔离必须有。我继续利用Supabase它内置了完整的身份认证系统。启用Supabase Auth在控制台启用邮箱密码登录或第三方登录如GitHub。集成到Next.js使用supabase/ssr包和Next.js的Middleware可以轻松实现服务端和客户端的认证状态同步。我创建了一个/app/auth目录来处理登录/注册页。数据关联在profiles表中增加一个user_id字段与Supabase Auth的用户ID关联。所有的数据库查询都加上where user_id auth.uid()的条件这样就天然实现了数据隔离用户只能看到和操作自己的简历数据。这部分花了周六晚上的一些时间但Supabase的文档和示例非常清晰集成过程基本是“复制-粘贴-微调”。4. 效率提升的关键那些“少即是多”的开发决策回顾整个开发过程真正让我在两天内完成系统的不是写了多少行酷炫的代码而是做对了一系列“不做”和“简化”的决策。放弃状态管理库这个应用的状态非常简单表单数据、列表数据React的useState和useContext完全够用。引入Redux或Zustand只会增加复杂度。放弃独立的API服务器Next.js的App Router将API路由和页面路由统一省去了配置CORS、管理两个服务器进程的麻烦。开发体验高度统一。使用云数据库服务DBaaS自己搭建和维护PostgreSQL哪怕是Docker也会消耗宝贵的时间。Supabase/Vercel Postgres让我在5分钟内就拥有了一个可用的、带管理后台的数据库。CSS方案锁定Tailwind无需在不同的CSS方案间切换。Tailwind的实用性优先类名让我在调整边距、颜色、排版时速度极快几乎不需要在CSS文件和组件文件间跳转。部署流程自动化连接GitHub仓库到Vercel设置自动部署。每次git push后我不需要手动构建、上传、重启服务。这节省了巨大的心智负担和时间让我可以专注于代码本身。这些决策共同构成了Vibe Coding的实践选择那些能让你忘记“工具存在”的工具。它们不应该成为你思考的负担而应该像空气和水一样自然让你全部的注意力都集中在解决实际问题上。5. 从周末原型到可分享的产品后续优化思路周日晚上系统基本功能全部跑通。我用自己的简历数据测试了增删改查和PDF生成一切顺利。但这只是一个MVP最小可行产品。如果我想把它变成一个真正可长期使用、甚至分享给更多人的工具还有一些方向可以优化多模板支持目前的PDF模板只有一种风格。可以抽象出模板系统让用户选择不同的主题经典、现代、创意等。这需要将ResumePDFDocument组件进一步模块化通过配置来驱动样式和布局。简历版本管理很多时候我们针对不同职位需要微调简历。可以增加“复制一份简历”并稍作修改的功能形成不同的版本方便管理和投递。投递记录追踪在系统内增加一个简单的模块记录简历投递的公司、职位、日期、状态已投递/面试中/已拒绝等让求职过程更可视化。性能与缓存PDF生成是CPU密集型操作。可以考虑对生成的PDF进行缓存例如在用户保存简历后后台预生成一次PDF并存储到对象存储如Supabase Storage或Vercel Blob中当用户再次下载时直接返回缓存文件提升响应速度。离线支持与PWA考虑到有时可能在网络不好的环境下使用可以将其改造为渐进式Web应用PWA利用Service Worker缓存关键资源实现基本的离线查看和编辑。不过这些都属于“锦上添花”。Vibe Coding教会我最重要的一课是先做出一个能解决核心问题的、可用的东西比规划一个完美无缺但永远做不出来的东西重要一万倍。这个周末项目让我不仅收获了一个实用的私人工具更体验了一种高效、愉悦的开发节奏。下次再有一个小想法时我知道一个周末的时间或许真的足够了。

最新新闻

日新闻

周新闻

月新闻