当前位置: 首页 > news >正文

openworld.js 的一些创意,以及 openWorld.zone 未来策划建议

(本文由 codex + chatGPT 5.5 整理,AI 参与度 20%)

openworld-js / signboard_lab / 飞书 / SaaS 的 API 盘点与产品方向深思

生成时间:2026-05-02
工作范围:openworld-js 本地源码、open-world-zone/plugins/signboard_lab 客户端、open-world-zone/plugins/signboard_lab/server 生产服务器代码、1tool/feishu_test 飞书读写 MVP、z-nextjs/saas-start SaaS 基础、以及你给的博客园文章。
说明:本文没有启动任何占用端口的程序,只做源码级审计、SQLite 只读抽样和产品方案推演。这样符合你“端口程序由你自己运行”的规则。

0. 先给结论

现在真正已经形成服务器与客户端闭环的核心,是 signboard_labboards 信息板系统。它不是一个松散的 demo,而是已经有了完整生命线:

  1. 3D 世界里的 plane 被建筑数据转成带 ID 的信息板。
  2. 客户端通过纹理 hook 发现某块信息板需要内容。
  3. 客户端把 ID 合并成批量请求,向 Node + SQLite 服务端取内容。
  4. 用户在 3D 里点击信息板,弹出 HUD 面板编辑文字或图片 URL。
  5. 面板通过 PATCH /api/signs/:id 保存单块信息板。
  6. 服务端写 SQLite 后,通过 SSE 把变化推给所有客户端。
  7. 客户端收到 SSE 后更新 signContentMap,清纹理缓存,强制引擎重新加载画板。
  8. 热点信息侧栏和全文/原图模态框也会同步更新。

这条线最重要的价值不是“能保存一段文字”,而是它已经证明:你的 3D 世界可以把二维内容变成空间里的长期对象,并且对象具有远程持久化、局部更新、实时广播、图片展示、备注扩展、编辑/展示两种模式。换句话说,它已经是“3D Knowledge World OS”的最小神经系统。

现在三个目录的关系可以这样理解:

  • openworld-js/open-world-zone/plugins/signboard_lab:3D 空间里的信息板运行时。它负责看见、懒加载、渲染、编辑、热更新。
  • openworld-js/open-world-zone/plugins/signboard_lab/server:当前生产 API 服务。它负责 SQLite 持久化、CORS、SSE、单条更新、批量替换、批量读取。
  • 1tool/feishu_test:飞书文档读写桥。它不自己处理 token/OAuth,而是调用本地 lark-cli,已经具备“从飞书读内容”和“向飞书追加内容”的能力。
  • z-nextjs/saas-start:商业化外壳。它已有登录、团队、活动日志、Stripe 订阅、仪表盘、博客、基础 API 和 Server Actions。

海外优先修正:后面的商业判断按“海外站优先”来做,不把国内市场当目标市场。feishu_test 在本文里主要代表“Lark/Feishu CLI 已跑通的内容源适配器原型”,真正面向海外用户时,应优先包装成 Lark / Notion / Google Docs / Markdown / RSS / Readwise / Obsidian 等 connector,而不是把产品定位成中文飞书生态工具。河南收入目标只作为你的个人生活成本锚点,不作为市场选择依据。

最好的连接方案不是把三者硬塞成一个巨型应用,而是分层:

  • Lark/Notion/Google Docs/Markdown 等内容源做协作编辑和原始内容仓库。
  • SaaS 做账号、订阅、项目管理、导入队列、发布权限、SEO 平面页。
  • openworld-js 做可逛、可分享、可沉浸的空间展示层。
  • signboard API 做“空间对象内容层”的同步协议。
  • AI 做自动整理、自动选址、自动摘要、自动生成空间结构、自动把内容变成可卖的展馆。

你给的文章里反复强调一个判断:3D 不是替代主笔记系统,而是用 3D 包裹 2D 笔记,2D 负责检索和编辑,3D 负责让人愿意回来逛、愿意复习、愿意把内容当成自己的空间。这个判断与当前代码最匹配,尤其是 signboard_lab 已经把“墙上写字、贴照片”落到了可运行代码层。

1. 源码地图:现在项目正在形成什么东西

1.1 openworld-js 主体

openworld-js 是一个浏览器端自研 WebGL 开放世界引擎项目。README.md 里强调它是一个体积极小的 WebGL 库,用于直接在浏览器里构建交互式 3D 世界。当前项目通过 Vite 跑,package.json 的脚本是:

  • npm run devvite --host 0.0.0.0
  • npm run buildvite build
  • npm run previewvite preview --host 0.0.0.0

真正的演示入口在 open-world-zone/main.js。这个文件把引擎初始化起来,然后依次加载公共插件和私有插件:

  • xmap:小地图。
  • cookieSavePos:保存当前位置。
  • xdashpanel:仪表盘。
  • sound:声音。
  • centerDot_clean:中心点取物/热点探测。
  • testSampleAni:人物动画。
  • build:建造器,只有 mode === 0 时加载。
  • dataProc:万数块/百数块/单数块实例化数据处理系统。
  • mvp:主角。
  • symoffset:对称阵列工具。
  • signboard_lab:当前重点,信息板系统。
  • build_lab:建造器使用的容器。
  • xhall:第一个成品建筑。
  • somecube:实验块。
  • normalevent:常用事件。
  • tab:右上角侧边栏。

这个组合说明你现在不是只有引擎,而是已经有一个可进入的世界:有地面、主角、建筑、模式切换、中心点、移动端控制、FOV、自动裁剪、信息板、服务器地址设置。这些东西虽然还散,但已经接近“工具运行时”,不是单纯图形 demo。

1.2 dataProc 是底层容量系统

open-world-zone/plugins/dataProc/dataProc.js 里有一个很关键的设计:用万数块、百数块、单数块来管理大量实例。它把空间对象分成不同容量的块:

  • Type 1:万数块,默认容量 10000。
  • Type 2:百数块,默认步长 300。
  • Type 3:单数块,步长 1。

这个系统的直觉很对。你做的是“空间里的大量对象”,不是传统 DOM 页面。每块对象既要渲染,又要有物理/热点档案,还要能被删除、隐藏、裁剪、绑定纹理。dataProc.process() 统一负责:

  1. 分配空闲块索引。
  2. 读取原始建筑数据。
  3. 填充实例化容器。
  4. 添加物理体和热点档案。
  5. 需要时调用 W.cubeW.plane 做实例渲染。
  6. 返回块头索引,供后续管理。

这对后面的商业化很重要,因为它意味着你的空间不是手摆几十个对象,而是有机会承载数千、数万、甚至更高数量的空间内容对象。

1.3 build_lab / xhall 如何产生信息板

build_lab/full_state.jsxhall/full_state.js 是信息板生成的关键。

build_lab/full_state.js 里,普通建筑数据会被加工成三类信息板:

  • house1H3-*
  • board1h-*
  • floorSign-*

处理逻辑大致是:

  1. 找到对应建筑索引。
  2. 给对象设置 dzst 等热点/物理参数。
  3. 把纹理字段 t 设置为业务 ID,例如 house1H3-1
  4. 把这些对象复制进数组 arrCarrDarr
  5. 原位置标记删除。
  6. 调用 ccgxkObj.signTest(arrC, ccgxkObj, {x:0}, 1) 交给 signboard_lab

xhall/full_state.js 里也有同样思路,INDICES.signBoard 会被转成 testSign1testSign2 这样的信息板 ID。

这里的关键不是命名,而是“建筑对象变内容对象”。这就是产品层的核心抽象:空间对象有一个稳定 ID,内容可以晚点加载、远程加载、实时更新。

1.4 signboard_lab 是“墙上写字、贴照片”的最小产品

signboard_lab/signTest.js 是入口。它做了三件主事:

  1. 给引擎注册 errorTexture_diy hook:当某个纹理找不到时,接管纹理生成逻辑。
  2. 通过 dataProc.process() 把信息板 plane 加入世界。
  3. 初始化 SSE、编辑面板、热点信息面板,并把热点点击与编辑面板绑定起来。

这意味着你的信息板不需要提前把所有纹理做成图片文件。它可以在浏览器里动态生成:

  • text 模式:用 Canvas 绘制文字,并自动换行、自动缩放、居中。
  • image 模式:加载图片 URL,然后按图片比例重设 plane 宽高。
  • empty 模式:可显示 ID 或做隐藏/占位。

这套方式很适合你的方向。因为 3D 世界里的信息本质仍是二维内容:文字、图片、网页卡片、视频封面、文档摘要。你真正需要的是“把二维内容挂到空间位置上”,不是把每段文字都变成复杂 3D 模型。

2. signboard_lab 服务器与客户端已经闭环的全部 API

下面是当前 signboard_lab/server 中服务器实际注册、客户端实际调用、并且能形成闭环的 API。这里按“能被生产系统信任的接口”来列。凡是客户端里有残留但服务器无路由的,我会单独放到“未闭环接口”里,不混在完成清单里。

2.1 服务基本信息

服务器入口:open-world-zone/plugins/signboard_lab/server/server.js
数据库模块:open-world-zone/plugins/signboard_lab/server/db/index.js
API 处理:open-world-zone/plugins/signboard_lab/server/api/signs.js
SSE 处理:open-world-zone/plugins/signboard_lab/server/sse.js
辅助函数:open-world-zone/plugins/signboard_lab/server/helpers.js
默认端口:8899
启动命令:npm run start,实际执行 node server.js
依赖:better-sqlite3sql.js,实际持久化使用 better-sqlite3

server.js 明确写着这是纯 API 服务器,静态文件由主项目 HTTP 服务器提供。它监听 0.0.0.0:8899,启动时初始化 SQLite,并在退出时关闭 SSE 客户端、执行 WAL checkpoint、关闭数据库。

2.2 通用 CORS / OPTIONS 预检

接口:OPTIONS *

实现位置:server.jshandlePreflight(req, res)

响应状态:204

响应头:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PATCH, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400

用途:

  • 允许浏览器跨域调用 API。
  • 支持 PATCHPOST 带 JSON body 的预检。
  • DELETE 虽然在 CORS 中允许,但当前服务器没有实现对应业务路由。

这对当前架构很重要,因为 3D 客户端、管理页、生产 API 很可能不在同一端口。开发时主项目可能在 8089 或 Vite 端口,API 在 8899;生产时默认配置又可能指向远程 https://selfdb.ccgxk.com

2.3 数据库表结构:boards

SQLite 文件:open-world-zone/plugins/signboard_lab/server/db/signboard.db

当前只读抽样显示,数据库里有 119 条 boards,其中:

  • text:96 条
  • image:23 条

表结构:

CREATE TABLE boards (id TEXT PRIMARY KEY,name TEXT NOT NULL,mode TEXT NOT NULL DEFAULT 'text',content TEXT,created_at DATETIME DEFAULT CURRENT_TIMESTAMP,updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,extra TEXT DEFAULT '{}'
);

触发器:

CREATE TRIGGER boards_updated_at
AFTER UPDATE ON boards
BEGINUPDATE boards SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
END;

字段含义:

  • id:空间对象 ID,也是客户端纹理 ID,例如 board1h-0house1H3-1
  • name:显示名;当前多数场景直接等于 id
  • mode:内容模式,目前闭环的是 textimage。客户端存在 empty 内存态;管理页残留 canvas 选项,但服务器未实现 canvas API。
  • content:正文或图片 URL。
  • extra:JSON 字符串,当前已用的是 remark,用于保存“不显示在画板上的备注”。
  • created_at:创建时间。
  • updated_at:更新时间,靠触发器自动刷新。

数据库模块有几个重要函数:

  • initDatabase():打开 SQLite,启用 WAL,建表,迁移 extra 字段,删除历史 canvas_functions 表。
  • getAllBoards():按 id 排序返回全部。
  • getBoardsByIds(ids):按 ID 批量查询。
  • upsertBoard(board):单条插入或更新。
  • replaceAllBoards(boards):事务内全量删除再插入。
  • deleteBoard(id):删除单条,但当前 HTTP 路由没有暴露。
  • closeDatabase():checkpoint、关闭连接、清理 wal/shm 文件。

