内容
# FutureMod
> AI 原生 React 组件库。Tailwind + shadcn 注册模式。青色主色 · 红色强调色 · Geist 字体 · 暗/亮模式 · Glassmorphic 表面。
**FutureMod 免费使用** — 组件库、MCP 服务器和 Studio 作为真正的产品发布,而不是受限的演示。
## 软件包
- [@futuremod/ui](packages/ui) — React 组件
- [@futuremod/ai-context](packages/ai-context) — 注册元数据,llms.txt 生成器
- [@futuremod/mcp-server](packages/mcp-server) — AI 代理的 MCP 服务器
## 快速开始
```bash
pnpm add @futuremod/ui
import '@futuremod/ui/styles';
import { Button, Card, DashboardShell } from '@futuremod/ui';
```
## 在此仓库中开发
使用 **Node 20+** 和 **pnpm 9**(此仓库固定 `packageManager: pnpm@9.0.0`)。启用 pnpm 一次:`corepack prepare pnpm@9.0.0 --activate`.
每次运行 **一条命令**(单独粘贴每行)。在 zsh/bash 中,注释必须以 `#` 开头或在完整命令后跟随空格;如果整个代码块作为单行粘贴,`pnpm dev` 之后的代码可以作为额外参数传递。这使得 `tsc` 看到 `"#"` 和 `watch all packages` 字样作为源文件并失败,报错 `Option 'project' cannot be mixed with source files`.
```bash
cd /path/to/FutureMod
pnpm install
pnpm dev
```
```bash
pnpm build
pnpm --filter @futuremod/mcp-server start
```
`pnpm dev` 以监视模式运行 TypeScript,适用于每个软件包。`start` 在标准输入/输出上运行 MCP 服务器(它等待输入;用 Ctrl+C 停止)。
## FutureMod Studio(项目 → 页面 → 应用画布)
[apps/studio](apps/studio) 是 Vite + React。结构:
- **项目** — `{project}.futuremod.site` 用于公开 URL;仪表板中的路由使用 **`/projects/:slug/...`** (`localhost` / apex)。项目存储在 Supabase Postgres(`projects` 表)中,并作用于已验证的用户。
- **页面** — 命名文档(`pageId`);Puck 在浏览器 `localStorage`(草稿)和 Cloudflare KV + Supabase(`pages` 表)中按项目存储布局 JSON。
- **编辑器** — **Puck** 带有 **@futuremod/ui** 块和 **数据面板**(`DataPanel.tsx`)用于项目 slug、页面切换和示例查询。Puck **根** 配置将所有块包裹在可配置的居中容器(最大宽度、填充)中,以便编辑器预览和实时发布页面看起来相同。
- **仪表板和身份验证** — [`AppRoutes.tsx`](apps/studio/src/routes/AppRoutes.tsx) 中的路由:`/login`、`/signup`、`/dashboard`、**`/projects/:slug/editor`**、**`/projects/:slug/preview`**。身份验证由 **Supabase Auth** 提供,支持电子邮件/密码和 **Google OAuth**。
- **独立编辑器** — 访问 **`{project}.{root}`** 而没有服务器注入的 **`__PAGE_DATA__`** 仍然会安装 [`StandaloneStudioApp.tsx`](apps/studio/src/StandaloneStudioApp.tsx)(与仪表板上的 Puck shell 相同)。
另外:
- **数据源和查询** — 示例数据集 + SQL 形状定义;连接您的 API 以获取实时数据库(凭证保留在服务器端)。
- **调色板 + [`placeFuturemodWidget`](apps/studio/src/ai/placement.ts)** — 用于 AI 驱动的合成钩子。
- **应用内预览路由** — **`/projects/:slug/preview`** 渲染只读 Puck(`Render`)与相同的根容器作为实时页面。
```bash
pnpm studio
```
打开 [http://localhost:5173](http://localhost:5173) — 使用 Google 或电子邮件/密码登录,然后选择或创建项目。
### 身份验证(Supabase Auth)
Studio 使用 **Supabase Auth** 进行所有登录流程:
| 流程 | 备注 |
|------|-------|
| 电子邮件 + 密码 | 标准注册,可选电子邮件确认 |
| Google OAuth | 一键登录;重定向回 `/dashboard` |
在 [`src/lib/supabase.ts`](apps/studio/src/lib/supabase.ts) 中配置。设置 **站点 URL** 为 `https://futuremod.site` 并在 Supabase Auth 设置中将 `https://futuremod.site/**` 添加到重定向 URL。 对于 Google OAuth,请在 Google Cloud Console 中将 Supabase 回调 URL(`https://<project>.supabase.co/auth/v1/callback`)注册为授权重定向。
### 数据库(Supabase Postgres)
项目和页面元数据存储在 Supabase Postgres 中。首次使用前运行迁移:
1. 打开 **[Supabase SQL 编辑器](https://supabase.com/dashboard/project/_/sql/new)**
2. 粘贴并运行 [`supabase/migrations/20260504_init.sql`](supabase/migrations/20260504_init.sql)
**模式:**
| 表 | 键列 | 备注 |
|-------|-------------|-------|
| `projects` | `user_id`, `slug`, `title` | 每项目一行;唯一于 `(user_id, slug)` |
| `pages` | `project_id`, `page_id`, `published_data jsonb`, `published_at` | 发布时写入快照 |
两张表均启用行级安全(RLS);用户只能读取和写入自己的行。
**发布流程:** `POST /api/publish`(工作线程)将 Puck 数据写入 **Cloudflare KV**(快速边缘读取)并通过 Supabase REST API 在 `pages` 中插入一行。KV 仍然是提供实时页面的权威来源;数据库记录用于仪表板列表和未来查询。
### 托管:每个项目一个子域
每个 **项目** 都在 **`{project}.futuremod.site`** 上提供服务。 Studio 从主机名中读取项目 slug(参见 [`project-site.ts`](apps/studio/src/lib/project-site.ts)),在 shell 中显示它,并使用它命名持久性键。访问未认领的子域名会重定向到 `futuremod.site`。
在 `*.futuremod.site` 的通配 DNS 记录和 TLS 后面部署相同的 Studio 构建。所需的环境变量:
| 变量 | 用途 |
|----------|---------|
| `VITE_SUPABASE_URL` | Supabase 项目 URL(`https://<ref>.supabase.co`) |
| `VITE_SUPABASE_ANON_KEY` | Supabase 可发布匿名密钥 |
| `VITE_FUTUREMOD_ROOT_DOMAIN` | 默认设置为 `futuremod.site` 如果未设置 |
| `VITE_FUTUREMOD_PROJECT_SLUG` | **本地仅限:** 假装没有 DNS 的命名项目 |
工作线程变量(在 `wrangler.toml` 或 Cloudflare 仪表板中设置):
| 变量 | 用途 |
|----------|---------|
| `SUPABASE_URL` | 相同的 Supabase 项目 URL |
| `SUPABASE_ANON_KEY` | 相同的匿名密钥(服务器端用于验证 JWT) |
### 部署 Studio(Wrangler,无需 GitHub Actions)
托管的 Studio 是一个 **Worker + 静态资产** 应用:[`apps/studio/wrangler.toml`](apps/studio/wrangler.toml) 附加 **`futuremod.site`** 和 **`*.futuremod.site`**,[`apps/studio/src/worker.ts`](apps/studio/src/worker.ts) 在边缘运行。只有当 **`wrangler deploy`** 运行针对 **`apps/studio`** 时,它才会发布。
仅上传 **`dist/`** (经典 **Pages "upload folder only"**) **不会** 部署 **`worker.ts`** 或 **`[[routes]]`**,因此自定义域名不会像 Studio 那样表现。
**从您的笔记本电脑(常规流程)**
```bash
pnpm install --frozen-lockfile
pnpm build
pnpm deploy:studio
```
等效: **`npx wrangler deploy --cwd apps/studio`** (参见根 [`package.json`](package.json))。使用 **`npx wrangler login`** 登录一次,或设置 **`CLOUDFLARE_API_TOKEN`**(Worker 部署权限 + DNS/区域范围,如果 **`wrangler.toml`** 使用 **`zone_name`**) 用于外部非交互式环境。
**Cloudflare 仪表板 + Git:** 在 **Workers & Pages** 下连接仓库并设置构建/安装命令,以便存在 **`dist/`**,然后 **`wrangler deploy`** 在 **`apps/studio`**(monorepo)下运行。成功 **`wrangler deploy`** 后, **`wrangler.toml`** 更新路由和 Worker 代码。
SPA 备用方案在 [`wrangler.toml`](apps/studio/wrangler.toml) 中使用 `not_found_handling = "single-page-application"`。 **不要** 添加一个导致循环的 **`_redirects`** 捕获所有(错误 10021)。
**软件包:** Studio 将 **`@futuremod/ui`** 打包到 **`apps/studio/dist`**; **`@futuremod/mcp-server`** 是一个单独的 Node MCP 进程,而不是此部署。
## MCP
此仓库包括 **[`.cursor/mcp.json`](.cursor/mcp.json)** 以便 Cursor 从工作空间加载 **`@futuremod/mcp-server`** 通过 [`scripts/run-futuremod-mcp.cjs`](scripts/run-futuremod-mcp.cjs)(如果 **`dist/`** 缺失,它会构建 **`packages/mcp-server`** 一次)。更改后重启 Cursor。
还包括一个用于 Supabase MCP 的 **[`.mcp.json`](.mcp.json)** — 它指向项目的 Supabase 实例,以便 AI 代理可以查询模式并直接调试数据库。
在工作空间之外,一旦发布 **`@futuremod/mcp-server`**,您可以使用:
```json
{
"mcpServers": {
"futuremod": { "type": "stdio", "command": "npx", "args": ["-y", "@futuremod/mcp-server"] }
}
}
```
## 组件
- 按钮,卡片,徽章,输入框,选择框,文本框,头像,加载器
- 表格,统计卡片,警报,选项卡,表单字段,标签,分割线,骨架
- 页面布局,侧边栏,头部,仪表板外壳,空白状态
## 设计令牌
| 令牌 | 浅色 | 深色 |
|----------------|--------------------|--------------------|
| 主色(青色) | hsl(189 94% 36%) | hsl(189 94% 46%) |
| 强调色(红色) | hsl(0 84% 60%) | hsl(0 84% 62%) |
| 背景 | hsl(0 0% 98%) | hsl(220 14% 6%) |
| 半径 | 10px | 10px |