# 无界笺 Boundless 一张可以无限延伸的灵感平面,自部署在自己的服务器上。所有内容保存在服务器里,手机、平板、电脑打开的都是同一张画布;在一台设备上修改,其他打开着同一空间的设备会立刻看到变化。 ## 功能 - 无限画布:平移、缩放、小地图、框选、对齐与均分 - 文字便笺与图片卡片:创建、编辑、移动、缩放、复制、换色、连线 - 多个空间(标签),每个空间有独立的地址 `/s/<空间 id>` - **多端实时同步**:基于 Yjs CRDT,多台设备同时编辑也不会互相覆盖 - **断网可用**:离线时的修改保存在本机,联网后自动同步 - **撤销只针对本机**:不会把其他设备的修改一起撤掉 - **历史版本**:编辑时每 10 分钟自动存一个版本,也可以手动保存,一键恢复 - **全局搜索**:搜索当前空间并跳转,同时列出其他空间里的匹配卡片 - 在线设备:查看哪些设备在线、各自打开的是哪个空间 - 口令登录:单用户,修改口令后所有设备自动退出 - 图片上传到服务器;过大的照片会在上传前自动压缩 - 随机油画加载动画(见下方致谢) ## 技术栈 - 前端:Vue 3 + TypeScript、Vite 8、Vue Flow、Pinia、Tailwind CSS 4 - 同步:Yjs、Hocuspocus(WebSocket)、y-indexeddb(本机离线缓存) - 服务端:Node.js(直接运行 TypeScript)、Hono、node:sqlite - 测试:Vitest、Playwright ## 本地开发 需要 Node.js 22.18+ 或 24.12+,推荐 Node.js 24 LTS。 ```sh pnpm install cp .env.example .env # 可选;不设置时开发口令为 boundless pnpm dev # 同时启动服务端(3000)与 Vite(5173) ``` 浏览器打开 。服务端数据默认存放在 `./data/`。 ## 检查项目 ```sh pnpm build # 类型检查 + 构建 pnpm test:unit -- --run # 单元测试 pnpm exec playwright install chromium # 首次运行 e2e 前 pnpm exec playwright test --project=chromium # 端到端测试(会自动构建并启动服务端) pnpm lint ``` ## 部署(Docker) ```sh echo "BOUNDLESS_PASSWORD=换成你的口令" > .env docker compose up -d --build ``` 服务监听 `127.0.0.1:3000`,数据保存在 `./data/`(SQLite 数据库、图片和会话密钥)。**备份整个 `data/` 目录即可完整备份。** 前面需要一个 HTTPS 反向代理,并且要支持 WebSocket。Caddy 最简单(自动申请证书,并会自动转发 WebSocket): ```caddyfile board.example.com { reverse_proxy 127.0.0.1:3000 } ``` Nginx 需要显式转发 WebSocket 和 Host: ```nginx location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 1d; client_max_body_size 25m; } ``` ### 环境变量 | 变量 | 说明 | 默认值 | | -------------------- | ------------------------------------------- | ------------------- | | `BOUNDLESS_PASSWORD` | 登录口令(生产环境必填) | 开发时为 `boundless` | | `BOUNDLESS_SECRET` | 会话签名密钥 | 自动生成并存入数据目录 | | `DATA_DIR` | 数据目录 | `./data` | | `PORT` / `HOST` | 监听端口与地址 | `3000` / `0.0.0.0` | | `SESSION_DAYS` | 登录有效天数 | `90` | | `MAX_IMAGE_MB` | 单张图片大小上限 | `20` | 不用 Docker 时:`pnpm install && pnpm build-only && BOUNDLESS_PASSWORD=... pnpm start`。 ## 致谢 加载动画来自 [Painting Loaders](https://painterly.design-tools.workers.dev)(作者 [Sasha](https://x.com/aleksksaa)),12 幅画作的绘制代码原样收录在 `public/painterly/`,基于 [p5.js](https://p5js.org)(LGPL-2.1)与 [p5.brush](https://github.com/acamposuribe/p5.brush)(MIT)。