基于 SpacetimeDB 构建全功能实时聊天应用12 项核心功能的评分报告与源码级实现解析【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB导读本文以 SpacetimeDB 仓库中tools/llm-oneshot评测框架生成的一份聊天应用评分报告为核心完整还原一个 Discord 风格实时聊天应用的 12 项核心功能基础聊天、输入指示、已读回执、未读计数、定时消息、阅后即焚、表情回应、编辑历史、实时权限、富用户状态、消息线程、私密房间与私信的设计与实现。文中将评分报告中的每一项结论与仓库内真实源码backend/spacetimedb/src/schema.ts、reducers.ts及前端client/src/App.tsx逐一对齐读者可以借此掌握 SpacetimeDB TypeScript 模块的表定义、reducer 编写、定时任务调度、前端订阅等完整实战链路。一、评测背景一份满分 36/36 的聊天应用该评分报告记录了 Claude Opus 4.5 使用提示词09_spacetime_private_rooms.md第 9 级私密房间与私信生成的聊天应用评测结果应用源码完整保存在同目录下GRADING_RESULTS.md评分报告README.md应用说明与部署步骤后端模块backend/spacetimedb/schema.ts、reducers.ts、index.ts前端客户端client/React Vite SpacetimeDB React SDK总体指标一览指标值使用的提示词级别9Private Rooms and DMs评估功能范围1–12该级别上限功能总得分36 / 36编译通过无错误运行正常无崩溃后端代码量约 650 行前端代码量约 750 行创建文件数11 个外部依赖spacetimedb后端、react、react-dom、spacetimedb客户端、vite值得注意的是“首次尝试成功率”一项报告标注了一次修复t.product()SDK 缺陷其余全部一次通过全程0 次重新提示reprompt。评测的评分体系本身定义在 grading_rubric.md 中每个功能按 0–3 分评估0 未实现或完全损坏1 部分实现且有重大问题2 基本可用但有次要缺陷3 完全符合规格且只对提示词级别内包含的功能计分——第 9 级包含功能 1–12满分即为 36 分。二、数据模型12 张表支撑全部功能评分报告指出“全部 12 张表定义在schema.ts中”。查看 schema.ts 源码这些表可以按职责分为四组1. 用户与房间基础表user表以t.identity()为主键记录name可选、online在线状态、statusonline | away | dnd | invisible四档支撑功能 10 富用户状态、lastActive最后活跃时间戳以及connectionId连接标识。room表房间主表id自增主键包含name、creatorIdentity创建者、createdAt以及两个关键布尔字段isPrivate私密房间不进入公共列表与isDm双人私信房间并建立了by_is_privateB-tree 索引。room_member表房间成员关系字段isAdmin管理员、isBanned被禁言标记支撑功能 9 实时权限、lastReadMessageId记录每个用户在每个房间的最后已读消息 ID支撑功能 4 未读计数并建立by_room、by_user两个索引。room_invitation表私密房间邀请记录status字段取值pending | accepted | declined支撑功能 12 的邀请接受/拒绝流程。2. 消息相关表message表主消息表除roomId、senderIdentity、content、createdAt外还有parentMessageId可选消息线程关联为null表示顶层消息支撑功能 11 线程isEphemeral与expiresAt可选阅后即焚标记与过期时间支撑功能 6索引by_room、by_sender、by_parent。message_edit表编辑历史记录previousContent与editedAt支撑功能 8 的“(edited)”标识与历史回看。reaction表表情回应messageIduserIdentityemoji三元组支撑功能 7。read_receipt表已读回执记录messageId、userIdentity、readAt支撑功能 3 的“Seen by X, Y, Z”显示。3. 定时任务表SpacetimeDB scheduled tables 核心用法这是最能体现 SpacetimeDB 能力差异化的部分——表本身即可声明定时 reducer行插入时由scheduleAt指定触发时间到期后自动执行对应 reducer表关联定时 reducer用途间隔typing_indicatorexpire_typing输入指示 5 秒后自动过期5sscheduled_messagesend_scheduled_message定时消息到期投递用户指定ephemeral_message_cleanupdelete_ephemeral_message阅后即焚消息到期物理删除1min/5min/1haway_status_jobcheck_away_status空闲检测5 分钟未活跃自动置为 away5min4. 架构决策小结评分报告中的架构决策在源码中逐条得到印证12 张表集中在schema.ts约 220 行通过schema(User, Room, RoomMember, ...)汇总导出25 个 reducer 集中在reducers.ts约 430 行index.ts仅 4 行负责导入 schema 与 reducers 并导出spacetimedb模块前端为单文件 React 组件App.tsx约 680 行styles.css750 行暗色赛博朋克配色定时清理类任务全部交给 SpacetimeDB 调度不依赖外部 cron 或定时器。三、功能逐项拆解评分要点与源码实现对照功能 1基础聊天3/3set_namereducer显示名设置50 字符上限空名拒绝SenderError(Name cannot be empty)create_roomreducer创建房间支持isPrivate公开/私密选项创建者自动以管理员身份加入join_room/leave_room成员关系增删重复加入、被禁言用户会被拒绝send_messagereducer2000 字符上限空消息拒绝发送前校验成员身份在线面板展示带状态指示的用户列表空名、重复成员、被禁言用户等均有校验分支。功能 2输入指示3/3后端通过定时表typing_indicator实现 5 秒自动过期start_typing先删除该用户在该房间的旧指示再插入新行stop_typing立即删除expire_typing定时 reducer 到期后由调度器自动删除行。前端按房间过滤、排除本人后显示单复数文案“User is typing...” / “Multiple users are typing...”。功能 3已读回执3/3mark_message_readreducer 写入read_receiptmessageIduserIdentityreadAt并顺带推进RoomMember.lastReadMessageIdUI 在消息下方展示“Seen by X, Y, Z”阅读人数较多时折叠为“Seen by N people”并显示迷你头像。功能 4未读计数3/3前端getUnreadCount辅助函数将当前lastReadMessageId与房间内消息 ID 逐条比较未读消息数显示为房间列表项上的红色徽标mark_room_readreducer 在进入房间时把lastReadMessageId推进到该房间最新消息实现实时归零。功能 5定时消息3/3schedule_messagereducer 接收scheduledTimeMs先校验“必须晚于当前时间”再换算为微秒级延迟以ScheduleAt.interval(delayMicros)写入scheduled_message表到期由send_scheduled_message定时 reducer 落成真实message行发送前还会复查成员资格被移出房间则放弃投递。作者可在待发面板看到自己待发送的消息并随时cancel_scheduled_message取消仅限本人。功能 6阅后即焚消息3/3send_message支持isEphemeralephemeralDurationSecsUI 提供 1 分钟 / 5 分钟 / 1 小时三档时长expiresAt由“当前时间 时长×1e6 微秒”计算前端每秒刷新倒计时。到期后delete_ephemeral_message定时 reducer 不仅删除消息本体还级联清理其 reactions、read receipts、edit history保证“永久删除”。功能 7消息表情回应3/3toggle_reactionreducer 先查reaction.by_message若该用户已对该 emoji 存在记录则删除取消否则插入内置 8 个 emoji ❤️ 。前端悬停显示谁点过赞自己的回应高亮。功能 8编辑消息与历史3/3edit_messagereducer 含所有权校验只能编辑自己的消息编辑前把旧内容写入message_edit表再把message.content更新为新内容并置isEdited: true。前端显示“(edited)”徽标点击 按钮弹出历史记录弹窗所有改动经 SpacetimeDB 订阅实时同步给所有查看者。功能 9实时权限3/3房间创建者在create_room时即以isAdmin: true加入kick_user删除目标成员行——由于客户端按成员关系过滤被踢用户立即失去 UI 访问权且不再收到更新ban_user将isBanned置位后续send_message、join_room等 reducer 的成员校验都会拦截被禁用户promote_to_admin提升其他成员为管理员三个权限 reducer 均先校验操作者isAdmin非管理员抛出SenderError(Only admins can ...)。功能 10富用户状态3/3set_statusreducer 只接受[online, away, dnd, invisible]四档lastActive在各类操作中随updateActivity(ctx)刷新away_status_job定时表 check_away_status定时 reducer在线用户超过 5 分钟AWAY_THRESHOLD_MS 300000000n微秒未活动且状态为online时自动改为away并继续为仍在线用户重新排程前端以绿/黄/红/灰四色状态点区分离线用户显示“Last active X minutes ago”。功能 11消息线程3/3message表的parentMessageId可选字段承载父子关系send_message校验父消息存在且与回复同房间回复按钮设置replyingTo状态父消息显示“ N replies”与预览线程视图按“父 子”过滤渲染返回按钮回到主视图。功能 12私密房间与私信3/3create_room对话框含私密房间勾选项isPrivate为 true 的房间不进入公共列表invite_to_room按用户名邀请仅管理员可操作去重已有成员与 pending 邀请respond_to_invitation支持接受/拒绝接受则自动插入成员行start_dm创建恰好两个成员、双方皆管理员的isDm: true房间并查重避免重复建立相同私信所有消息类 reducersend_message、schedule_message、start_typing、mark_message_read、toggle_reaction都在入口处做成员资格检查从服务端保证只有成员能看到私密内容。四、定时 reducer 机制客户端零轮询的实时底座评分报告“Architecture Decisions”一节反复强调 scheduled reducers 的四个用途。在 SpacetimeDB 中定时 reducer 的注册方式非常简洁——在 schema.ts 的表声明中通过scheduled: reducer_name字段关联表行携带scheduledId主键与scheduledAt: t.scheduleAt()在 reducers.ts 中对应 reducer 以{ arg: Xxx.rowType }为参数接收被调度的行。以输入指示过期为例其完整生命周期是用户输入时调用start_typing插入scheduledAt: ScheduleAt.interval(5000n * 1000n)5 秒换算为微秒的typing_indicator行到期后调度器执行expire_typingreducer函数体为空因为行在 reducer 完成后由系统自动删除若用户在 5 秒内持续输入前端反复调用start_typing每次先删旧行再插新行形成“续期”效果。同理send_scheduled_message在投递前重新校验成员资格、delete_ephemeral_message在删除前级联清理关联行、check_away_status在检查后为仍在线用户重新排程——这些“到期复查”逻辑避免了定时器触发时状态已经失效的问题是值得复用的设计模式。五、前端实时集成React SDK 与订阅前端入口 main.tsx 展示了标准的连接流程用DbConnection.builder()链式配置withUri(SPACETIMEDB_URI)、withModuleName(MODULE_NAME)、withToken(localStorage auth_token)注册onConnect/onConnectError回调连接成功后调用conn.subscriptionBuilder().subscribeToAllTables()订阅全部表通过SpacetimeDBProvider connectionBuilder{builder}包裹App /token 持久化到localStorage401/Unauthorized时清除 token 并刷新页面。连接参数集中在 config.tsMODULE_NAME chat-app、SPACETIMEDB_URI ws://localhost:3000。在 App.tsx 中数据获取完全依赖useTable(tables.user)、useTable(tables.room)、useTable(tables.message)等 hooks——订阅推送更新React 自动重渲染无需手动轮询。前端同时负责关键过滤逻辑在线用户u.online u.status ! invisible房间分类publicRooms/myPrivateRoomsisPrivate !isDm 我是成员/myDmRooms输入指示与定时消息都从公开表按房间 身份过滤未读数、已读回执、线程视图均在客户端实时计算。架构取舍说明为保证实时性与简单性所有表声明为public敏感过滤成员资格、私密可见性由服务端 reducer 的成员校验与客户端的身份过滤共同完成而非依赖数据库级权限视图。这一取舍在“技术笔记”一节有明确交代。六、部署与运行四条命令跑通全栈根据 README.md 的部署章节完整流程如下# 1. 启动 SpacetimeDB 服务器 spacetime start # 2. 发布后端模块清库、免确认指定模块路径 spacetime publish chat-app --clear-database -y --module-path backend/spacetimedb # 3. 生成 TypeScript 客户端绑定 mkdir -p client/src/module_bindings spacetime generate --lang typescript --out-dir client/src/module_bindings --module-path backend/spacetimedb # 4. 安装客户端依赖并启动开发服务器 cd client npm install npm run dev应用默认运行在http://localhost:5173。后端模块的依赖在 package.json 中声明为spacetimedb: ^1.11.0注意第 3 步生成的module_bindings目录README 项目结构中的client/src/module_bindings/是运行时产物评测交付的目录中不包含该目录需按上述命令自行生成。七、实战踩坑t.product()与视图的取舍评分报告“Technical Notes”记录了本次评测遇到的唯一 SDK 问题初次尝试在视图定义中使用t.product()报错t.product is not a function。修复方式是移除视图定义改为表全部公开 客户端过滤。这解释了为什么 schema.ts 中所有表均为public: true且没有使用view声明在当前 SDK 版本下t.product()不可用团队选择了“公开表 客户端身份过滤 服务端 reducer 成员校验”三层方案来保证功能与安全性的平衡。对于想要改用数据库视图的读者建议先确认所用spacetimedbSDK 版本是否支持对应的视图 API再做迁移。八、评测方法参考一份可复用的 LLM 应用评估框架本次评分严格遵循 grading_rubric.md 定义的方法论其要点可作为任何 LLM 生成应用的验收模板提示词到功能的映射各级提示词包含的功能是递增的01_*_basic为功能 1–4、09_*_private_rooms为 1–12……只对提示词包含的功能打分避免“超范围扣分”0–3 四级评分制区分“完全损坏 / 部分实现 / 基本可用 / 完全符合规格”记录客观指标代码行数、文件数、外部依赖、编译与运行是否通过记录重提示次数统计修复所需的追加提示数量衡量 LLM 一次到位的质量逐功能留存实现说明为每个功能记录“实现笔记”便于回溯审计。结语从评分报告到可运行源码的完整闭环这份 36/36 的评分报告之所以有参考价值在于其背后是一套完整可运行、可复现的源码12 张表定义支撑 12 项功能25 个 reducer 承载全部业务规则4 个定时表处理所有“未来某刻该发生的事”React 前端通过订阅实时渲染。对 SpacetimeDB 学习者而言schema.ts 是表结构与定时任务的最佳入门范例reducers.ts 是成员校验与权限控制的完整清单而 App.tsx 则展示了如何用极少量样板代码把数据库实时变化变成 UI 更新。按第六节的四步部署流程读者可以零成本跑起这套应用并在此基础上扩展自己的实时功能。【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考