返回项目列表 YSKM523 / lakebbs-ca

lakebbs

面向 Thunder Bay、Sudbury 和北安省小城市的城市感知中文本地信息平台 —— 近期整体重写到 Next.js 16 + Drizzle,加入每日聚合 bot 和面向 AI 搜索的 GEO landing。

Live · 近期重写 Founder · 核心开发者 最后更新: 2026年5月16日

背景

北安省小城市(Thunder Bay、Sudbury 等)的中文社区,租房 / 工作 / 二手 / 移民 / 本地知识基本都沉在 WeChat 群里。微信是好用的聊天客户端,但不是合格的信息载体:搜不到、不能分类、群满了新人看不到历史,Google 也索引不进去。

lakebbs 把这些信息当作一等公民,而不是流。这不是一个论坛克隆,是一个介于论坛、二手市场、租房板、移民指南之间的 城市感知中文本地信息平台

首页 —— 城市感知 feed,混合用户帖、每日租房 / 工作 / Reddit digest、移民简报、最赞侧栏。
首页 —— 城市感知 feed,混合用户帖、每日租房 / 工作 / Reddit digest、移民简报、最赞侧栏。
分类页 —— /thunderbay/realEstate。每日聚合自 Kijiji 等源的租房信息 + 用户转租 / 出租帖。
分类页 —— /thunderbay/realEstate。每日聚合自 Kijiji 等源的租房信息 + 用户转租 / 出租帖。
帖子详情 —— 长文本地指南 + 点赞 / 收藏 / 评论 + 「相关推荐」。
帖子详情 —— 长文本地指南 + 点赞 / 收藏 / 评论 + 「相关推荐」。
GEO landing —— /landing/thunderbay-rent。租金中位数、区域指南、安省租约规则、面向 AI 搜索引擎的 FAQ schema。
GEO landing —— /landing/thunderbay-rent。租金中位数、区域指南、安省租约规则、面向 AI 搜索引擎的 FAQ schema。
移动端 —— 顶部 bar + 底部导航。
移动端 —— 顶部 bar + 底部导航。

方法

城市作为 namespace,不是 tag

所有 surface 用 /[city]/[section] 路由。Thunder Bay 的租房和 Sudbury 的租房是不同的 feed、不同的 SEO target、不同的 landing 页面。一个城市的内容不会污染另一个,「Thunder Bay 租房」这样的查询能命中真实页面,而不是一个通用的全国页。

每日聚合 bot 解决冷启动

社区产品最难的是冷启动——空 feed 直接劝退留存。lakebbs 用一套每日运行的私有聚合 bot 解决这件事:

  • 租房 digest —— Kijiji + 其他源,抓取、去重、推到 /[city]/realEstate
  • 工作 digest —— LinkedIn / Kijiji / 雷湾市政府岗位
  • IRCC 移民每日简报 —— 加拿大移民资讯的中文整理
  • r/ThunderBay digest —— Reddit 当日热帖翻译 + 精选评论

这让 lakebbs 变成「每天可开」的页面,而不是 request-response 的论坛。即使用户基数不大,页面每天都有新内容。

GEO landing —— 为 AI 搜索而非只是 Google 做的

专门的 landing 页面(/landing/thunderbay-rent、移民、RNIP、Lakehead 等)把本地知识沉淀成长期可发现的资产。产品把 Generative Engine Optimization 当成和传统 SEO 同等重要的事:

  • 动态 sitemap.xml:root + 城市 + 分类 + landing + 最新 5K 帖子(1 小时 revalidate)
  • 动态 robots.txt:显式 AI 爬虫白名单 + Bytespider crawl-delay
  • landing 页有结构化数据 + OG + FAQ schema
  • 后台有 GEO 就绪度 checklist 和被引用 tracking —— 看真实是否被 AI 搜索引擎采用

这是产品防御性的来源:Google 索引一个城市论坛是常规操作,被某 LLM 在「Thunder Bay 该租哪」时引用 才是稀缺的。

技术栈整体重写(数据库保留)

lakebbs 起步是 Vue 2 + Express + Sequelize。现已迁到现代 TypeScript 栈,没动数据库。MySQL 5.7 schema 保持不变,Drizzle ORM 直接对它建模。

现在
框架Next.js 16 (App Router)
UIReact 19, Server Components + Server Actions
样式Tailwind 4, Base UI, shadcn
数据Drizzle ORM 对接现有 MySQL 5.7
认证NextAuth v5 (credentials + session)
部署systemd lakebbs-next.service on :3477,nginx 反代

栈重写时锁住数据库,是无趣但正确的选择——这把迁移变成一个纯代码项目,而不是数据项目。线上切换零 schema 变更、用户侧零可感知 downtime(只是 nginx reload)。

产品 surface

  • 6 个标准分类的城市感知论坛(新鲜事 / 资讯 / 二手 / 房产 / 汽车 / 工作移民),支持图片画廊
  • 长文本地指南与短帖并存(租房片区指南、移民 playbook、考证记录)
  • 点赞 / 收藏 / 评论(最新 / 最热 / 最早三种排序),帖子详情底部「相关推荐」
  • 1:1 私信,会话级 block / archive,站内通知中心
  • 用户主页:关注 / 取关 / 黑名单
  • 全站全文搜索
  • 后台仪表盘:地理受众分布、各 AI 爬虫活动 (PV / 末访 / 用途)、GEO 就绪信号

结果与教训

在生产环境运行:lakebbs.ca,覆盖 Thunder Bay、Sudbury 和北安省其他小城市。

低估的事:社区产品很大一部分就是「在第零天让页面看起来活的」。一个分类全空的论坛,设计再好也像死的。每日聚合 pipeline 起初被当作「锦上添花的内容自动化」——结果它是 load-bearing 组件。没有它,SEO landing 没东西指过去,回访用户看到的是昨天那批帖子。

第二件事:城市作为 namespace 是最值得防御的架构决定。Tag 会输。一个用户用「多伦多 xxx」搜进来,落到一个 Thunder Bay 论坛上立刻跳出;落到 /thunderbay/realEstate 上就找到他要的。SEO 和产品体验在这件事上指同一方向。

栈重写也是 scope 的教训。一开始有冲动「既然都重写了,schema 也顺手优化一下」——我没做。MySQL 5.7 保持,表结构保持,Drizzle 对接,只重写真正需要现代化的那几层。结果迁移用了几周,而不是几个月。

完整说明见 英文版