这里有一个很关键的事实:initDatabase()DROP TABLE IF EXISTS canvas_functions。这说明 canvas 函数库在当前生产服务器里已经被主动移除。管理页 JS 里保留的 API_CANVAS 不能算已闭环 API。

2.4 GET /api/signs

接口:GET /api/signs

服务器入口:

  • server.js 路由到 handleGetSigns(req, res)
  • 实现在 server/api/signs.js

客户端调用位置:

  • signboard_lab/hotinfo/hotinfo.jsloadBoardsData()
  • signboard_lab/server/js/main.jsloadData(),也就是管理页。

请求参数:无。

成功响应:

{"version": 1,"boards": [{"id": "board1h-0","name": "board1h-0","mode": "text","content": "文本或图片 URL","extra": { "remark": "" },"updated_at": "2026-04-15 13:20:56"}]
}

错误响应:

{"error": "错误信息"
}

错误状态:500

实现细节:

  • 服务端读取全部 boards。
  • 对每条数据执行 JSON.parse(b.extra),把数据库里的 JSON 字符串转成对象。
  • 返回 version: 1,说明你已经预留协议版本概念。
  • 响应由 sendJson() 写出,带 Content-Type: application/json; charset=utf-8Access-Control-Allow-Origin: *

当前用途:

  1. 管理页全量编辑时先拉全量。
  2. 热点信息面板初始化时拉一份轻量元数据,用于左侧信息、全文/原图弹窗、后续 SSE 局部修补。

这个接口是“平面管理”和“空间热点侧栏”的基础,但不是 3D 画板懒加载的主路径。3D 懒加载走的是 POST /api/signs/batch,这样才不会一次性把所有内容都拉下来。

2.5 POST /api/signs/batch

接口:POST /api/signs/batch

服务器入口:

  • server.js 路由到 handleGetSignsBatch(req, res)
  • 实现在 server/api/signs.js

客户端调用位置:

  • signboard_lab/store.jsdoBatchFetch()

请求头:

Content-Type: application/json

请求体:

{"ids": ["board1h-0", "house1H3-12", "floorSign-3"]
}

成功响应:

{"boards": [{"id": "board1h-0","name": "board1h-0","mode": "text","content": "内容","extra": { "remark": "" },"updated_at": "2026-04-15 13:20:56"}]
}

特殊情况:

  • 如果 ids 不是数组,或者长度为 0,直接返回 { "boards": [] }
  • 如果某些 ID 在数据库里不存在,响应里不会包含它们。客户端会把这些 ID 标成 empty,并可在编辑模式下显示 ID 方便补内容。

错误响应:

{"error": "错误信息"
}

错误状态:500

客户端懒加载机制很重要:

  • signContentMap 没有某个 ID 时,lazyLoadSign(id) 把 ID 加入 pendingIds
  • 100ms 内的多个 ID 会合并成一次 POST /api/signs/batch
  • 请求成功后,客户端逐条 setSignContent(),再调用 window.updateSign() 触发 3D 纹理刷新。
  • 没查到的 ID 会被标记为空内容。
  • 请求失败时,客户端把失败 ID 放回队列,下次重试。

这就是“可扩展到很多画板”的核心接口。它避免每个画板一个 HTTP 请求,也避免一进入世界就拉全量。你的空间对象数量会继续增加,这个接口比 GET /api/signs 更接近生产运行时主干。

2.6 POST /api/signs

接口:POST /api/signs

服务器入口:

  • server.js 路由到 handleSaveSigns(req, res)
  • 实现在 server/api/signs.js

客户端调用位置:

  • signboard_lab/server/js/main.jssaveData(),也就是管理页批量保存。

请求头:

Content-Type: application/json

请求体:

{"version": 1,"boards": [{"id": "board1h-0","name": "board1h-0","mode": "text","content": "新的内容","extra": { "remark": "" }}]
}

成功响应:

{"success": true,"message": "保存成功","changed": 3
}

错误响应:

{"error": "错误信息"
}

错误状态:500

实现细节:

  1. 服务端解析请求体。
  2. data.boards || []
  3. 读取旧数据,建立 oldMap
  4. 对比 namemodecontentextra,找出变化的 boards。
  5. 调用 replaceAllBoards(),事务内先删除全部,再插入新数组。
  6. 返回保存成功和变化条数。
  7. 如果有变化,只通过 SSE 广播变化的 boards,而不是广播全量。

这里有一个强烈的设计味道:批量接口不是为高频编辑设计的,而是给 admin 管理页做全量维护。它有破坏性,因为 replaceAllBoards() 会删除数据库里所有 boards 再重建。如果未来多人协作或云端正式商业化,这个接口应保留给管理员、导入器、迁移工具,普通用户编辑应该继续走 PATCH /api/signs/:id

2.7 PATCH /api/signs/:id

接口:PATCH /api/signs/:id

示例:PATCH /api/signs/board1h-0

服务器入口:

  • server.js 识别 pathname.startsWith('/api/signs/')
  • 通过 decodeURIComponent(pathname.slice('/api/signs/'.length)) 取 boardId
  • 路由到 handleUpdateOneBoard(req, res, boardId)

客户端调用位置:

  • signboard_lab/signPanel/signTest.jssave()

请求头:

Content-Type: application/json

请求体:

{"mode": "text","content": "画板正文","extra": {"remark": "不显示在画布上的备注"}
}

图片模式请求体:

{"mode": "image","content": "https://example.com/image.png","extra": {"remark": "图片说明"}
}

成功响应:

{"success": true,"message": "更新成功"
}

错误响应:

{"error": "错误信息"
}

错误状态:500

服务端默认值:

  • name: data.name || id
  • mode: data.mode || 'text'
  • content: data.content || ''
  • extra: data.extra || {}

写入方式:

  • 调用 upsertBoard(board)
  • 如果 ID 不存在,插入新行。
  • 如果 ID 存在,更新 namemodecontentextra
  • updated_at 由触发器刷新。

SSE 广播:

{"boards": [{"id": "board1h-0","name": "board1h-0","mode": "text","content": "画板正文","extra": {"remark": "备注"}}]
}

这个接口是当前最核心、最健康的写接口。它满足:

  • 单条更新,不会误伤其他 boards。
  • 新板子可以直接 upsert。
  • 保存后通过 SSE 回环刷新本机客户端和其他客户端。
  • 客户端保存成功后隐藏面板,但不直接改本地状态,而是等待 SSE 回来统一更新,减少“双写状态”带来的错乱。

这个设计经验很宝贵。以后无论你接飞书、Notion、Obsidian、本地文件、SaaS 后台,都应该优先落到“单个空间对象 upsert + 事件广播”的模型,而不是每次全量覆盖。

2.8 GET /api/signs/stream

接口:GET /api/signs/stream

类型:Server-Sent Events

服务器入口:

  • server.js 路由到 handleSseStream(req, res)
  • 实现在 server/sse.js

客户端调用位置:

  • signboard_lab/hotUpdate.jsinitSSE()

响应头:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Access-Control-Allow-Origin: *

连接建立后,服务器先写:

: connected

每 15 秒心跳:

: heartbeat

数据事件格式:

data: {"boards":[{"id":"board1h-0","mode":"text","content":"...","extra":{"remark":""}}]}

客户端行为:

  • new EventSource(${apiBase}/api/signs/stream)
  • onopen 打日志。
  • onmessage 解析 JSON。
  • 如果收到 data.boards,逐条判断这块板是否已经注册到 signIndexMap
  • 如果当前本地内容没有变化,则跳过,避免重复重绘。
  • 如果变化,调用 window.updateSign(board.id, board.content, board.mode, board.extra || {})
  • onerror 时关闭连接,3 秒后重连。
  • 初始化失败时 5 秒后重试。

服务端行为:

  • clients = new Set() 管理所有响应对象。
  • 每个客户端断开时从 Set 里删除。
  • broadcast(data) 会把 JSON 序列化成 SSE 格式,发给所有客户端。
  • 进程关闭时 closeAllClients() 会结束所有连接。

这个接口让你的系统从“保存后刷新页面”进化成“空间对象实时变化”。这在未来有几种直接价值:

  • 管理后台改内容,3D 展厅自动更新。
  • 飞书同步改内容,在线空间自动更新。
  • 多人共同布展,一人保存,别人马上看到。
  • AI 后台自动整理位置,3D 前端能逐步显示变化。

SSE 比 WebSocket 简单,当前场景也足够。你的主要事件是服务端向客户端广播,不是高频双向游戏状态同步。保留 SSE 是很务实的选择。

2.9 404 Not Found

所有未匹配路由都会返回:

{"error": "Not Found"
}

状态:404

这也意味着:

  • DELETE /api/signs/:id 没有暴露。
  • GET /api/canvas-lib 没有暴露。
  • POST /api/canvas-lib 没有暴露。
  • POST /api/canvas-lib/add 没有暴露。
  • DELETE /api/canvas-lib/:name 没有暴露。

这些不能列入已完成 API。

3. signboard_lab 客户端内部 API 与运行协议

HTTP API 只是边界,客户端内部也有一套事实上的协议。它们不一定暴露给外部,但决定了系统如何运行。

3.1 getApiBase:服务器地址协议

文件:signboard_lab/config.js

关键常量:

const STORAGE_KEY = 'signboard_server_address';
const DEFAULT_ADDRESS = '127.0.0.1:8899';

getApiBase() 逻辑:

  • 如果 localStoragesignboard_server_address,直接返回这个值。
  • 如果没有,返回 http://127.0.0.1:8899

同时 tab/serverConfig.js 也使用同一个 STORAGE_KEY,但默认值是:

const DEFAULT_ADDRESS = 'https://selfdb.ccgxk.com';

这形成一个隐藏规则:

  • 如果用户没有保存过地址,signboard_lab/config.js 会默认本地 http://127.0.0.1:8899
  • 如果用户在侧边栏点了“默认”,会写入 https://selfdb.ccgxk.com
  • 如果用户手动输入 127.0.0.1:8899 且没有协议,getApiBase() 会原样返回,fetch/EventSource 可能失败。

建议以后把地址保存逻辑统一成“必须带协议”,保存时自动补 http:// 或校验。这不是当前 API 闭环的阻断点,但会影响普通用户配置成功率。

3.2 signContentMap

文件:signboard_lab/store.js

用途:内存里的画板内容缓存。

实际形态:

signContentMap.set(id, { mode: 'text', t: content, extra });
signContentMap.set(id, { mode: 'image', imgUrl: content, extra });
signContentMap.set(id, { mode: 'empty' });

它的职责:

  • 判断某块画板是否已经加载内容。
  • 给编辑面板回填文字、图片 URL、备注。
  • 给渲染 hook 提供文本或图片 URL。
  • 给 SSE 更新检测提供当前值。

这里没有直接持久化,本地刷新页面会重新向服务器加载。

3.3 signIndexMap

文件:signboard_lab/store.js

用途:把业务 ID 映射到引擎对象索引。

形态:

signIndexMap.set(id, { index });

它在 errorTexture_diy hook 里建立。当某块 plane 进入纹理加载流程时,hook 能知道 drawItem.indexdrawItem.id,于是把 ID 和物理/渲染索引绑定。

它的作用:

  • window.updateSign(boardId, ...) 能找到该改哪个引擎对象。
  • 编辑面板能从当前 hotPoint 反查 boardId。
  • 热点信息面板能从 hotIndex 找 boardId。
  • SSE 收到未进入视野、还没注册的 board 时可以跳过,等它未来进入 hook 后再懒加载。

3.4 window.updateSign

文件:signboard_lab/hotUpdate.js

这是当前客户端最核心的内部函数。它做的事很多:

  1. signIndexMap 找到 board 对应的引擎 index。
  2. 更新 signContentMap
  3. 如果是图片模式,生成 random 后缀对抗浏览器纹理缓存。
  4. 清理 textureModule.textureMap 里的旧缓存。
  5. 清除 window['T' + index]
  6. 对 image 模式删除旧 img DOM,设置 ccgxkObj.indexToArgs.get(index).texture = boardId + random
  7. 对 text 模式设置 texture = boardId
  8. currentlyActiveIndices 删除 index,让引擎重新走 hook。

