啡跃 Endoleap

本地 Next.js App Router + TypeScript + Tailwind CSS + shadcn/ui 项目。首页采用留白、黑色主按钮、衬线标题与线稿画布预览;账户页保留原有布局。工作台使用合并后的单侧栏。

项目目录:/Users/zzyang/endoleap。

启动

npm ci
npm run dev

默认仅监听本机 localhost:17321。生产模式:npm run build && npm start。

  • 首页:/(未登录显示 landing page;有效登录会话跳转 /dashboard)
  • 登录、注册:/login
  • 登录回调:/auth/callback
  • 真实工作台:/dashboard
  • 本地演示:/dashboard?demo=1
  • 无限图谱:/dashboard/{workspace}/{board}

路由结构

  • src/app/layout.tsx:根布局、中文语言标记、全局样式与页面元信息。
  • src/app/page.tsx:首页。
  • src/app/login/page.tsx、src/app/auth/callback/page.tsx:账户页与登录回调。
  • src/app/dashboard/layout.tsx:共享单侧栏;page.tsx 保留空白工作区。
  • src/app/dashboard/dashboard.tsx:侧栏收起/展开、页面搜索、新建图谱与底部账户弹出框。
  • src/app/dashboard/[workspace]/[board]/page.tsx:按 workspace 和图谱 ID 打开页面,重新读取后端资料。
  • src/components/ui/icon-button.tsx:Lucide 图标按钮,图标为 16×16px,上下 4px、左右 6px 内边距,总尺寸为 28×24px。
  • src/app/api/**/route.ts:Foundry 代理与 OAuth 跳转,使用 App Router Route Handlers。

配置

复制 .env.example 为 .env.local,按实际部署填写:

  • FOUNDRY_API_ORIGIN:仅供 Next 服务端请求后端,默认 https://api.foundry.entroia.com。
  • NEXT_PUBLIC_FOUNDRY_PROJECT:项目标识,默认 endoleap。

Slack Client Secret、Signing Secret、Verification Token、用户令牌与 app token 均不需要放入此前端。浏览器调用同源 Next API,由服务端转发到 Foundry。Foundry 会话保存在 HttpOnly / SameSite=Lax Cookie,生产 HTTPS 反向代理需传 X-Forwarded-Proto=https。不要将原始会话写入客户端存储。

Google / Slack 的提供方回调仍是 Foundry 后端地址;后端的项目回调映射必须指向本前端 /auth/callback。协议、主机名、端口必须与启动第三方登录时一致,否则 sessionStorage 中的 verifier 无法恢复。正式账号授权、邮件验证与 OAuth 全流程尚未完成真人验收;HTTP 302 跳转成功不能代表登录成功。

当前功能与范围

  • 响应式首页、锚点导航与 FAQ。
  • 邮箱注册 / 登录 / 邮件验证兑换,Google 和 Slack 的 PKCE 登录入口及回调处理。
  • 真实用户资料、空间列表与创建、画布列表与创建。资料和空间并行读取;首次创建画布时自动建立个人空间。
  • 单侧栏第一行提供完全收起/恢复与新建页面,第二行为当前空间页面列表搜索。画布列表包含可展开的父子画布目录,搜索保留祖先路径,直接打开子图时自动展开所在目录。侧栏使用 Motion for React 14.9.1 实现 240ms 开关动画,尊重系统减少动态效果偏好,收起后保留左上角快捷浮框。
  • 账户菜单分为工作空间概览、账户设置、用户资料与空间切换、新建工作空间、退出登录;账户设置和新建空间均接入 Foundry。菜单文字和行距参考 Notion 收紧,工作空间分组标题保留浅灰色。
  • 底部按钮、账户菜单和设置面板使用 Foundry profile.avatar_url 提供的 Google 头像;无头像或图片加载失败时显示姓名首字。
  • 新建页面使用 Foundry Core 的 POST /workspaces/{workspace}/materials,提交 kind: board、默认名称“未命名图谱”和内容版本;由后端生成 ID。没有空间时先创建“个人空间”,成功后跳转到图谱的独立地址。
  • 本地演示提供示例图谱、搜索、新建和浏览器保存,支持图谱独立地址与刷新。
  • 图谱页面使用 React Flow 12.12.1,支持空白处平移、节点拖动、连线、多选、缩放和文本编辑。文字、脚本、图片节点和创作模板可从底部悬浮工具栏插入。
  • 右上角悬浮框提供撤销、重做、缩放、恢复 100%、适应画布和 JSON 导出;底部支持 JSON 导入及操作帮助。
  • 真实图谱先读取 Core Canvas 快照,再开放编辑;节点、样式、连线与视图以独立版本串行自动保存。旧本地草稿需用户明确选择恢复;版本冲突停止覆盖并保留恢复记录。演示模式仅本地保存。支持 Core Canvas V1/V2;V2 分区是真实子画布,内部内容按所属画布独立保存。
  • 分享、Agent、收藏、自由绘图及多人协同尚未接入。画布覆盖整个视口,侧栏和快捷浮框覆盖其上;演示数据不写入线上。
  • 收起侧栏后,左上角浮框显示 Logo 和用户头像;头像与展开侧栏底部的账户按钮打开同一个菜单。
  • 本地演示仅用于查看界面,不提供后端认证与权限。

