feat: add Cloudflare Workers deployment alongside Vercel

InfiPlot now deploys to either Vercel or Cloudflare Workers — both
targets are first-class. The project is fully stateless (sessions live
on the client), so the Cloudflare side needs only Workers + Workers
Assets and zero D1/KV/R2.

- apps/web/wrangler.jsonc — nodejs_compat, Assets binding, 60s CPU
  limit (Workers Paid required; matches vercel.json maxDuration). I/O
  wait does not count against this budget — fits the LLM-bound
  workload that's most of the runtime.
- apps/web/open-next.config.ts — minimal defineCloudflareConfig (no
  cache needed since the engine is stateless).
- apps/web/package.json — added build:cf / preview:cf / deploy:cf via
  @opennextjs/cloudflare + wrangler (both devDeps); sharp moved from
  dependencies to devDependencies (only used by the manual
  optimize-home-images.mjs / localize-firstact-images.mjs scripts now).
- .gitignore — .open-next, .wrangler, .dev.vars.
- READMEs (3 langs) — Deploy to Cloudflare button next to Vercel,
  plus a Cloudflare section in the env-var setup (wrangler secret put
  + Cloudflare Access for staging access control).

Verified: pnpm typecheck + pnpm build (Vercel path) + pnpm build:cf
(OpenNext bundle: worker 4 KB, server 24 MB, assets 32 MB / 186
files — all within Workers limits) + pnpm preview:cf with the full
play loop (start → scene → background click → CORS-clean Canvas
annotation via Runware CDN → vision LLM → insert-beat) all green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
yuanzonghao
2026-06-02 21:47:03 +08:00
parent 346d5359d4
commit 72331bb865
8 changed files with 3519 additions and 28 deletions
+4
View File
@@ -14,6 +14,9 @@ out
.turbo
.claude
.open-next
.wrangler
.DS_Store
*.log
npm-debug.log*
@@ -22,3 +25,4 @@ pnpm-debug.log*
repomix-output.xml
users.md
.dev.vars
+10 -4
View File
@@ -39,9 +39,11 @@ Free to play, no setup required: [infiplot.com](https://infiplot.com)
## One-click deploy
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/zonghaoyuan/infiplot&root-directory=apps/web&env=TEXT_BASE_URL,TEXT_API_KEY,TEXT_MODEL,IMAGE_BASE_URL,IMAGE_API_KEY,IMAGE_MODEL,VISION_BASE_URL,VISION_API_KEY,VISION_MODEL,TTS_BASE_URL,TTS_API_KEY,TTS_SPEECH_MODEL,MOCK_IMAGE&envDescription=Three%20required%20providers%20%2B%20optional%20TTS.%20Any%20OpenAI-compatible%20endpoint%20works%20for%20text%2Fvision.%20TTS%20uses%20MiMo%27s%20own%20protocol.&envLink=https://github.com/zonghaoyuan/infiplot/blob/main/README.en.md%23configuration-guide)
InfiPlot deploys to both Vercel and Cloudflare Workers — pick whichever you prefer.
After deploy, set your environment variables in the Vercel project — see the [Configuration guide](#configuration-guide) below. The Vercel project's **Root Directory** must be `apps/web` (the deploy button passes this automatically; if you configure manually, set it in Project Settings).
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/zonghaoyuan/infiplot&root-directory=apps/web&env=TEXT_BASE_URL,TEXT_API_KEY,TEXT_MODEL,IMAGE_BASE_URL,IMAGE_API_KEY,IMAGE_MODEL,VISION_BASE_URL,VISION_API_KEY,VISION_MODEL,TTS_BASE_URL,TTS_API_KEY,TTS_SPEECH_MODEL,MOCK_IMAGE&envDescription=Three%20required%20providers%20%2B%20optional%20TTS.%20Any%20OpenAI-compatible%20endpoint%20works%20for%20text%2Fvision.%20TTS%20uses%20MiMo%27s%20own%20protocol.&envLink=https://github.com/zonghaoyuan/infiplot/blob/main/README.en.md%23configuration-guide) &nbsp; [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot/tree/main/apps/web)
After deploy, fill in the environment variables — see the [Configuration guide](#configuration-guide) below. Both platforms need `apps/web` as the project root (Vercel's button passes this automatically; on Cloudflare, set the build root to `apps/web` and the build command to `pnpm --filter @infiplot/web build:cf`).
---
@@ -135,13 +137,17 @@ InfiPlot talks to four kinds of model providers. **Text and Vision use any OpenA
**2. Set the environment variables**
Set these in your Vercel project (**Settings → Environment Variables**), or in `apps/web/.env.local` for local runs. Nine variables are required; TTS is optional (leave blank to run silently). There's also a flag for cheap testing:
Nine variables are required; TTS is optional (leave blank to run silently). There's also a flag for cheap testing:
| Variable | Effect |
|---|---|
| `MOCK_IMAGE=true` | Skip image generation; the renderer returns a static placeholder. Story, voice, and choices still run normally. Great for iterating on TTS without burning Runware credits. |
See `apps/web/.env.example` for the exact shape.
Where to set them (see `apps/web/.env.example` for the exact shape):
- **Local dev** — `apps/web/.env.local`
- **Vercel** — Project Settings → Environment Variables
- **Cloudflare Workers** — from `apps/web/`, run `wrangler secret put <NAME>` for each variable, or set them in the dashboard (Workers → infiplot → Settings → Variables and Secrets). For a private staging instance, gate the Worker behind [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/applications/) — zero-code email-whitelist auth in front of the Worker.
**3. Mind the cost**
+10 -4
View File
@@ -39,9 +39,11 @@ InfiPlot は、AI がコンテンツをリアルタイムに生成するイン
## ワンクリックデプロイ
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/zonghaoyuan/infiplot&root-directory=apps/web&env=TEXT_BASE_URL,TEXT_API_KEY,TEXT_MODEL,IMAGE_BASE_URL,IMAGE_API_KEY,IMAGE_MODEL,VISION_BASE_URL,VISION_API_KEY,VISION_MODEL,TTS_BASE_URL,TTS_API_KEY,TTS_SPEECH_MODEL,MOCK_IMAGE&envDescription=Three%20required%20providers%20%2B%20optional%20TTS.%20Any%20OpenAI-compatible%20endpoint%20works%20for%20text%2Fvision.%20TTS%20uses%20MiMo%27s%20own%20protocol.&envLink=https://github.com/zonghaoyuan/infiplot/blob/main/README.ja.md%23%E8%A8%AD%E5%AE%9A%E3%82%AC%E3%82%A4%E3%83%89)
InfiPlot は Vercel と Cloudflare Workers の両方にそのままデプロイできます —— お好みの方をお選びください。
デプロイ後、Vercel プロジェクトで環境変数を設定してください —— 下記の[設定ガイド](#設定ガイド)を参照。Vercel プロジェクトの **Root Directory**`apps/web` に設定する必要があります(デプロイボタンが自動で渡します。手動設定の場合は Project Settings で指定してください)。
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/zonghaoyuan/infiplot&root-directory=apps/web&env=TEXT_BASE_URL,TEXT_API_KEY,TEXT_MODEL,IMAGE_BASE_URL,IMAGE_API_KEY,IMAGE_MODEL,VISION_BASE_URL,VISION_API_KEY,VISION_MODEL,TTS_BASE_URL,TTS_API_KEY,TTS_SPEECH_MODEL,MOCK_IMAGE&envDescription=Three%20required%20providers%20%2B%20optional%20TTS.%20Any%20OpenAI-compatible%20endpoint%20works%20for%20text%2Fvision.%20TTS%20uses%20MiMo%27s%20own%20protocol.&envLink=https://github.com/zonghaoyuan/infiplot/blob/main/README.ja.md%23%E8%A8%AD%E5%AE%9A%E3%82%AC%E3%82%A4%E3%83%89) &nbsp; [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot/tree/main/apps/web)
デプロイ後、環境変数を設定してください —— 下記の[設定ガイド](#設定ガイド)を参照。両方のプラットフォームで、プロジェクトのルートを `apps/web` に設定する必要があります(Vercel のデプロイボタンが自動で渡します。Cloudflare では build root を `apps/web`、ビルドコマンドを `pnpm --filter @infiplot/web build:cf` に設定してください)。
---
@@ -112,13 +114,17 @@ InfiPlot は 4 種類のモデルプロバイダと通信します。**テキス
**2. 環境変数を設定する**
Vercel プロジェクト(**Settings → Environment Variables**)、またはローカル実行時は `apps/web/.env.local` に設定します。9 つの変数が必須で、TTS は任意です(空欄なら無音で動作)。低コストなテスト用のフラグもあります。
9 つの変数が必須で、TTS は任意です(空欄なら無音で動作)。低コストなテスト用のフラグもあります。
| 変数 | 効果 |
|---|---|
| `MOCK_IMAGE=true` | 画像生成をスキップし、レンダラが静的なプレースホルダを返します。ストーリー・音声・選択肢は通常どおり動作します。Runware のクレジットを消費せずに TTS を調整するのに最適です。 |
正確なフォーマットは `apps/web/.env.example` を参照してください。
設定場所(正確なフォーマットは `apps/web/.env.example` を参照):
- **ローカル開発** —— `apps/web/.env.local`
- **Vercel** —— Project Settings → Environment Variables
- **Cloudflare Workers** —— `apps/web/` から各変数について `wrangler secret put <NAME>` を実行するか、ダッシュボード(Workers → infiplot → Settings → Variables and Secrets)で設定します。ステージング環境にアクセス制限を掛けたい場合は、Worker の前に [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/applications/) を挟むと、ゼロコードでメール許可リスト方式の認証が利用できます。
**3. コストに注意**
+10 -4
View File
@@ -39,9 +39,11 @@ InfiPlot是一款AI实时生成内容的互动剧情游戏,这里没有预设
## 一键部署
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/zonghaoyuan/infiplot&root-directory=apps/web&env=TEXT_BASE_URL,TEXT_API_KEY,TEXT_MODEL,IMAGE_BASE_URL,IMAGE_API_KEY,IMAGE_MODEL,VISION_BASE_URL,VISION_API_KEY,VISION_MODEL,TTS_BASE_URL,TTS_API_KEY,TTS_SPEECH_MODEL,MOCK_IMAGE&envDescription=Three%20required%20providers%20%2B%20optional%20TTS.%20Any%20OpenAI-compatible%20endpoint%20works%20for%20text%2Fvision.%20TTS%20uses%20MiMo%27s%20own%20protocol.&envLink=https://github.com/zonghaoyuan/infiplot%23%E9%85%8D%E7%BD%AE%E6%95%99%E7%A8%8B)
InfiPlot 同时支持部署到 Vercel 与 Cloudflare Workers —— 任选其一即可。
部署完成后,在 Vercel 项目里填好环境变量 —— 详见下方的[配置教程](#配置教程)。Vercel 项目的 **Root Directory** 必须设为 `apps/web`(一键部署按钮会自动带上;若手动配置,请在 Project Settings 里设置)。
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/zonghaoyuan/infiplot&root-directory=apps/web&env=TEXT_BASE_URL,TEXT_API_KEY,TEXT_MODEL,IMAGE_BASE_URL,IMAGE_API_KEY,IMAGE_MODEL,VISION_BASE_URL,VISION_API_KEY,VISION_MODEL,TTS_BASE_URL,TTS_API_KEY,TTS_SPEECH_MODEL,MOCK_IMAGE&envDescription=Three%20required%20providers%20%2B%20optional%20TTS.%20Any%20OpenAI-compatible%20endpoint%20works%20for%20text%2Fvision.%20TTS%20uses%20MiMo%27s%20own%20protocol.&envLink=https://github.com/zonghaoyuan/infiplot%23%E9%85%8D%E7%BD%AE%E6%95%99%E7%A8%8B) &nbsp; [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot/tree/main/apps/web)
部署完成后,填好环境变量 —— 详见下方的[配置教程](#配置教程)。两个平台都需要把项目根目录设为 `apps/web`(Vercel 一键部署按钮会自动带上;在 Cloudflare 上请把 build root 设为 `apps/web`,构建命令设为 `pnpm --filter @infiplot/web build:cf`)。
---
@@ -134,13 +136,17 @@ InfiPlot 会与四类模型供应商通信。**文本(Text)和视觉(Visio
**2. 填写环境变量**
在 Vercel 项目里设置(**Settings → Environment Variables**),或在本地运行时写进 `apps/web/.env.local`九个变量为必填;TTS 可选(留空则静音运行)。此外还有一个用于低成本测试的开关:
九个变量为必填;TTS 可选(留空则静音运行)。此外还有一个用于低成本测试的开关:
| 变量 | 作用 |
|---|---|
| `MOCK_IMAGE=true` | 跳过图像生成,渲染器返回一张静态占位图。剧情、语音、选项照常运行。非常适合在不消耗 Runware 额度的情况下调试 TTS。 |
确切字段格式`apps/web/.env.example`
在哪里设置(确切字段见 `apps/web/.env.example`):
- **本地开发** —— `apps/web/.env.local`
- **Vercel** —— Project Settings → Environment Variables
- **Cloudflare Workers** —— 在 `apps/web/` 目录下逐个执行 `wrangler secret put <NAME>`,或在 dashboard 里设置(Workers → infiplot → Settings → Variables and Secrets)。如果要给 staging 加访问限制,可以在 Worker 前面挂一个 [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/applications/)(零代码,邮箱白名单)。
**3. 注意成本**
+5
View File
@@ -0,0 +1,5 @@
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
// Minimal config — the project is fully stateless (sessions live on the
// client), so no R2/KV/D1 incremental cache is needed.
export default defineCloudflareConfig();
+9 -4
View File
@@ -8,7 +8,10 @@
"build": "next build",
"start": "next start",
"lint": "next lint",
"typecheck": "tsc --noEmit"
"typecheck": "tsc --noEmit",
"build:cf": "opennextjs-cloudflare build",
"preview:cf": "opennextjs-cloudflare preview",
"deploy:cf": "opennextjs-cloudflare deploy"
},
"dependencies": {
"@infiplot/ai-client": "workspace:*",
@@ -16,16 +19,18 @@
"@infiplot/types": "workspace:*",
"next": "^16.0.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"sharp": "^0.33.5"
"react-dom": "^19.0.0"
},
"devDependencies": {
"@opennextjs/cloudflare": "^1.19.11",
"sharp": "^0.33.5",
"@types/node": "^22.9.0",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.15",
"typescript": "^5.6.3"
"typescript": "^5.6.3",
"wrangler": "^4.96.0"
}
}
+20
View File
@@ -0,0 +1,20 @@
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "infiplot",
"main": ".open-next/worker.js",
"compatibility_date": "2025-03-25",
"compatibility_flags": ["nodejs_compat"],
"assets": {
"binding": "ASSETS",
"directory": ".open-next/assets"
},
"observability": {
"enabled": true
},
// 60s mirrors apps/web/vercel.json maxDuration for the scene pipeline tail
// (multi-agent LLM, ~30-45s p95). Requires Workers Paid — Free is capped
// at 10ms CPU. I/O wait does not count against this budget.
"limits": {
"cpu_ms": 60000
}
}
+3451 -12
View File
File diff suppressed because it is too large Load Diff