这是一种“以纹理缺失触发动态绘制”的设计。它不是传统 React 状态刷新,而是直接和你的引擎缓存层打交道。这个函数在未来值得拆分,但现在它跑通了最难的部分:让空间对象内容变化能重新进入渲染管线。

3.5 errorTexture_diy hook

文件:signboard_lab/signTest.js

运行逻辑:

  • 如果 signContentMap 已有该 ID:
    • mode === 'text':调用 drawSmartText()
    • mode === 'image':调用 handleImageMode()
    • mode === 'empty':绘制 ID 或占位。
  • 如果没有内容:
    • 调用 lazyLoadSign(id)
    • 临时绘制 Loading...

这个 hook 的巧妙点在于:内容加载与渲染需求绑定。只有当画板真的被引擎需要绘制时,才触发懒加载。这适合你的大空间,避免入口瞬间请求所有墙面。

3.6 drawSmartText

文件:signboard_lab/renderer.js

它是 text 模式的画板渲染器,能力包括:

  • 白底。
  • 中文友好字体族。
  • 根据画板宽高动态计算 padding。
  • 从较大字号开始试排。
  • 自动逐字换行。
  • 避免部分中文标点出现在行首。
  • 内容过高时逐步缩小字号。
  • 三行以内居中,多行时左上排版。

这看似小功能,但对产品非常关键。3D 信息板第一眼是否舒服,取决于文字是否像“贴在墙上的正常纸张”,而不是一坨超出边界的 canvas 文本。

3.7 handleImageMode

文件:signboard_lab/handlers/imageHandler.js

它负责 image 模式:

  • 用唯一 DOM ID 管理隐藏 <img>
  • 设置 crossOrigin = 'anonymous'
  • 图片加载完成后按自然宽高计算画板宽高。
  • 把图片元素塞入 textureMap
  • 调用 ccgxkObj.W.plane() 更新纹理与尺寸。
  • 如果 naturalWidth === 0,尝试把它当 SVG fetch 成文本,再转成 data URI。

这个功能让“贴照片”已经是真正意义上的贴照片,不只是文本。

3.8 signPanel 编辑面板

文件:signboard_lab/signPanel/signTest.jssignboard_lab/signPanel/dom.js

能力:

  • 点击热点后弹出 HUD 编辑窗口。
  • 支持 text / image 模式切换。
  • 支持图片 URL 预览。
  • 支持备注区,备注存在 extra.remark,不渲染在画布上。
  • 支持 Ctrl/Cmd + S 保存。
  • 支持可拖动。
  • 支持文字全屏编辑模式。
  • 按画板在内存里记住文本光标、滚动条、全屏/小屏状态。
  • 打开面板时解锁鼠标、暂停热点追踪。
  • 关闭面板时恢复热点追踪,并视情况重新锁定鼠标。

保存流程:

用户点保存
-> 读取 mode/content/remark
-> 保留已有 extra,仅覆盖 extra.remark
-> PATCH /api/signs/:id
-> 成功后显示“已保存”并关闭
-> 等 SSE 回来统一刷新画板

这是一个接近真实产品的编辑器,不是简单 prompt。它已经考虑了用户在 3D 第一人称世界里编辑文字时最容易出问题的鼠标锁定、焦点、快捷键、热点漂移、内容不丢失。

3.9 hotinfo 热点信息面板

文件:signboard_lab/hotinfo/hotinfo.jshotinfo/dom.js

这个模块服务于 mode === 1 展示模式。它的职责不是直接编辑,而是让浏览者在看到某块信息板时,可以在左侧看到信息,并打开全文或原图。

能力:

  • 初始化时 GET /api/signs 拉元数据缓存。
  • 每 100ms 轮询 ccgxkObj.hotPoint
  • 中心点指向信息板时更新左侧信息。
  • 图片与文字都走统一内容模态框。
  • mode=1 下点击热点只解锁鼠标,不直接弹编辑器。
  • 内容模态框里可以点击编辑,复用 signPanel。
  • SSE 更新时修补本地 boardsData,并刷新当前热点信息或当前打开模态框。

这正好对应你文章里提到的问题:3D 文字看久了累,应该像游戏里读书那样,点开后拍扁成 2D 阅读。hotinfo 已经在做这件事。

3.10 admin.html 管理页

文件:signboard_lab/server/admin.htmlserver/js/main.js

已闭环能力:

  • GET /api/signs 全量读取。
  • 在网页里编辑每块 board。
  • POST /api/signs 批量保存。
  • 文本模式 textarea。
  • 图片模式 URL 输入和预览。

未闭环残留:

  • 管理页里还有 Canvas 函数库 Tab。
  • JS 里定义了 API_CANVAS = API_BASE + '/api/canvas-lib'
  • 它会尝试调用:
    • GET /api/canvas-lib
    • POST /api/canvas-lib
    • POST /api/canvas-lib/add
    • DELETE /api/canvas-lib/:name
  • 但当前 server/api 目录只有 signs.js
  • server.js 没有注册 canvas 路由。
  • db/index.js 还主动删除 canvas_functions 表。

所以 Canvas 函数库不是当前服务器与客户端已完美实现的 API。它是历史残留 UI,需要未来要么删除,要么重新实现。

4. 飞书测试目录已经实现的 API

路径:/Users/kehongli/studio/1tool/feishu_test

这个项目是飞书文档读写 MVP。它的关键选择是:不在应用代码里手写飞书 token、OAuth、开放平台 API,而是把授权、读写都交给本地 @larksuite/cli。这很实用,因为对个人工具来说,先跑通“能读/能写”比一开始就做完整 OAuth 后台更重要。

4.1 服务基本信息

入口:server.js
静态页:public/index.html
默认端口:5177
启动脚本:npm run start
CLI:node_modules/.bin/lark-cli

.env 只用于改 PORT,飞书授权由 CLI 自己管理。

4.2 GET /api/cli/status

接口:GET /api/cli/status

用途:检查本地 lark-cli 是否已配置和登录。

服务端动作:

lark-cli auth status

成功响应示例:

{"ok": true,"configured": true,"raw": "CLI 原始状态或 JSON"
}

未配置响应示例:

{"ok": true,"configured": false,"error": "错误内容","hint": "先在终端运行:cd /Users/kehongli/studio/1tool/feishu_test && ./node_modules/.bin/lark-cli config init --new"
}

客户端调用位置:

  • public/index.htmlrefreshCliStatus()

页面右上角会显示:

  • cli: configured
  • cli: not configured
  • cli: unknown

4.3 POST /api/read

接口:POST /api/read

请求体:

{"url": "飞书 Wiki 文档链接"
}

服务端动作:

lark-cli docs +fetch --doc <飞书 Wiki 链接> --as user --format json

成功响应:

{"ok": true,"source": "lark-cli","raw": "CLI JSON 或原始文本","content": "提取出的可读正文"
}

错误响应:

{"ok": false,"source": "lark-cli","error": "错误信息","parsed": "如果错误可解析为 JSON,则返回 JSON"
}

客户端调用位置:

  • public/index.html 的“读取内容”按钮。

兼容逻辑:

  • 服务端尝试 JSON.parse() CLI 输出。
  • 内容字段按优先级取:
    • data.content
    • data.markdown
    • data.data?.content
    • data.data?.markdown
    • data.document?.content
    • 否则返回格式化 JSON 或原始文本。

这说明飞书层现在已经能作为“内容入口”。未来可以把读取结果拆成多个段落、标题、图片、链接,再映射成多个 signboard。

4.4 POST /api/append

接口:POST /api/append

请求体:

{"url": "飞书 Wiki 文档链接","text": "要追加的 Markdown"
}

服务端动作:

lark-cli docs +update --doc <飞书 Wiki 链接> --as user --mode append --markdown "要追加的内容"

成功响应:

{"ok": true,"source": "lark-cli","result": "CLI JSON 或原始输出"
}

错误响应同上。

客户端行为:

  • 点击“追加文本”后调用 /api/append
  • 成功后自动触发读取按钮,重新读取当前文档。

这给你未来做“3D 空间里写了一段内容,同步追加回飞书”提供了第一块砖。它目前还不是精确更新某个块,而是 append,但作为 MVP 足够。

5. SaaS 基础已经具备的 API 与 Server Actions

路径:/Users/kehongli/studio/z-nextjs/saas-start

这是 Next.js 15 App Router 的 SaaS 基础。它是商业外壳,而不是 3D 运行时。它已经具备:

  • 登录/注册。
  • JWT cookie session。
  • 团队模型。
  • RBAC 的 owner/member 角色字段。
  • 活动日志。
  • Stripe Checkout。
  • Stripe Customer Portal。
  • Stripe webhook。
  • Dashboard。
  • Pricing。
  • Blog。
  • shadcn/ui 基础组件。
  • Drizzle + Postgres schema。

5.1 GET /api/user

文件:app/api/user/route.ts

接口:GET /api/user

行为:

  • 调用 getUser()
  • 从 cookie 读 session
  • 验证 JWT。
  • 检查过期时间。
  • 查数据库 users 表。
  • 排除 deletedAt 非空的软删除用户。
  • 返回当前用户或 null

客户端调用:

  • components/header.tsx 用 SWR 拉 /api/user
  • dashboard/general/page.tsx 用 SWR 拉用户信息。
  • dashboard/page.tsx 的团队成员邀请区域也会用到用户信息。
  • app/layout.tsx 用 SWR fallback 预置 /api/user

5.2 GET /api/team

文件:app/api/team/route.ts

接口:GET /api/team

行为:

  • 调用 getTeamForUser()
  • 先拿当前用户。
  • teamMembers 中查该用户所属 team。
  • 连带取 teamMembers 和成员用户的 id/name/email
  • 返回团队数据或 null

客户端调用:

  • dashboard/page.tsx 用 SWR 拉 /api/team
  • app/layout.tsx 用 SWR fallback 预置 /api/team

5.3 GET /api/stripe/checkout

文件:app/api/stripe/checkout/route.ts

接口:GET /api/stripe/checkout?session_id=...

用途:Stripe Checkout 成功回跳后,服务端确认 session 和 subscription,并把订阅状态写入团队。

行为:

  1. 没有 session_id,重定向 /pricing
  2. Stripe 未配置,重定向 /pricing?error=stripe_not_configured
  3. 调 Stripe retrieve checkout session。
  4. 展开 customer、subscription。
  5. 查 subscription 和 plan。
  6. client_reference_id 取 userId。
  7. 查用户。
  8. 查用户所属 team。
  9. 更新 teams 表:
    • stripeCustomerId
    • stripeSubscriptionId
    • stripeProductId
    • planName
    • subscriptionStatus
    • updatedAt
  10. 重新设置 session。
  11. 重定向 /dashboard

5.4 POST /api/stripe/webhook

文件:app/api/stripe/webhook/route.ts

接口:POST /api/stripe/webhook

用途:接收 Stripe 订阅更新和删除事件。

行为:

  1. Stripe 未配置,返回 503
  2. 读取原始 text payload。
  3. 从 header 取 stripe-signature
  4. STRIPE_WEBHOOK_SECRET 校验签名。
  5. 对事件类型分流:
    • customer.subscription.updated
    • customer.subscription.deleted
  6. handleSubscriptionChange(subscription)
  7. 返回 { received: true }

错误:

  • 签名校验失败返回 400

5.5 认证和账户 Server Actions

文件:app/(login)/actions.ts

这些不是传统 REST API,但在 Next.js App Router 里它们就是表单提交的服务器端 API。

