返回文章归档

Vibe Coding了一个“朋友圈”

约 9 分钟
技术AI

记录用 Vibe Coding 开发朋友圈动态的过程,与其说是朋友圈,不如说是个人动态。

背景

博客适合写完整内容,比如某个技术点、某次折腾记录、年度总结之类。可平时经常会有一些很零碎的想法,只想简单发一句话、一张图、一个链接,如果专门写成文章又太重,最后大概率就是不写了。

所以就想在网站里加一个类似朋友圈的功能,随手记录一些动态,让这个网站看起来不只是一个文章列表,而是一个更接近日常的个人空间。

这篇文章就简单记录一下这个功能从想法到上线的过程,也算是我第一次比较完整地用 Vibe Coding 写一篇功能开发记录。

为什么做朋友圈动态

其实动机挺简单,主要还是想降低记录成本。

之前写博客会有一种心理负担,一篇文章总得有个主题,有开头有结尾,最好还能讲清楚来龙去脉。但动态就不一样,想到什么就发什么,不需要太完整,也不用非得总结出什么结论。

另外就是现在很多内容都会发在社交平台,但发完之后就散落在各个平台里了。既然已经有自己的站点,那不如把这些轻量内容也放在自己这里,后续回看也方便。

还有一点是想试试 Vibe Coding 能把一个完整功能推进到什么程度。朋友圈动态看起来只是一个列表,但真做起来会涉及发布、图片、点赞、评论、权限、分页、缓存、通知等一堆细节,刚好适合拿来实践。

先做一个能跑的版本

一开始并没有想得特别复杂,目标就是先把最小闭环跑通:能发布,能保存,能展示。

页面入口放在 /pyq,页面主要由 PostCover 和 PostList 两部分组成。PostCover 负责顶部封面和发布入口,PostList 负责动态流展示。

数据这块用的是 Supabase,主要是图省事,数据库和图片存储都能一起解决。表结构也比较直接:

  • pyq_users 用户信息
  • pyq_posts 动态内容
  • pyq_likes 点赞
  • pyq_comments 评论
  • pyq_admin_read_at 管理员已读记录

第一版只要能把动态发出来,其实就已经有点感觉了。

很多功能都是在这个基础上慢慢加的,这点跟一开始想象的不太一样。原本以为做个动态流应该很快,结果越做越发现,朋友圈这种看起来很轻的功能,背后全是细节。

动态流不是简单列表

最开始的动态流确实只是简单列表,按创建时间倒序展示。

跑起来之后发现,如果内容多了,只是一直往下排会有点乱,看不出时间感。所以后面又加了按月份分组,普通动态按月份归类,月份标题固定在列表里,看起来更像时间线。

置顶动态也单独处理了。因为置顶内容不太适合混在月份分组里,不然既要保持置顶,又要参与时间线排序,逻辑会有点别扭。最后的处理方式是置顶动态单独返回,普通动态再走分页和月份分组。

触底加载用的是 IntersectionObserver,滚动到底部自动请求下一页。动态流还是更适合这种交互,不需要用户去点分页按钮。

这里也能感受到 Vibe Coding 的节奏:先让列表出来,再根据真实页面感觉调整。很多时候盯着代码想半天,不如先跑起来看一眼。

图片上传

发布动态支持文字和图片,图片上传到 Supabase Storage,动态里保存图片地址。

上传本身还好,真正容易忽略的是删除。

一开始很容易只想着删数据库记录,但图片已经传到 Storage 了,如果不一起删,时间久了就会留下一堆没人引用的文件。所以删除动态时,也要同步把对应图片清掉。

编辑动态也有类似问题,如果图片发生变化,就要考虑旧图片怎么处理。这个地方不是一开始就设计完整的,而是写着写着发现边界越来越多。

实际做这种功能经常就是这样:第一版先能用,然后再把这些边角补上。要是从一开始就把所有情况都想完,估计功能还没写就先累了。

点赞和评论

朋友圈没有点赞和评论总感觉差点意思,所以后面又补了这两块。

点赞相对简单,点一下请求接口,再更新当前状态。评论稍微麻烦一点,因为评论列表没必要首屏全部加载,尤其动态多了以后会影响性能。

这个问题也是实际用的时候才明显感觉到的。如果每条动态都带着评论一起请求,首屏会做很多没必要的事情。大部分时候用户只是先浏览动态,不一定会展开评论。