Figma 原始 Logo、人物插画与图标已下载到 public/assets,不依赖临时 Figma URL。品牌保持啡跃 Endoleap;shadcn Button / Dialog 使用官方 registry 源码。依赖版本固定,package-lock.json 可用于 npm ci。

验证

npm run build
node tests/api-smoke.mjs

API 测试使用本机临时后端和独立前端进程,检查会话 Cookie、令牌不泄漏、同源校验和路径白名单,不访问线上账号。构建需先完成。冒烟测试还覆盖所有页面地址、元信息、OAuth 跳转、请求体限制及退出会话。此前的浏览器验收覆盖登录/注册切换、演示画布创建、搜索空状态、笔记保存、桌面与 390px 手机布局;本次迁移的验证结果见 VALIDATION.md。

若执行环境限制 Turbopack 的 CSS 工作进程绑定本地端口,可使用官方 Webpack 模式:npm run build -- --webpack。

项目已同步至 ssh://git@gitea.entroia.com:22222/Zayden-Jung/Endoleap.git;尚未部署。

性能分析、实测耗时和修复说明见 PERFORMANCE.md。 流程回归可在支持 TypeScript 类型擦除的 Node 版本执行:node --experimental-strip-types --test tests/workspace.test.mjs。

品牌资源

public/brand/ 原样复用旧 PROMPT 仓库 Zayden-Jung/probably-rendering-one-more-pixel-tonight 的 packages/brand/assets/,来源提交 47467874841ea7f7b4b362d4ec0e66f236c6a7d6。

共 88 个原始资源:6 套 PNG(logo/icon/mono 的 light 与 dark 版本,每套 16、24、32、48、64、128、180、192、256、512、1024、2048px),8 个 SVG,以及 8 个应用图标文件(含 3 种 ICO、Apple Touch 和 PWA PNG)。所有文件与来源 Git blob 哈希一致。

收起侧栏后的浮框使用 Logo 返回 /;展开侧栏后仍保留新建页面按钮。首页与账户页品牌组件使用原始 SVG,根布局声明 ICO、深浅色 PNG favicon 和 Apple Touch 图标。

画布操作

  • 单击选择,双击编辑文本或卡片名称。纯文本与图片可整块拖动;选中时四侧连接点可拖线。
  • 触控板滚动平移,Ctrl / ⌘ 加滚动或捏合缩放。V 选择,H 抓手,空格临时平移,Shift 框选。
  • 上方编辑栏提供文字样式、旋转和八向拉伸模式。旋转时 Shift 吸附 15°;八向拉伸时 Shift 固定比例,Esc 退出。图标保留等比缩放预设。
  • 连线可单独选择:颜色、粗细、透明度、实/虚/点线、箭头与箭尾形状/大小/填充均可设置。双击线或点击添加按钮插入曲线点,拖动锚点和控制柄制作多段贝塞尔链;支持平滑、镜像和独立控制柄。
  • 连线动画可关闭、始终播放或仅执行时播放,包含沿完整曲线的流光、流动虚线和脉冲;方向、颜色和时长可设。执行动画由真实任务边事件驱动。
  • 底部 AI 模式可保持开启;选择文本/图片/卡片后,上方为编辑栏,下方为固定屏幕尺寸的 AI 面板。模型从后端目录读取,支持原地生成、取消及可选下游传播;冲突结果保留供明确应用。
  • 新选框通过服务端事务创建并关联真实子画布。标签用三个图标切换隐藏/固定字号/随缩放,悬停查看解释。选框可收起、展开及调整概览比例,子图真实内容尺寸不变。
  • 展开内容使用子画布投影,编辑保存到实际 owner;不会在父图复制一份。拖入/移出使用多画布事务;新跨图连线按后端能力通过 connections 命令创建端口链。删除选框解散并保留内容。
  • 原地生成与用户拖动可合并;内容冲突保留本地草稿。网络结果不确定时暂停编辑,用相同幂等请求重试或重新读取。每个画布有独立版本与串行保存器。
  • 图标面板支持 2313 个 Lucide 和 24 个 Tabler 图标试用、分类/搜索、虚拟列表及本地图形分片加载。未打开面板不加载目录。
  • 有子图时导出完整 owner 文档集合;关系型子图备份不直接覆盖导入到其他画布。历史 V1/关系不兼容草稿可导出,不能覆盖 V2 子图关系。