已实现:

  • signIn

    • 校验 email/password。
    • 查用户和团队。
    • bcrypt 比对密码。
    • 设置 session。
    • 记录 SIGN_IN
    • 如果来自 checkout,则创建 Stripe Checkout Session。
    • 否则跳 /dashboard
  • signUp

    • 校验 email/password/inviteId。
    • 防重复 email。
    • hash 密码。
    • 创建用户。
    • 如果有邀请,加入邀请团队。
    • 如果没有邀请,创建新 team。
    • 写 teamMembers。
    • 记录 CREATE_TEAMSIGN_UPACCEPT_INVITATION
    • 设置 session。
    • 可接 checkout。
  • signOut

    • 获取当前用户。
    • 记录 SIGN_OUT
    • 删除 session cookie。
  • updatePassword

    • 校验旧密码、新密码、确认密码。
    • 比对旧密码。
    • 新旧不能相同。
    • hash 新密码。
    • 更新 users.passwordHash。
    • 记录 UPDATE_PASSWORD
  • deleteAccount

    • 校验密码。
    • 记录 DELETE_ACCOUNT
    • 软删除用户。
    • 修改 email 保持唯一性。
    • 删除 teamMembers 中对应成员关系。
    • 删除 session。
  • updateAccount

    • 校验 name/email。
    • 更新 users 表。
    • 记录 UPDATE_ACCOUNT
  • removeTeamMember

    • 校验 memberId。
    • 删除团队成员。
    • 记录 REMOVE_TEAM_MEMBER
  • inviteTeamMember

    • 校验 email/role。
    • 防止重复成员。
    • 防止重复 pending invitation。
    • 写 invitations。
    • 记录 INVITE_TEAM_MEMBER
    • 邮件发送尚是 TODO。

5.6 支付 Server Actions

文件:lib/payments/actions.ts

已实现:

  • checkoutAction

    • 通过 withTeam 确保用户登录且有 team。
    • 从表单取 priceId
    • createCheckoutSession()
  • customerPortalAction

    • 通过 withTeam 确保用户登录且有 team。
    • createCustomerPortalSession(team)
    • 重定向到 portal URL。

5.7 数据库 schema 对未来 3D SaaS 的意义

当前 SaaS schema 有:

  • users
  • teams
  • teamMembers
  • activityLogs
  • invitations

这对接 3D 产品时还缺:

  • projects:一个用户/团队可以有多个 3D 空间。
  • worldsspaces:世界配置、主题、默认入口点。
  • boards:云端内容对象,未来可替代 signboard SQLite 或与其同步。
  • boardVersions:内容版本历史。
  • sources:飞书、网页、Markdown、本地文件等外部来源。
  • syncJobs:导入/同步任务。
  • publicShares:公开分享链接与权限。
  • worldBuilds:静态导出版本,便于 CDN 发布。

但作为基础,SaaS 已经够用了。你不需要先重写登录支付系统,应该把 openworld 的“空间内容对象”接进去。

6. 目前明确不该误认为完成的接口和能力

6.1 signboard 的 Canvas 函数库

管理页 JS 里有 Canvas 函数库 UI,但当前服务器没有:

  • api/canvas.js
  • GET /api/canvas-lib
  • POST /api/canvas-lib
  • POST /api/canvas-lib/add
  • DELETE /api/canvas-lib/:name

并且数据库初始化会删除 canvas_functions 表。

结论:这不是已完成 API。未来如果要保留,应重新设计成受控绘图模板,不能让用户任意提交 JS 函数在浏览器执行,否则商业化后安全风险很高。

6.2 signboard 没有删除 API

db/index.jsdeleteBoard(id),但 HTTP 没暴露。CORS 允许 DELETE,只是路由不存在。

结论:删除内容现在只能通过直接数据库、未来管理工具,或 POST /api/signs 全量替换间接实现。正式产品应做:

  • DELETE /api/signs/:id
  • 或软删除字段 deleted_at
  • 或版本化恢复

6.3 signboard 没有鉴权

当前 API 是 Access-Control-Allow-Origin: *,没有 token、cookie、签名、team/project 权限。

这对个人部署没问题,但对商业 SaaS 必须补:

  • 项目 ID。
  • 用户/团队权限。
  • API token 或 session。
  • 公开只读与私有编辑分离。
  • SSE 权限校验。
  • 写操作速率限制。

6.4 飞书 MVP 不是云端 OAuth 产品

feishu_test 依赖本地 CLI 当前登录用户。它很适合个人工具和本地自动化,但不能直接拿去做多用户 SaaS。

商业化时有两条路:

  • 先保留 CLI 模式,做“本地高级版/创作者工具”。
  • 后续再接飞书开放平台 OAuth,做云端团队版。

6.5 SaaS 还没有 openworld 业务模型

SaaS 有 auth/team/billing,但没有 world/project/board/source/sync 的业务表。它是外壳,不是已经接通的三维产品。

7. 三者连接的最佳方案:把内容源变成空间,把 SaaS 变成控制台,把 openworld 变成播放器

7.1 一句话架构

Lark/Notion/Google Docs/Markdown/RSS/Readwise/Obsidian 负责原始内容,SaaS 负责账号、项目、订阅、导入、发布、SEO,openworld-js 负责 3D 空间体验,signboard API 负责“空间对象内容协议”,AI 负责把无结构内容变成可逛的空间结构。

这不是强行组合,而是刚好补齐:

  • Lark/Notion/Google Docs 强在协作编辑和既有内容沉淀,弱在空间记忆。
  • SaaS 强在商业闭环,弱在沉浸体验。
  • openworld-js 强在空间展示和引擎壁垒,弱在账号/支付/协作。
  • signboard_lab 强在单个空间对象内容闭环,弱在权限和内容来源。

7.2 推荐总数据流

Lark / Notion / Google Docs / Markdown / RSS-> 内容源读取适配器-> AI 解析:标题、段落、图片、摘要、标签、实体、关系-> SaaS 项目库:sources / boards / layout / versions-> 布局器:把内容放进房间、墙面、展台、走廊-> signboard API:写入或同步 boards-> openworld-js:懒加载画板、展示、热点阅读-> 用户在 3D 里编辑-> PATCH board-> SaaS 记录版本-> 可选追加回飞书

7.3 最小可落地版本

第一版不要做“AI 自动建整个世界”。那会失控。最小版本应该是:

  1. SaaS 里创建一个项目。
  2. 用户填一个 Lark/Notion/Google Docs/Markdown/RSS 链接,或上传一份 Markdown。
  3. 后台读取内容源。
  4. AI 把文档切成若干卡片,每张卡片有:
    • title
    • summary
    • body
    • imageUrl
    • suggestedRoom
    • suggestedWall
    • importance
  5. SaaS 生成一份 boards JSON。
  6. 写入 signboard server 的 SQLite 或新云端 boards 表。
  7. openworld-js 打开时显示这些 boards。
  8. 用户可以在 3D 里改某块板。
  9. 改动保存为版本。
  10. 用户一键发布公开 URL。

这个版本已经能卖,因为它解决的是“把已有知识内容变成一个可逛的三维空间”。它不是卖引擎,是卖成品体验。

7.4 推荐新表结构

在 SaaS 里新增:

projects
- id
- teamId
- name
- slug
- status
- createdAt
- updatedAtworlds
- id
- projectId
- theme
- entryPosition
- engineVersion
- publicMode
- createdAt
- updatedAtsources
- id
- projectId
- type: feishu | markdown | url | manual
- sourceUrl
- title
- syncStatus
- lastSyncedAt
- rawHash
- createdAt
- updatedAtboards
- id
- projectId
- worldId
- sourceId
- boardKey
- name
- mode: text | image | link | video | markdown
- content
- extra
- positionJson
- visualJson
- sortKey
- createdAt
- updatedAtboard_versions
- id
- boardId
- content
- extra
- changedBy
- changeSource: user | feishu | ai | import
- createdAtsync_jobs
- id
- projectId
- sourceId
- status
- inputJson
- outputJson
- error
- createdAt
- finishedAt

其中 boardKey 对应现在 SQLite 的 id。未来可以是:

projectSlug:roomSlug:wallSlug:index

但在 openworld 里仍然可投影成 board1h-0 这种稳定纹理 ID。

7.5 signboard API 的升级方向

现在的 API 是单项目 SQLite。连接 SaaS 后要变成多项目:

  • GET /api/projects/:projectId/signs
  • POST /api/projects/:projectId/signs/batch
  • PATCH /api/projects/:projectId/signs/:id
  • GET /api/projects/:projectId/signs/stream

为了兼容当前客户端,可以先在网关层保留旧路径:

  • 旧:/api/signs
  • 新:根据 token 或 URL 参数推断 projectId,再转到项目级 boards。

最省事的过渡方案:

  1. 先不改 signboard server。
  2. SaaS 生成每个项目独立的 SQLite 或 JSON。
  3. openworld 的 getApiBase() 指向项目专用 API。
  4. 等产品验证后,再统一迁到 Postgres。

这比一开始就重构服务器更安全。你的 server/claude.md 也提醒生产服务器已部署云上,修改很棘手。商业化前期要尽量减少对这块的破坏。

7.6 内容源同步策略

Lark/Notion/Google Docs 这类内容源不是要和每个 board 做强双向同步。强双向同步会很难,因为文档结构和 3D 空间结构不是同构的。

更好的策略是三层:

第一层:导入

  • 读取原始文档。
  • 切成 boards。
  • 生成空间。
  • 后续空间可独立编辑。

第二层:半自动同步

  • 再次读取原始文档。
  • 对比 rawHash 或段落 hash。
  • AI 标出新增、删除、改动。
  • 用户在 SaaS 审核“应用到 3D 空间”。

第三层:回写摘要

  • 用户在 3D 里新增或修改内容。
  • 不直接改原文某一段。
  • 先追加到原文档的“空间编辑记录”区,或在 SaaS 里生成可复制的变更报告。
  • 或生成一份 Markdown 变更报告。

这样就避开了最难的冲突合并,也符合真实用户习惯:原文档是正式工作区,3D 是展厅/记忆宫殿/空间化版本。

7.7 AI 的正确位置

AI 不应该第一天就“替用户决定一切”。它应该先做几个低风险但很值钱的动作:

  • 从 Lark/Notion/Google Docs/Markdown 抽标题、摘要、图片、关键句。
  • 判断内容适合放在“入口、走廊、房间、附录”哪个层级。
  • 给每块信息板生成短标题和长正文。
  • 把超长正文压成适合墙面阅读的短版,把全文留给 2D 模态框。
  • 生成 extra.remark,保存不展示的解释。
  • 给每个 board 生成 SEO 平面页标题和摘要。
  • 识别哪些内容应该变成图片板、哪些应该变成文字板。
  • 根据空间容量给用户提醒:这间房不要塞超过 80 块板,否则空间记忆开始崩。

真正强的 AI 不是“自动生成一堆无用内容”,而是“把已有内容变成可以被空间记忆吸收的对象”。这个方向和你文章中的第一性原理一致。

8. 参考文章给出的产品方向判断

你给的文章《关于 openworld-js 驱动的 open world zone 的开发想法、思考》里有几条判断,和当前源码高度吻合:

  • 第一性原理是墙上写字、贴照片。
  • 3D 不应强迫用户承担所有输入和检索,应该配套 2D 平面管理系统。
  • 3D 更适合长期结构化知识栖息地,而不是每条碎片笔记的唯一入口。
  • 空间记忆适合 50 到 200 个对象这种人能自然记住的位置规模,超大数量需要 2D 索引辅助。
  • 文字阅读应当能拍扁成 2D 模态框,否则透视文字会累。
  • 引擎本身不是产品,普通用户需要一个今天就能用的最小版本。

这几条里,当前代码已经落地了三条:

  1. 墙上写字、贴照片:signPanel + PATCH + SSE + drawSmartText + handleImageMode
  2. 2D 阅读模态框:hotinfo 的全文/原图模态框。
  3. 平面管理雏形:admin.html 的全量编辑。

还没落地的是:

  • SaaS 化 2D 管理系统。
  • 飞书等内容源导入。
  • AI 自动整理。
  • SEO 平面页。
  • 公开分享和付费。

所以接下来不是“再想一个大方向”,而是把已有神经系统接上内容源和收费外壳。

参考文章链接:https://www.cnblogs.com/duyuanshang/p/19679184

9. 收入目标:在河南生活,但市场按海外算

为了不空谈,可以用河南官方统计做一个粗基准。河南省统计局公布的 2024 年数据里,全省城镇非私营单位就业人员年平均工资为 86199 元,城镇私营单位为 50625 元。来源:河南省统计局,2024年河南省城镇单位就业人员年平均工资情况,链接:https://tjj.henan.gov.cn/2025/06-25/3173720.html

