项目结构
浏览 main、preload、renderer、shared 与 Supabase 的目录布局。
Electron 模板先按进程边界拆分,再按功能组织。renderer 负责 React UI,main
process 负责特权桌面 API,preload 暴露窄桥接层,shared/ 放两侧都可导入的常量与配置。
顶层布局
Renderer: app/
app/ 是沙盒中的 React SPA。它使用 HashRouter、lazy routes、TanStack
Query、zustand stores、i18next 与 shadcn 风格 UI primitives。
| 路径 | 作用 |
|---|---|
app/app.tsx | 路由树、providers、app-intent navigation、analytics route tracking、onboarding gate。 |
app/renderer.tsx | 浏览器入口、错误监听、Supabase env 校验、i18n bootstrap、React mount。 |
app/routes/ | Home、Settings、Account、Billing、About、Logs、Help、Update、认证页和 Showcase routes。 |
app/components/ | 外壳、侧边栏、命令面板、window/titlebar、onboarding、billing cards、UI primitives。 |
app/services/ | todos、profile、avatar、subscription、billing、license、analytics 的 Supabase 与 Edge Function 调用。 |
app/stores/ | auth-store 与 subscription-store zustand 状态。 |
app/lib/ | 认证 schemas、Supabase client/types、query client、i18n bootstrap、feature gate、support URLs。 |
app/locales/ | 英文与简体中文 JSON 词典。 |
app/showcase/ 和 app/routes/showcase/ | [template-demo] capability catalog、组件画廊与演示。 |
Main process: lib/main/
lib/main/ 拥有特权桌面行为,永远不在 renderer 中运行。重要模块包括:
| 模块 | 职责 |
|---|---|
main.ts | 应用启动、single-instance lock、协议注册、service wiring、handler 注册。 |
app.ts | BrowserWindow 创建、sandbox/context isolation、导航防护、外部 URL 处理、window-state 持久化 hook。 |
settings.ts | 带前向迁移的版本化 JSON 设置存储。 |
updater.ts | electron-updater service、后台检查、手动检查、状态事件。 |
tray.ts 和 menu.ts | 原生托盘与应用菜单,包括 flag-gated Showcase entries。 |
shortcuts.ts 和 notifications.ts | 全局快捷键注册与原生通知服务。 |
secure-storage.ts | 通过 Electron safeStorage 使用系统 keychain 的存储。 |
backup.ts、diagnostics.ts、logger.ts、log-redact.ts | 设置导入导出、脱敏诊断、文件日志、凭据清洗。 |
protocols.ts、app-intents.ts、argv-intents.ts | 资源协议、deep-link intent 分发、Windows/Linux second-instance argv 解析。 |
navigation-guard.ts 和 external-url.ts | 拒绝危险导航,并把外部 URL 交给系统浏览器的唯一审计路径。 |
window-state.ts、zoom.ts、permissions.ts、i18n.ts | 桌面窗口偏好、缩放、权限处理、main-process 本地化。 |
feature-flags.ts、error-reporting.ts | main-process showcase flag 与可选 Sentry 错误插槽。 |
这一层有大量共置 *.test.ts。扩展 main-process 行为时,可以把这些测试当作可执行文档。
Preload 与 IPC
lib/preload/preload.ts 暴露一个全局对象:
window.conveyor这个对象来自 lib/conveyor/api/index.ts,通过 Electron contextBridge
发布。应用代码应调用 useConveyor('window')、useConveyor('app') 或其他
Conveyor domain,不要导入 ipcRenderer。
lib/conveyor/ 有四部分:
| 路径 | 作用 |
|---|---|
api/ | renderer 侧类,覆盖 app、file、logs、notification、secure、shortcut、update、window。 |
handlers/ | 启动时注册的 main-process IPC 实现。 |
schemas/ | 入参、返回值和 main-to-renderer 事件的 Zod schemas。 |
conveyor.d.ts | renderer 中 window.conveyor 的全局类型。 |
完整新增 channel 流程见 IPC 页面。
Shared config
shared/constants.ts 是产品身份来源:app name、app id、product slug、
deep-link scheme、support email、repository、homepage、license URL 与 EULA 设置。
shared/config.ts 统一读取 renderer-facing feature flags 与 opt-in analytics
配置。shared/price-config.ts 把 Creem product IDs 映射到 Free、Pro、Lifetime tiers。
Supabase、resources、scripts、docs
| 路径 | 作用 |
|---|---|
supabase/migrations/ | 已提交 SQL migrations。当前包含 billing read model;Supabase 设置文档会补上 profile/todos/avatar SQL。 |
supabase/functions/ | checkout、customer portal、license activation 与 Creem webhook 的 Edge Functions。 |
resources/ | 构建资源、图标、macOS entitlements、公证 hook。 |
scripts/dev.mjs | 包装 electron-vite dev -w 的开发启动器。 |
scripts/rebrand.mjs | 一次性替换 product name、slug、scheme、app id 与静态配置。 |
scripts/deploy-edge-functions.sh | 部署 Supabase Edge Functions。 |
docs/CUSTOMIZE.md | Showcase 删除的权威清单。 |
docs/APP_ICONS.md | 应用图标替换指南。 |
构建配置
electron.vite.config.ts 构建三个 bundle:
| Bundle | 入口 | 说明 |
|---|---|---|
| Main | lib/main/main.ts | Node/Electron APIs、externalized dependencies、build metadata defines。 |
| Preload | lib/preload/preload.ts | 依赖会被打包,因为 sandboxed preload 不能 require 任意 npm 包。 |
| Renderer | app/index.html | React/Vite 应用,带 Tailwind 与 React plugin。 |
bundle 共享 aliases:@/app、@/lib、@/resources、@/shared。
tsconfig.node.json 覆盖 main、preload、tests、config、resources、app 与
shared 代码。tsconfig.web.json 覆盖 renderer-facing 代码与 Conveyor 类型。
两者都把根 alias 暴露为 @/*。
环境变量前缀按进程区分:
VITE_*会被打入 renderer 代码。MAIN_VITE_*通过 electron-vite 进入 main bundle。UPDATE_SERVER_URL、签名凭据、Supabase Edge secrets 等 release/build 变量不是 app renderer 配置。
命名与测试
模板遵循自身 AGENTS.md 的约定:
- React components 使用
PascalCase,如TitlebarMenu.tsx。 - Hooks 使用带
use-前缀的 kebab-case,如use-conveyor.ts。 - 工具与进程模块使用描述性的 kebab-case 文件名。
- 测试与代码共置为
*.test.ts或*.test.tsx。
Showcase/demo 代码带 [template-demo] 标记。删除前先用
VITE_SHOWCASE_ENABLED=false 与 MAIN_VITE_SHOWCASE_ENABLED=false 预览无演示层应用,
然后按 Showcase 操作。