Canvas V2 接口与检查

后端基线由用户交付的部署 b4e537b、CI #912/#913 与指定测试画布迁移摘要确认。跨图 connections 扩展以线上 capabilities.subgraphs.connections 为准;客户端先检查能力,再发事务。前端未重复运行迁移或调用线上付费模型。

同源代理转发 V2 Accept、If-Match、Idempotency-Key 和事件分页查询,保留 ETag/schema/Retry-After;受管图片通过带会话的二进制代理读取。快照上限 5 MiB,图片上传支持受限 multipart;服务令牌不会发给浏览器。

验证命令:

npm run typecheck
node --experimental-strip-types --test tests/*.test.mjs
CANVAS_UI_TOOLS=/path/to/isolated-tools node tests/canvas-ui-check.mjs

DOM 工具仅需在临时目录安装 esbuild/jsdom,见测试文件开头;不启动浏览器。生产构建与 tests/api-smoke.mjs 使用隔离副本和临时本地服务,避免影响现有开发服务器。实际结果及限制见 VALIDATION.md。

Headless Canvas API 的完整方案保留在本地忽略的 docs/HEADLESS_CANVAS_API_DRAFT.md。当前工作分支已接入纯 core/runtime、ledger/queue、IndexedDB 恢复、渐进导入/深复制、canonical Foundry 协议和私有 ESM 包预览;使用方式见 headless/README.md,尚未发布 npm registry,也不代表完整产品验收或后端部署完成。

Workspace AssetDepot 支持重新授权后的跨项目采用、持久绑定与共享字节。浏览器数据库 v4 将已确认上传的项目文件转换为共享字节指针,保留原 File MIME 和逻辑读取接口;绑定使用恢复格式13。共享回收要求所有项目的持久引用清单完整且与 Root 同步;关闭项目仍受保护。源文件转换、字节、引用清单和 Root 在同一个事务中保存,未确认上传继续保留原 Blob。

应用提示使用 Sonner,图标说明使用 Radix Tooltip;根布局统一安装 provider。画布通用操作错误与归属完成使用固定 ID 通知,保存冲突、失败上传和重试操作仍保留在相关内容处。消息和浮层依赖仅属于应用 UI,不作为未来 headless core 的依赖。

会话期限

会话为可撤销的随机令牌。30 天闲置续期、90 天绝对期限由 Core 控制,代理按剩余期限更新 HttpOnly Cookie;既有过期会话不恢复。详细本地说明为 docs/SESSION_LIFETIME.md。

图片附件与加载

真实画布新上传的图片存入 Foundry 附件 API,快照只保存原始附件引用,避免 Base64 随每次打开和保存传输。原图保留;画布按需读取单一最长边 1024px 的预览,放大后可读取原图。预览权限与原图一致,Core 的配套预览功能已随 PR #15 合并并部署(b2ae48e);小图或 GIF 可能直接返回原始文件。

指定测试画布已完成一次性旧图迁移,原图、节点与连线的哈希核对一致;临时迁移入口及执行逻辑已移除。打开页面不会自动迁移或 PATCH。只改变视角保存在本机;真实内容修改才自动保存到服务器。

跨分区拖放同步

拖放后元素保持落位,旁边显示局部同步状态;其他元素仍可编辑和拖动。移动中的节点及分区几何暂时受保护,归属事务排队使用最新版本。期间的本地编辑在响应到达后合并,再自动保存。响应丢失时重试复用同一请求和幂等键;明确版本冲突则先重读版本,避免重复移动或覆盖其他编辑。

Core subgraphs.member_positions 能力启用时,最终落点(源画布局部坐标)与归属通过一次 members POST 原子保存,单纯拖放不再先 PATCH 坐标。旧后端仍使用先保存坐标再迁移的兼容流程,但不显示整屏等待遮罩。Core 配套 PR #16 已合并并部署为 2207c85;刷新页面后会重新检测并启用新接口能力。

上传图片时立即在画布显示本地预览,并在后台上传原始文件;上传成功才把稳定附件引用加入快照。服务端预览加载完成前继续显示本地图片,避免网络等待期间空白。失败保留文件供重试/取消,重试沿用同一幂等键;本地 blob URL 不保存到服务端。

上传中的图片也是正常本地节点,可立即选中、拖动、缩放、改名、删除和撤销;上传完成只补齐附件引用,不重置节点。上传前改变分区归属会先在本地完成,文件准备好后保存到当时的实际所属画布。临时上传标记和 blob 地址由传输层排除,不发送给 Core;文件仍未可用时,依赖服务端文件的 AI 生成需等待上传完成。

S
Description
No description provided
Readme 14 MiB
Languages
TypeScript 51.4%
JavaScript 45.8%
CSS 2.8%