但这个数据只用于衡量你的生活成本,不用于选择客户。你的站应当优先做海外市场,原因很直接:

  • Stripe 订阅、英文 SEO、Product Hunt、Reddit、Indie Hackers、Hacker News、X/Twitter 更适合 SaaS 冷启动。
  • 海外创作者、worldbuilders、educators、ADHD/visual thinkers 对“personal knowledge space / memory palace / immersive portfolio”这类表达更容易理解。
  • 海外用户能接受 8 到 29 美元/月的小工具订阅,也更习惯为 creator tool、PKM tool、teaching tool 付费。
  • 国内市场会把你拖进备案、支付、飞书私域、低价定制、强关系销售;这和你想做“海外站”的节奏相冲突。

所以这里的收入目标应该按“海外收美元,河南生活成本结算”来理解:

  • 如果产品每月净收入 8000 元,已经接近或超过河南很多私营岗位的月均水平。
  • 如果每月净收入 15000 元,在河南多数城市会明显更从容。
  • 如果每月净收入 30000 元,就不是“过得体面”,而是有余力继续投入产品和试错。

折算成海外订阅,不需要很夸张:

  • Solo:8 到 12 美元/月,100 个用户约 800 到 1200 美元月收入。
  • Pro:19 到 29 美元/月,100 个用户约 1900 到 2900 美元月收入。
  • Studio:49 到 99 美元/月,30 到 60 个用户就能形成稳定现金流。
  • Done-for-you setup:499 到 4999 美元/单,少量客户就能覆盖生活与研发。

对你这种独立开发者,最现实的不是先追求海量 C 端,而是做“海外高客单价的小众强需求”。你的引擎壁垒在“空间化展示”,不是普通笔记软件效率。所以收费对象应该优先是:

  • English-speaking educators / course creators。
  • Worldbuilders / novelists / TTRPG creators。
  • Indie researchers / knowledge bloggers / newsletter writers。
  • Startup founders who need memorable demo rooms。
  • ADHD / visual thinkers / memory palace users。
  • Small museums / cultural nonprofits outside China。
  • Creator economy users who already pay for Notion, Readwise, Obsidian Sync, Super, Framer, Webflow.

10. 超级工具创意 1:Lark / Notion / Docs 一键变 3D Knowledge Villa

10.1 产品一句话

把一篇 Lark、Notion、Google Docs、Markdown 或 newsletter archive,自动变成一个可在网页里第一人称漫游的 3D Knowledge Villa:客厅放总览,走廊放目录,房间放章节,墙上挂摘要、图片和原文入口。

10.2 为什么这不是普通人容易想到的

大多数人会想“Notion AI summary”或“docs to website”。但这只是平面复制。真正有差异的是把文档结构变成建筑结构:

  • 文档标题变楼层。
  • 一级标题变房间。
  • 二级标题变墙面分区。
  • 关键段落变信息板。
  • 图片变画框。
  • 结论变入口大屏。
  • 附录变地下室或档案柜。

这不是花哨。它把用户的空间记忆接进文档复习。对于长文档、课程、研究资料、世界设定,位置本身就是索引。

10.3 当前代码怎么支撑

已有:

  • Lark/Feishu 读取原型:POST /api/read
  • 信息板批量写入:POST /api/signs
  • 信息板单条更新:PATCH /api/signs/:id
  • 3D 展示:signTest + drawSmartText + handleImageMode
  • 2D 全文阅读:hotinfo
  • SaaS 登录/团队/订阅:saas-start

缺口:

  • 内容源切块,海外版优先做 Markdown/Notion/Google Docs/Lark。
  • 文档结构到空间结构的布局器。
  • 项目表。
  • 发布链接。
  • 权限与订阅。

10.4 AI 怎么赋能

AI 做 6 件事:

  1. 把原始文档正文切成适合墙面的小卡。
  2. 给每张卡生成墙面短标题、短摘要、全文链接。
  3. 判断卡片应该放在哪个房间。
  4. 生成一张“入口导览地图”。
  5. 给每个房间生成一句引导语。
  6. 自动生成 SEO 平面页。

10.5 谁会付钱

  • Course creators。
  • Newsletter writers / independent researchers。
  • Startup founders 做产品故事展示。
  • Educators / tutors。
  • Worldbuilders / novelists / TTRPG creators。

10.6 收费方式

  • Free:1 个项目,最多 30 块板,有水印。
  • Pro:$12/month,10 个项目,500 块板,公开分享。
  • Studio:$29/month,50 个项目,AI 自动布局,SEO 页。
  • Done-for-you:$499 起,把客户现有 Notion/Docs/Markdown 知识库做成一个可分享展厅。

10.7 最小可卖版本

先不要做漂亮的大世界。只做一个固定建筑模板:

  • 入口大厅。
  • 6 个房间。
  • 每个房间 20 块板。
  • 内容源导入后自动填板。
  • 点击板子看全文。
  • 用户可以手动替换图片 URL。
  • 一键生成公开链接。

只要这个跑通,就能拿去找英文知识博主、newsletter 作者、course creator、worldbuilding 社群试卖。

11. 超级工具创意 2:AI Course Museum for Educators

11.1 产品一句话

Educators 上传 syllabus、lesson notes、Google Docs、Notion 或 Markdown,AI 自动生成一个可逛的网页 3D course museum:按时间线、知识点、案例、练习题分区展示,学生像逛博物馆一样复习。

11.2 为什么它适合你

你文章里提到博物馆体验。现实中很多线上课程页面非常无聊,PPT 又容易丢。3D 课件展馆不追求最高效率,而追求“学生愿意进去看”。这与你的第一人称空间能力天然匹配。

11.3 具体场景

  • History educators:把二战、古文明、艺术史做成时间线展馆。
  • Medical educators:把 anatomy、cases、pharmacology 做成楼层。
  • Language tutors:把词汇、场景、语法、例句放进固定房间。
  • Corporate trainers:把 onboarding、安全规范、产品知识做成闯关展厅。

11.4 AI 能做的部分

  • 从教案里提炼知识点。
  • 把知识点分成展厅、展墙、展板。
  • 自动生成讲解词。
  • 自动生成测验题。
  • 自动生成学生参观路线。
  • 自动生成 educator 可复制的 classroom script。
  • 根据学生错题,把错题对应展板放到“复习大厅”。

11.5 用现有 API 怎么做

初始导入:

  • Lark/Markdown 原型通过 /api/read 读入,海外版优先补 Notion/Google Docs/Markdown importer。
  • AI 生成 boards。
  • 通过 POST /api/signs 写入。

课堂中修改:

  • educator 在 3D 里点某块板。
  • PATCH /api/signs/:id 保存。
  • 学生端通过 SSE 实时看到更新。

课后复习:

  • SaaS 生成公开链接。
  • SEO 平面页收录课程目录。
  • 3D 页负责沉浸复习。

11.6 收费方式

  • Starter:$19/month,适合单个 educator。
  • Pro:$49/month,支持多个课程展馆和公开分享。
  • Done-for-you course museum:$499 到 $2999。

这类产品不需要一开始就很多用户。只要做出一个真正漂亮的英文 “World War II course museum” 或 “Anatomy memory palace” 样板,就有机会靠海外 course creator 和 tutor 群体收费。

12. 超级工具创意 3:Researcher 3D Authority Site

12.1 产品一句话

把一个 researcher、newsletter writer、blogger 多年文章变成一个三维知识庭院:每个主题一个房间,每篇文章一块展板,平面页负责 SEO,3D 空间负责建立专业感和记忆点。

12.2 为什么这个有商业价值

现在个人主页太同质化。博客、Notion、GitHub Pages、Substack archives 都像目录。真正想建立专业权威的人,需要一种“不像模板网站”的展示形式。

你的 openworld-js 的优势是轻。一个 3D 空间如果打开很快,能在浏览器直接逛,就有传播价值。它像作品集,又像数字展馆。

12.3 目标客户

  • Independent researchers。
  • Newsletter writers。
  • Technical bloggers。
  • Designers / game concept artists。
  • Novelists / worldbuilders。
  • Consultants / educators。

12.4 AI 能做什么

  • 抓取用户博客 RSS、Substack archive、Markdown、Notion 或 Google Docs。
  • 自动按主题聚类。
  • 给每个主题生成房间名。
  • 给每篇文章生成墙面摘要。
  • 给文章生成“为什么值得读”。
  • 自动挑选代表图。
  • 生成平面 SEO 页。

12.5 产品形态

每个用户有:

  • /{username} 平面首页。
  • /{username}/world 3D 世界。
  • /{username}/rooms/:slug 平面房间页。
  • /{username}/boards/:id 单个展板 SEO 页。

SaaS 负责订阅、域名绑定、统计、导入、主题模板。openworld 负责 3D 世界。

12.6 收费方式

  • Solo:$12/month。
  • Pro:$29/month,支持自定义域名和 AI 重排。
  • Done-for-you authority site:$499 到 $4999。

这个方向最适合早期变现,因为你可以手工帮前 10 个客户做。手工过程会反过来沉淀自动化模板。

13. 超级工具创意 4:小说/游戏世界观 Bible 的空间导航器

13.1 产品一句话

为小说作者、编剧、TRPG 主持人、游戏策划提供一个 3D 世界观资料馆:人物、势力、地点、时间线、道具、设定稿都挂在空间里,AI 帮忙查矛盾、补摘要、生成关系路线。

13.2 为什么普通笔记软件不够

世界观资料有强空间性。地点、势力范围、家族房间、角色关系、地图、事件时间线,本来就不适合纯列表。作者经常不是找不到笔记,而是忘了某个设定存在过。空间化可以制造“路过时看见”的偶遇。

13.3 当前引擎为什么合适

你不需要高精 3D。世界观 Bible 的核心是“位置和联想”:

  • 王国大厅。
  • 家族房间。
  • 城市墙面。
  • 时间线走廊。
  • 道具陈列柜。
  • 人物关系板。

这些用 plane、cube、图片、文字就能做。openworld-js 体积小,网页打开快,非常适合作者分享给编辑或合作伙伴。

13.4 AI 能做的部分

  • 从小说草稿中抽取人物、地点、组织、物品。
  • 自动建立实体卡。
  • 检查年龄、时间线、关系矛盾。
  • 给每个实体推荐摆放位置。
  • 生成“本章涉及哪些房间”的路线。
  • 在作者写新章时提醒:这个角色上次出现在哪些事件里。

13.5 收费方式

  • Writer:$12/month。
  • Studio:$49/month。
  • Done-for-you story bible museum:$499 到 $4999。

这个方向天然海外优先,关键词围绕 worldbuilding、story bible、visual knowledge base、memory palace for writers。

14. 超级工具创意 5:ADHD / 视觉思考者的空间复习屋

14.1 产品一句话

面向 ADHD、视觉思考者、考试复习用户,提供一个“每天进去逛 10 分钟”的空间复习屋:AI 把待复习内容贴到固定位置,按遗忘曲线安排显眼程度,用户通过空间路径复习。

14.2 为什么它不是普通待办软件

很多待办软件失败,不是因为功能不够,而是因为用户不想打开。你的文章里有一句核心判断:它不解决效率问题,它解决“人为什么还想打开它”。这个方向就该承认自己不是最快,而是更容易让人愿意回来。

14.3 产品机制

  • 今天要复习的内容放客厅。
  • 明天要复习的放走廊。
  • 已熟悉内容放书房。
  • 长期记忆内容放阁楼或档案室。
  • 高优先级内容发光或贴近入口。
  • 用户看完后点“我记住了 / 我没记住”。
  • AI 根据反馈调整位置。

14.4 AI 能做什么

  • 把用户的笔记压缩成记忆卡。
  • 生成问答。
  • 生成图像提示或类比。
  • 自动安排复习路线。
  • 识别太长的卡片并拆分。
  • 每天生成“10 分钟散步路线”。

14.5 收费方式

  • Solo:$8 到 $15/month。
  • Exam pack:$19 到 $49 一次性,优先做 SAT/MCAT/USMLE/LSAT 或 language learning,而不是国内考试。
  • Pro:$19/month,支持 AI route 和复习记录。

这个方向的难点是用户留存,但一旦做中,订阅很自然。它最适合先做一个极窄海外场景,例如 “Spanish vocabulary memory house” 或 “MCAT visual memory palace”,不要泛化成万能笔记。

15. 超级工具创意 6:Lightweight 3D Museum for Small Cultural Organizations