最后的处理方式是评论区域懒加载,动态卡片进入可视区域附近时再请求评论。这样首屏只关注动态本身,评论等用户真正看到时再加载。

这类优化单独看都不难,但很难在第一天就全想出来。页面跑起来之后,哪里慢、哪里别扭、哪里多余,才会变得很明显。

公开和私有

做个人动态时会遇到一个问题:有些内容适合公开,有些只想自己记录。

所以动态加了 public 和 private 两种可见性。普通访问者只能看到公开动态,管理员可以看到全部内容。

这个功能对我来说挺重要,因为它让朋友圈动态不只是一个公开展示页,也可以当成自己的轻量记录工具。有些内容没必要给所有人看,但又不想另外找地方记。

管理员相关操作包括发布、编辑、删除、置顶、查看私有动态等。接口层会校验管理员密码,校验通过后才返回完整数据。

权限这类东西还是要谨慎一点,AI 可以帮忙写接口,但哪些数据能返回、哪些操作必须校验,还是得自己盯着。

通知是后来才加的

一开始其实没打算做通知。

评论功能做好之后才发现,如果没人提醒,我自己也不一定知道有人评论了动态。于是又加了通知 banner、历史记录和已读状态。

到这一步,朋友圈动态已经不只是一个展示页面了,基本有了简单后台的感觉。虽然没有单独做后台页面,但发布、编辑、删除、置顶、通知这些能力都在页面里完成了。

这也是这类功能容易“长出来”的地方。你以为只是加个评论,评论加完又会自然想到通知;通知有了又要有已读;有已读又要能看历史。功能之间会互相牵引。

首屏缓存

动态流最明显的优化是首屏缓存。

使用 sessionStorage 保存一份 feed 快照,再次进入页面时可以先展示缓存内容,然后再请求最新数据。缓存带了版本号和过期时间,避免后续数据结构变化导致旧缓存出问题。

这个优化对体验提升挺明显,尤其是从其他页面返回动态页时,不会一直空白等接口返回。

一开始没做缓存时,页面不是不能用,但会有一点“等一下”的感觉。加了缓存之后,至少视觉上会更连贯。

Vibe Coding 的感受

这次开发很明显感受到 Vibe Coding 的优势:不用一开始就把所有细节想完,可以先描述一个大概方向,然后快速得到一个能跑的版本。

比如最开始只是“做一个朋友圈动态”,跑起来后发现需要分页;分页有了之后发现需要缓存;评论有了之后发现需要通知;图片能上传后又要考虑删除清理。

很多需求不是提前设计出来的,而是在使用过程中冒出来的。

以前写这种功能,我可能会先纠结表怎么设计、组件怎么拆、接口怎么分。现在更多是先把需求描述清楚,让 AI 起一版,我再根据页面效果一点点改。

但也不能完全放手。AI 有时候会把简单问题写复杂,也会漏掉一些只有实际使用才会发现的边界,比如图片删除、评论加载、管理员视角这些。它更像是把实现速度提上来,但最终方向和取舍还是要自己判断。

这次最明显的感受是:Vibe Coding 不是让人不思考,而是让试错成本变低。想法可以很快变成页面,然后再根据真实体验继续修。

开发结果

目前朋友圈动态已经包含这些能力:

  • 发布图文动态
  • 动态列表展示
  • 置顶动态
  • 按月份分组
  • 触底加载更多
  • 点赞
  • 评论
  • 图片上传和删除
  • 公开 / 私有动态
  • 管理员编辑和删除
  • 评论通知和历史记录
  • 首屏缓存

技术上主要用到:

  • Next.js App Router
  • Route Handlers
  • Supabase
  • React Query

从结果看,它已经不是一开始想的“加个动态列表”了,而是一个围绕个人记录展开的小型动态系统。

总结

这次开发朋友圈动态,最开始只是想给博客加一个轻量记录入口,最后做着做着变成了一个完整功能。

博客适合沉淀,动态适合记录当下。对我来说,这个功能补上了个人网站里比较生活化的一块。

通过这次实践,对 Vibe Coding 的感受也更明确了:它很适合这种从模糊想法开始、边做边调整的功能开发。先把东西做出来,再在真实体验里不断修正,比一直停留在设计阶段更有效。

当然,AI 写代码很快,但文章和产品一样,最后还是要回到自己的表达和判断上。功能能不能用、体验顺不顺、内容是不是像自己写的,这些都得自己把关。