15.1 产品一句话

为 small museums、local history societies、university archives、cultural nonprofits 做轻量 3D 网页展馆:不用重型三维建模,主要用空间结构、图片、文字、讲解、路线,快速上线可分享。

15.2 为什么这很现实

大量小型文化机构需要“online exhibit”,但预算不一定够做高精 Unity/Unreal,也没有团队维护复杂系统。你可以卖的是:

  • 打开快。
  • 成本低。
  • 能手机/电脑访问。
  • 可自己更新展板。
  • 有平面 SEO 页面。
  • 能嵌入 Markdown/Google Docs/Notion 或管理后台。

这里 openworld-js 的小体积和 signboard 的可编辑,正好是优势。

15.3 AI 能做什么

  • 从讲解稿生成展板摘要。
  • 从照片生成说明文字。
  • 自动生成参观路线。
  • 生成语音讲解稿。
  • 生成不同年龄段版本:kids、visitors、researchers。
  • 自动生成导览问答。

15.4 收费方式

  • Small exhibit setup:$999 到 $4999。
  • Annual maintenance:$999 到 $9999。
  • Multi-exhibit plan:按机构包年。

这类单子客单价更高,但 2 个月内不建议作为主攻,因为海外 B2B 销售周期会长。它更适合作为样板成熟后的第二阶段。

16. 超级工具创意 7:B2B 产品演示空间

16.1 产品一句话

把 SaaS 或硬件产品的功能、案例、客户评价、教程做成一个可逛的 3D Demo Room,销售发给客户,客户可以像看展一样理解产品。

16.2 为什么它可卖

很多 B2B 官网和 PPT 太像了。销售需要一种让客户记住的演示材料。你的 3D 空间不需要像游戏,只要比 PPT 更有停留感,就能服务成交。

16.3 产品结构

  • 入口:一句话价值主张。
  • 左侧房间:痛点。
  • 右侧房间:解决方案。
  • 中央:产品截图。
  • 走廊:客户案例。
  • 二楼:价格和 FAQ。
  • 会议室:预约演示。

16.4 AI 能做什么

  • 根据官网自动生成 Demo Room。
  • 从产品文档提炼卖点。
  • 自动生成客户行业版本。
  • 自动生成销售讲解词。
  • 根据客户行业生成专属参观路线。

16.5 收费方式

  • Single demo room:$499 到 $4999。
  • SaaS subscription:$49 到 $199/month。
  • Enterprise custom:$5000 起。

这对你也有反向价值:你可以用自己的产品演示空间卖自己的产品。

17. 超级工具创意 8:网页收藏的 3D 陈列柜

17.1 产品一句话

把用户散落在 browser bookmarks、Readwise、Raindrop、Pocket、RSS、Markdown 里的链接,AI 自动整理成一个 3D 陈列柜。不是替代搜索,而是让好东西重新被看见。

17.2 真实痛点

很多人收藏了几千个链接,但几年不看。不是因为没有搜索,而是因为忘了自己收藏过什么。空间陈列柜解决的是“偶遇”,而不是效率检索。

17.3 产品机制

  • 收藏链接导入。
  • AI 抽标题、封面、摘要。
  • 同主题放同一墙。
  • 最近想看的放入口。
  • 长期收藏放书架。
  • 用户每次打开都有“今日路过 10 个旧收藏”。

17.4 收费方式

  • Browser extension + 3D space:$8/month。
  • Local lifetime:$49 一次性。
  • 高级 AI 整理:按量收费。

这个方向偏 C 端,难度在增长和留存,但作为你个人使用的原型非常顺手。你自己就是第一用户。

18. 哪个创意最该先做

我按“现有代码复用度、可收费速度、差异化、开发复杂度”排序:

第一优先:Lark / Notion / Docs / Markdown 一键变 3D Knowledge Villa
原因:你已经有 Lark/Feishu 读取原型、signboard 编辑、SaaS 外壳。这个最能把三者连起来。海外 MVP 明确,可演示,可卖给 newsletter writer、course creator、worldbuilder。

第二优先:Researcher 3D Authority Site
原因:适合代建收费。你可以先手工做样板,收第一批定制钱,不必等完整 SaaS。

第三优先:AI Course Museum
原因:海外 educator/course creator 付费意愿更强,但需要好样板。

第四优先:Worldbuilding Story Bible
原因:海外潜力好,社群清晰,适合 Reddit/Discord/YouTube demo。

第五优先:Lightweight 3D Museum for Small Cultural Organizations
原因:客单高,但海外销售周期更长,2 个月内不适合作第一现金流。

暂缓:泛 ADHD 空间复习屋、网页收藏陈列柜
原因:想象力强,但 C 端留存难。可以作为长期方向,不作为第一现金流。

19. 最推荐的具体路线:先做“Docs/Markdown -> 3D Knowledge Villa”

19.1 2 个月内见效果的约束

你补充了一个很重要的时间约束:最好 2 个月内能见到效果。这里的“效果”不应该定义成系统完美,而应该定义成:

  • 有一个英文落地页能被陌生人看懂。
  • 有一个可录屏的 3D Knowledge Villa 样板。
  • 有一个内容源导入到 signboard 的半自动流程。
  • 有 20 到 50 个海外目标用户被触达。
  • 有 3 到 5 个深度反馈。
  • 最理想是拿到第一笔 $99 到 $499 的 setup 订单,或至少拿到 waitlist / email。

所以 8 周内不做:

  • 完整多用户 OAuth。
  • 完整 Notion 双向同步。
  • 复杂多人协作。
  • 自由建造器商业版。
  • 无限模板系统。
  • 大规模重构生产 signboard server。

8 周内只做“可展示、可导入、可收费询价”的 overseas-first MVP。

19.2 第 1 周目标

不要动生产服务器核心。先做一个导入脚本或 SaaS 后台实验页:

  1. 输入 Markdown / Lark 文档 URL,先用你已有 feishu_test 逻辑跑通一个内容源。
  2. 把返回 Markdown/正文切成 20 到 80 张卡。
  3. 生成 boards JSON。
  4. POST /api/signs 写到本地 signboard server。
  5. 打开 openworld 页面看效果。

这里 AI 可以先手工 mock。第一周的目标不是完美自动布局,而是证明“内容源变墙上卡片”。

19.3 第 2 周目标

做固定模板:

  • 入口 4 块总览板。
  • 走廊 12 块目录板。
  • 房间 A/B/C 各 20 块正文板。
  • 图片板自动挑出来。
  • 每块板的 extra 存原文、内容源 URL、段落 hash、备注。

同时给 hotinfo 的全文模态框适配 extra.fullText,这样墙上显示短摘要,点开看全文。

19.4 第 3 周目标

接入 SaaS:

  • 登录后创建项目。
  • 保存内容源 URL。
  • 生成项目 boards。
  • 项目页显示 2D 列表。
  • 提供“打开 3D 世界”按钮。
  • 免费项目限制 boards 数量。

这里先不必改 openworld 太多。可以通过 URL 参数或 localStorage 指向不同 API base。

19.5 第 4 周目标

做第一个样板站:

  • 选一个你自己的高质量文章或资料。
  • 生成 3D 知识别墅。
  • 平面页写清楚:这是把长文档变成可逛空间的工具。
  • 录屏。
  • 找 20 个英文知识博主、newsletter 作者、course creator、worldbuilding 创作者私聊。
  • 提供 3 个免费或低价代建名额,换反馈和案例。

19.6 第 5 到 6 周目标

把样板变成能卖的海外站:

  • 英文域名和 landing page。
  • H1 不要抽象,建议直接叫:Turn your notes into a walkable 3D knowledge space
  • 展示 30 秒录屏 GIF 或视频。
  • 放 3 个 use cases:course, worldbuilding, research archive。
  • 放价格:$99 early setup$499 done-for-you
  • 放 waitlist / Stripe payment link / Calendly。
  • 写 3 篇 SEO 文章:
    • 3D knowledge base for visual thinkers
    • Memory palace software for writers
    • Turn Notion pages into an interactive knowledge museum
  • 到 Reddit、Indie Hackers、Hacker News Show HN、Product Hunt upcoming、worldbuilding 论坛试探。

19.7 第 7 到 8 周目标

验证是否有现金信号:

  • 如果有人愿意付 $99 到 $499,请先手工交付,不要急着自动化。
  • 如果没人付钱但有人愿意留邮箱,继续调整定位。
  • 如果点击很多但没人留邮箱,落地页表达有问题。
  • 如果大家只说 cool 但没人要,说明展示很酷但场景不尖,要缩到一个人群,例如 worldbuilders 或 course creators。
  • 如果有人问能否导入 Notion,就优先做 Notion/Markdown importer,而不是继续加 3D 功能。

19.8 第一个收费版本

不要等全自动。直接卖代建:

  • Early setup:$99,1 篇长文/1 个小展馆/最多 60 块板。
  • Standard:$499,一组 Notion/Docs/Markdown 文档/最多 200 块板/一个公开链接。
  • Studio:$1999,定制建筑主题/SEO 平面页/后续一次修改。

这个比 $12/month 订阅更适合第一笔收入。订阅等流程稳定后再上。

20. 技术债与改造优先级

20.1 最高优先级:统一服务器地址格式

当前 config.jstab/serverConfig.js 对默认地址的处理不完全一致。建议:

  • 保存时必须带协议。
  • 如果用户输入 127.0.0.1:8899,自动转成 http://127.0.0.1:8899
  • UI 文案写清楚:本地填 http://127.0.0.1:8899,生产填 https://selfdb.ccgxk.com

20.2 高优先级:把管理页 Canvas 残留处理掉

二选一:

  • 暂时删掉 Canvas Tab,避免误导。
  • 或重新实现 canvas API,但要用安全模板,不要任意执行用户 JS。

20.3 高优先级:extra 结构标准化

现在 extra.remark 已经有了。未来建议标准化:

{"remark": "","source": {"type": "feishu","url": "","blockId": "","hash": ""},"fullText": "","summary": "","tags": [],"ai": {"room": "","importance": 0,"lastProcessedAt": ""}
}

这样不改主表,也能先承载飞书同步和 AI 输出。

20.4 中优先级:批量写接口加保护

POST /api/signs 是全量替换。未来至少要加:

  • 管理员权限。
  • 项目隔离。
  • 请求体大小限制。
  • dry-run 模式,先返回将新增/修改/删除多少。
  • 备份版本。

20.5 中优先级:SSE 加项目频道

多项目后不能所有人都收所有 boards。SSE 应变成:

GET /api/projects/:projectId/signs/stream

或者通过 token 绑定 project。

20.6 中优先级:2D 平面页

你的文章已经判断对了:3D 负责逛,2D 负责 SEO 和检索。每块 board 都应该有平面页。平面页包含:

  • 标题。
  • 摘要。
  • 全文。
  • 所在房间。
  • 打开 3D 并传送到该位置。

这个功能会让产品不只是玩具,而是能被搜索、分享、传播。

21. 一个更大胆但可行的终局:空间内容操作系统

终局不要叫笔记软件。笔记软件会把你拖进 Notion、Obsidian、飞书的战场。更好的定位是:

空间内容操作系统,给已有内容一个可逛、可展示、可记忆、可发布的三维外壳。

它的核心对象不是“页面”,而是:

  • 世界 World
  • 房间 Room
  • 墙 Wall
  • 展板 Board
  • 物件 Object
  • 路线 Route
  • 来源 Source
  • 平面页 Page

在这个系统里:

  • 飞书是 Source。
  • SaaS 是管理台。
  • signboard 是 Board API。
  • openworld 是 World Runtime。
  • AI 是 Curator,也就是策展人。

你真正要卖的不是“3D 笔记”,而是“AI 策展 + 3D 展示 + 平面发布”。这个表达更容易商业化,因为客户能理解:

  • 我有一堆内容。
  • 你帮我整理成一个展馆。
  • 这个展馆能分享、能传播、能收费、能让别人记住我。

22. 最后的判断

从源码看,signboard_lab 已经跨过了最危险的一步:不是空想,不是只画一个 3D 场景,而是把“空间对象内容”跑通了。现在最该做的是把它接入一个真实内容来源和一个真实收费外壳。

Lark/Feishu 读取原型证明内容源适配能跑,SaaS 正好是收费外壳,openworld-js 正好是差异化体验。海外站的最小可卖形态,就是 “Docs/Markdown/Notion to 3D Knowledge Villa”。

这条路的关键克制是:不要把 openworld-js 包装成万能 3D 笔记;不要一开始做多人世界;不要一开始做复杂编辑器;不要一开始做自动生成任意建筑。先让用户把一篇长文档变成一个能打开、能逛、能分享、能修改、能让人眼前一亮的空间。

一旦这个样板成立,后面才轮到:

  • AI 自动选址。
  • 多主题模板。
  • 内容源增量同步。
  • 平面 SEO 页面。
  • 订阅。
  • 定制展馆。
  • 海外版本。

你的壁垒不是某个 API,而是你已经把一个轻量 3D 引擎、空间对象、动态画板、实时更新、个人长期知识栖息地这几件事揉在一起了。普通人会把它看成“一个 3D 页面”,但真正的产品直觉是:它可以成为内容的第二居所。

23. 附录:已闭环 API 总表

signboard_lab 生产 API

方法 路径 状态 客户端 作用
OPTIONS * 已实现 浏览器预检 CORS
GET /api/signs 已实现 hotinfo/admin 全量读取 boards
POST /api/signs/batch 已实现 store.lazyLoadSign 按 ID 批量懒加载
POST /api/signs 已实现 admin.html 全量替换保存
PATCH /api/signs/:id 已实现 signPanel 单条 upsert
GET /api/signs/stream 已实现 hotUpdate SSE 实时广播
其他 未匹配 已实现 所有 404 JSON

signboard_lab 前端残留但服务器未闭环

方法 路径 状态 备注
GET /api/canvas-lib 未实现 管理页残留
POST /api/canvas-lib 未实现 管理页残留
POST /api/canvas-lib/add 未实现 管理页残留
DELETE /api/canvas-lib/:name 未实现 管理页残留
DELETE /api/signs/:id 未实现 数据库函数有,HTTP 无

飞书 MVP API

方法 路径 状态 作用
GET /api/cli/status 已实现 检查 lark-cli 配置
POST /api/read 已实现 读取飞书文档
POST /api/append 已实现 向飞书文档追加 Markdown

SaaS 基础 HTTP API

方法 路径 状态 作用
GET /api/user 已实现 当前登录用户
GET /api/team 已实现 当前用户团队
GET /api/stripe/checkout 已实现 Stripe 成功回跳
POST /api/stripe/webhook 已实现 Stripe 订阅事件

SaaS 基础 Server Actions

名称 状态 作用
signIn 已实现 登录
signUp 已实现 注册/接受邀请
signOut 已实现 登出
updatePassword 已实现 修改密码
deleteAccount 已实现 软删除账户
updateAccount 已实现 修改姓名和邮箱
removeTeamMember 已实现 移除团队成员
inviteTeamMember 已实现 创建邀请记录,邮件发送待补
checkoutAction 已实现 创建 Stripe Checkout
customerPortalAction 已实现 打开 Stripe 客户门户

24. 附录:本次审计的关键源码证据

  • openworld-js/open-world-zone/main.js:主世界装载顺序。
  • openworld-js/open-world-zone/plugins/signboard_lab/signTest.js:信息板入口、hook、SSE、热点编辑。
  • openworld-js/open-world-zone/plugins/signboard_lab/store.js:懒加载、批量读取、内存缓存。
  • openworld-js/open-world-zone/plugins/signboard_lab/hotUpdate.js:SSE 客户端、window.updateSign
  • openworld-js/open-world-zone/plugins/signboard_lab/signPanel/signTest.js:编辑面板与 PATCH /api/signs/:id
  • openworld-js/open-world-zone/plugins/signboard_lab/hotinfo/hotinfo.js:展示模式热点信息与 GET /api/signs
  • openworld-js/open-world-zone/plugins/signboard_lab/server/server.js:HTTP 路由总表。
  • openworld-js/open-world-zone/plugins/signboard_lab/server/api/signs.js:signs API 实现。
  • openworld-js/open-world-zone/plugins/signboard_lab/server/db/index.js:SQLite 表、CRUD、迁移。
  • openworld-js/open-world-zone/plugins/signboard_lab/server/sse.js:SSE 连接和广播。
  • 1tool/feishu_test/server.js:飞书 CLI API。
  • 1tool/feishu_test/public/index.html:飞书 MVP 前端调用。
  • z-nextjs/saas-start/app/api/user/route.ts:当前用户 API。
  • z-nextjs/saas-start/app/api/team/route.ts:当前团队 API。
  • z-nextjs/saas-start/app/api/stripe/checkout/route.ts:Stripe checkout 回跳。
  • z-nextjs/saas-start/app/api/stripe/webhook/route.ts:Stripe webhook。
  • z-nextjs/saas-start/app/(login)/actions.ts:认证和团队 Server Actions。
  • z-nextjs/saas-start/lib/payments/actions.ts:支付 Server Actions。
  • z-nextjs/saas-start/lib/db/schema.ts:SaaS 数据模型。

25. 追加:5 个更激进的海外创意

这次追加的 5 个创意,不再只是“把资料放进 3D 空间”。海外相邻产品已经说明,普通 3D gallery 不稀奇:Menel、OpenVGAL、Exospace、Exhibbit 这类产品都已经在做 “images to 3D gallery / virtual exhibition”。Worldbuilding 领域也有 Neverkin、TomeWorlds、WorldKeeper、PlotForge 这类工具在做 story bible、timeline、AI world generation。Memory palace 方向也已有移动端和 VR/AI 记忆训练产品。

所以你的新创意不能只是“我也做一个 3D 展馆”。真正要避开正面竞争,应该抓住你现在已有但别人没有强调的三个点:

  • 内容源自动策展:不是手动上传图片,而是从已有 Docs/Markdown/RSS/Notion/Readwise 里抽内容。
  • 空间对象 API:每块板都有 ID、内容、extra、SSE、编辑回写,不是一次性静态展览。
  • 2D + 3D 双通道:3D 负责记忆、逛、情绪,2D 负责全文、SEO、交易、检索。

下面 5 个创意都按海外站优先、2 个月内可做出样板信号来设计。

25.1 创意 9:Knowledge Escape Room for Learning

一句话:把课程、培训文档、newsletter archive 自动变成一个“知识密室逃脱”。用户必须读懂墙上的信息板、打开全文、回答问题、找到线索,才能进入下一间房。

这个点子比“3D course museum”更强,因为它不只是展示,而是把学习变成可验证的路径。传统课程的问题是:学生打开视频,但不知道有没有真的吸收。普通 quiz 又太像考试,压力大、无趣。Knowledge Escape Room 把 quiz 藏进空间里:一个知识点是一把钥匙,一个概念关系是一条暗门线索,一个错题会把用户送回对应房间。

它的特别之处:

  • 用户不是“看完一页”,而是“走出一个房间”。
  • AI 不是简单总结,而是把内容转成谜题、线索和门锁。
  • 3D 空间不是装饰,而是学习状态机。
  • 每个 board 都是可更新的知识对象,SSE 可让老师/作者实时调整谜题。

适合海外客户:

  • Course creators:把 paid course 做成 bonus interactive room。
  • Corporate onboarding:把 boring handbook 变成 20 分钟闯关。
  • Language tutors:把词汇、语法、情景对话做成关卡。
  • Cybersecurity / compliance trainers:让员工在空间里找风险点。

MVP 怎么做:

  1. 导入一篇 Markdown 或 Lark/Docs 文档。
  2. AI 生成 20 张知识板、5 道题、3 个门。
  3. 用户点击热点打开全文,然后在 2D modal 里答题。
  4. 答对后把 extra.unlocked = true 写入 board 或 session。
  5. 空间里下一扇门从 hidden 变 visible。

当前代码怎么接:

  • 题目和答案可以存在 extra.quiz
  • 门的状态可以先做成前端 localStorage,不急着入库。
  • 正文仍然用 content + extra.fullText
  • PATCH /api/signs/:id 可让作者在 3D 里调整题目说明。

2 个月内如何验证:

  • 做一个 “AI Safety Basics Escape Room” 或 “Spanish Prepositions Escape Room” 样板。
  • 发到 Reddit 的 r/SideProject、r/InternetIsBeautiful、r/languagelearning、Indie Hackers。
  • Landing page 文案:Turn your boring docs into a playable learning room.
  • 先卖 $99 setup:用户给一篇培训文档,你交付一个可玩的 room。

为什么可能有钱:

普通课程工具很多,但“把文档变成 playable room”的表达新,适合创作者当 bonus content 卖。第一批不靠订阅,靠 done-for-you。只要 2 个月内拿到 1 到 3 单 $99-$499,就说明方向有现金味。

风险:

  • 谜题太难会劝退。
  • 3D 操作如果不顺会影响学习。
  • 所以第一版必须极简:三间房、五道题、十分钟完成。

25.2 创意 10:Spatial Newsletter Companion

一句话:给 newsletter 作者一个“每期文章自动生成一个可逛小房间”的 companion page。读者读完邮件后,可以进入 3D 房间复习本期关键观点,旧文章会逐渐形成一座可逛的思想馆。

这个创意看起来小,但很适合海外。Substack、Beehiiv、ConvertKit 作者很多,他们都面临同一个问题:文章发出去后很快沉底。读者看过就忘,作者过去 100 篇文章也很难被系统性发现。传统 archive 是列表,没人愿意翻。你的空间可以把 archive 变成“作者的思想建筑”。

核心机制:

  • 每期 newsletter 生成一个 room。
  • 文章标题变门牌。
  • 3 到 7 个核心观点变墙面 boards。
  • 推荐阅读变走廊出口。
  • 作者可以把最重要的一期放到入口。
  • 读者从最新一期走回旧主题,形成“思想路径”。

为什么比普通 3D gallery 有差异:

  • gallery 展示的是图片作品,newsletter companion 展示的是思想结构。
  • 它不是替代邮件,而是给邮件一个长尾复习空间。
  • 每一期都是一个可分享 landing asset,可带来 SEO 和社交传播。

MVP 怎么做:

  1. 先不接 Substack API,用户粘贴一篇 Markdown。
  2. AI 输出:
    • issueTitle
    • oneSentence
    • keyIdeas[]
    • quoteCards[]
    • relatedLinks[]
  3. 写入 boards。
  4. 生成一个 /{creator}/{issueSlug}/world
  5. 平面页给 SEO,3D 页给体验。

2 个月内验证:

  • 选 3 篇你自己的文章或公开英文长文,做成样板。
  • 私信 30 个 newsletter 作者,尤其是写 AI、learning、PKM、worldbuilding、history 的。
  • 提供 I will turn one of your best essays into a walkable idea room for free / $99

定价:

  • Free sample:1 篇文章。
  • Creator:$12/month,每月 4 个 issue rooms。
  • Archive setup:$499,把 30 篇旧文章做成一座小型思想馆。

为什么这个很可能比泛知识库更快见效:

newsletter 作者已经懂内容资产、懂 landing page、懂付费订阅。他们会理解“让旧文章重新被发现”的价值。你的工具不是卖给所有读者,而是卖给有内容资产的创作者。

风险:

  • 作者可能觉得 3D 是 gimmick。
  • 解决方法是不要说 metaverse,不要说 VR。说:a memorable interactive archive for your best ideas

25.3 创意 11:Investor Update War Room

一句话:把 startup 的 monthly investor update、metrics、roadmap、customer quotes、demo links 变成一个私密 3D war room,让投资人和顾问像进入作战室一样理解公司进展。

这个方向很怪,但有潜力。创始人每月发 investor update,通常是邮件、Notion、DocSend、Slides。问题是这些材料都很平,读者扫一眼就过。一个 war room 可以把公司状态“空间化”:

  • 左墙:本月指标。
  • 右墙:客户证据。
  • 中央:产品 demo。
  • 后墙:roadmap。
  • 桌面:asks,告诉投资人本月需要什么帮助。
  • 角落:risk board。

这不是给大众看的,而是给少数高价值关系看的。B2B 小工具最怕没有付费场景,但 startup founder 愿意为 fundraising、investor relations、sales narrative 付费。

AI 能做什么:

  • 从 update 文档里抽 metrics。
  • 把好消息、坏消息、asks 分区。
  • 把数字变成可读展板。
  • 生成 investor-friendly narrative。
  • 自动生成 “3-minute tour route”。
  • 对过长内容生成 “board version” 和 “full memo version”。

MVP 怎么做:

  1. 创始人粘贴 monthly update Markdown。
  2. AI 生成 war room boards。
  3. 生成私密链接,需要简单 token。
  4. 每个 board 有 full text modal。
  5. 访问后记录基本 analytics:访问次数、停留时间、打开了哪些板。

当前代码适配:

  • boards API 已能承载指标、quote、roadmap。
  • SaaS 已有 team 和 auth,可做私密项目。
  • Stripe 可收 setup fee。
  • 不需要复杂 3D 建模,一个固定会议室模板即可。

2 个月验证:

  • 做一个虚构 startup 的 war room demo。
  • 发到 Indie Hackers、founder Slack/Discord、X。
  • 私信早期 SaaS founder:I turn your monthly investor update into a private interactive war room.
  • 收 $199-$999 setup。

为什么这个可能比教育更快有钱:

创始人买的是“让投资人记住我”和“显得专业”,不是买学习工具。只要样板有冲击力,单价可以高。它不需要大量用户,2 单就能验证。

风险:

  • 隐私和安全要求更高。
  • 第一版不要碰敏感真实数据,先允许用户自行部署或静态导出 ZIP。
  • 对外强调 private link / static export / no indexing。

25.4 创意 12:Semantic Sales Battle Room

一句话:销售团队上传竞品页面、客户电话纪要、FAQ、案例,AI 生成一个 3D Sales Battle Room。销售在拜访客户前走一遍路线,就能记住 objection handling、竞品对比和最佳话术。

这个创意不是普通 CRM,也不是普通 sales enablement 文档。销售真正的问题不是没有资料,而是资料散、临场想不起来。空间路线很适合做“战前演练”:

  • 第一间:客户画像。
  • 第二间:痛点。
  • 第三间:竞品反驳。
  • 第四间:案例证据。
  • 第五间:价格异议处理。
  • 出口:本次 call 的 5 个关键句。

AI 的价值:

  • 从销售资料里提炼 objections。
  • 把每个 objection 绑定一张 answer card。
  • 根据客户行业生成专属路线。
  • 自动把成功案例放到相关异议旁边。
  • 生成 “before-call 5-minute walkthrough”。

为什么这很有创意:

多数 sales enablement 是文档库、搜索、AI chat。AI chat 的问题是销售还要问对问题;空间 route 则把“该复习什么”预先排好。它更像认知训练,而不是资料库。

MVP 怎么做:

  1. 用户上传一个 Markdown:包含 product、competitors、FAQ、case studies。
  2. AI 生成 30 张 battle cards。
  3. 固定一个 war room 模板。
  4. 每张 card 可点开全文。
  5. 增加 “start 5-minute route” 按钮,按顺序高亮 boards。

当前代码适配:

  • extra.routeIndex 存路线顺序。
  • extra.customerSegment 存行业版本。
  • content 存短话术。
  • extra.fullText 存完整解释。
  • SSE 可让销售经理更新 battle cards 后,团队前端实时看到。

2 个月验证:

  • 做一个 “AI writing SaaS vs competitors” demo。
  • 找 indie SaaS founder、solo sales、agency owner。
  • 文案:A walkable sales battlecard room your team can rehearse before calls.
  • 收费:$499 setup,或 $49/month per team。

风险:

  • 企业销售周期长。
  • 所以前 2 个月不要卖大企业,卖 indie SaaS founder、agency、consultant。

25.5 创意 13:Digital Legacy House

一句话:把一个人的照片、文章、录音、信件、人生事件、作品整理成一个私密或公开的 3D Digital Legacy House。它不是相册,也不是纪念网页,而是一个可走进去的个人记忆空间。

这个创意比较情绪化,但海外市场有真实付费可能。很多家庭、创作者、艺术家、教授、创业者都有一堆散落资料:Google Drive、照片、博客、采访、邮件、演讲稿。普通 memorial website 是平面的,Notion archive 又像文件柜。Digital Legacy House 把人生按房间组织:

  • Entrance:一生概览。
  • Study:文章和手稿。
  • Gallery:照片。
  • Voice room:录音和访谈。
  • Timeline hallway:重要年份。
  • Guestbook room:亲友留言。
  • Works room:作品和项目。

AI 能做什么:

  • 从资料中抽时间线。
  • 给照片生成说明。
  • 把文章按主题分房间。
  • 从录音转写中抽关键语句。
  • 生成每个房间的导览词。
  • 生成 privacy-safe public version 和 family-only version。

为什么它和你的项目匹配:

你的第一性原理是“在墙上写字、贴照片”。Digital Legacy House 就是这个原理最直观、最有情感价值的版本。它不要求极高效率,也不需要复杂交互。它需要的是“人愿意进入一个属于某个人的空间”。这和你文章里的“人愿意长期投入属于自己的空间”完全一致。

MVP 怎么做:

  1. 用户提供 20 张图片、5 段文字、1 条时间线。
  2. 生成固定 house 模板。
  3. 每张照片变 image board。
  4. 每段文字变 text board。
  5. 2D 平面页负责完整文字和分享。
  6. 可选择 public/private。

2 个月验证:

  • 不要一开始碰沉重的 memorial 场景,先定位为 Digital Legacy House for creators and families
  • 做一个虚构 creator 的样板,或用你自己的公开资料做一个 founder archive house
  • 找 biography writers、family historians、artists、professors、photographers。
  • 收费:$499-$2999 done-for-you。

风险:

  • 情感和隐私敏感,不能轻浮。
  • 第一版必须明确:用户拥有数据,可导出静态文件,默认私密,不训练模型。

这个方向不一定适合 2 个月内第一现金流,但它可能是长期最高情感溢价的方向。普通人不一定为知识管理付钱,但会为“把某个人的一生好好保存下来”付钱。

26. 追加创意的优先级判断

如果只看 2 个月内见效果,追加的 5 个里我会这样排:

  1. Spatial Newsletter Companion:最适合冷启动。newsletter 作者有内容、有受众、有付费意识,样板容易做。
  2. Knowledge Escape Room for Learning:最适合录屏传播,标题新,容易让人点进去看。
  3. Investor Update War Room:最适合拿高单价,但要更会销售。
  4. Semantic Sales Battle Room:B2B 价值强,但 2 个月内要避开大企业。
  5. Digital Legacy House:长期情感价值强,但需要更谨慎的品牌表达。

这 5 个里面,最“快”的不是最宏大的 Digital Legacy House,而是 Spatial Newsletter Companion。因为你可以很快做出一个英文样板:拿一篇文章,自动拆成 8 块板,放进一个小房间,再给作者一个 URL。它有明确目标人群,有冷启动渠道,有 $99 setup 的交易形态。

最适合做 viral demo 的是 Knowledge Escape Room。它可以录屏:走进房间,看墙上知识点,答对题,门打开。这个比“我做了个 3D 知识库”更容易让陌生人理解。

最可能提高客单价的是 Investor Update War Room。创始人如果愿意买,可能不会纠结 $99 和 $499 的差别,因为他买的是叙事资产和专业感。

最终建议:不要把这 5 个全做。2 个月内最多做一个主线、一个展示变体。主线继续用 Docs/Markdown -> 3D Knowledge Villa,展示变体可以选择 Knowledge Escape Room,因为它能把同一套 boards API 变成更有传播力的 demo。

27. 追加创意参考的海外相邻产品

这次追加时,我快速看了几个海外相邻产品,目的不是照抄,而是避免把已有市场里常见的 3D gallery / story bible / memory palace 重新包装一遍:

  • Menel:浏览器 3D gallery builder,强调 artists、galleries、museums、share with one link。https://www.menel.art/
  • OpenVGAL:开源 3D virtual gallery,从图片生成可自托管 WebGL gallery。https://openvgal.com/
  • Exospace:面向 artists/galleries 的 3D exhibition 创建工具。https://exospace.gallery/
  • Exhibbit:in-browser 3D virtual art gallery platform,强调 curate、publish、promote。https://exhibbit.com/
  • Neverkin:collaborative writing and worldbuilding app。https://neverkin.com/
  • TomeWorlds:面向 authors、novelists、TTRPG creators 的 worldbuilding companion。https://www.tomeworlds.com/
  • WorldKeeper:AI worldbuilding and storytelling software,强调 AI world generation、characters、places、agent API。https://worldkeeper.io/
  • Mind Palace: Memory Trainer:App Store 上的 method of loci / AI memory palace 类产品。https://apps.apple.com/us/app/mind-palace-memory-trainer/id6758350669

这些参照说明:海外已经有人做虚拟展馆、写作世界观、记忆宫殿。你的机会不在“也做一个 3D 房间”,而在“已有内容源 -> AI 策展 -> 空间对象 API -> 2D/3D 双通道发布”这条组合链。

http://www.jsqmd.com/news/741460/

相关文章:

  • 【深度解析】Codex 从代码助手到 AI Coding Workspace:浏览器验证、权限闭环与自动化审查实战
  • 告别轮询!用STM32CubeMX给STM32F072配置ADC+DMA,实现后台无感数据采集
  • Certificate Lifecycle Management:从理论到实践的完整指南
  • 手把手教你修复iText PDF的‘trailer not found’错误(附PDF模板保护指南)
  • 从太阳镜到光纤通信:深入浅出聊聊偏振技术如何影响我们的数字生活
  • ARMv8调试寄存器详解:断点与观察点控制
  • 2026宜宾别墅搬家技术指南:宜宾喜来乐搬家/宜宾店铺搬迁/宜宾异地搬家/宜宾搬迁厂房/宜宾机器搬迁/宜宾设备搬迁/选择指南 - 优质品牌商家
  • 歌词滚动姬终极指南:免费快速制作完美LRC歌词的完整流程
  • 告别原型!AI 工程化的 3 个生死线,90% 开发者都踩过的坑
  • 部署与可视化系统:26届秋招避坑:Gradio 自定义 CSS 界面美化与异步函数解决大模型长时间推理阻塞问题
  • 2026四川室外健身器材厂家名录:四川健身器材公司、四川健身器材批发厂家、四川健身房健身器材、四川室外体育健身器材选择指南 - 优质品牌商家
  • 2026届学术党必备的AI辅助写作神器实际效果
  • 别再手动更新了!用MATLAB Requirements Manager自动同步Excel需求文档(附ASPICE追溯实战)
  • Bioicons:科研绘图的革命性图标库 - 3000+免费可编辑生物科学矢量图标完全指南
  • Aieditor编辑器使用require.js集成到内容管理系统
  • 【深度解析】从 Claude Jupiter 到 ARC-AGI 3:大模型发布信号、评测体系与多模型工程接入实践
  • 毕设日志26.5.2(1):开发板睡眠模式
  • Visual C++运行库终极指南:一劳永逸解决Windows软件兼容性问题
  • 工业物联网LoRaWAN控制终端应用与配置指南
  • 加速!英伟达要招聘会AI的芯片工程师了
  • ROS2 C++开发系列07-高效构建机器人决策逻辑,运算符与控制流实战
  • 证书自动化解决方案选型:技术、成本与合规的平衡之道
  • YimMenu终极使用指南:从零开始掌握GTA5开源辅助工具
  • StarRailCopilot:崩坏星穹铁道全自动脚本终极解决方案
  • Java流程编排框架TaskFlow:3个技巧让复杂业务逻辑变得简单高效
  • 2026成都诚信控制电缆优质厂家推荐:电线电缆品牌十大排名、电缆厂家十大排名、矿物质防火电缆厂家、铜芯电缆厂家排名选择指南 - 优质品牌商家
  • OpenClaw Hub:统一AI网关与智能调度,降低90%大模型调用成本
  • 掌握Cura 3D切片软件:从零开始打造完美打印体验的5个关键步骤
  • XUnity.AutoTranslator:让游戏语言障碍消失的7个智能翻译技巧
  • AI Agent在客户服务中的最新研究进展有哪些