diff --git a/apps/web/.env.example b/.env.example
similarity index 79%
rename from apps/web/.env.example
rename to .env.example
index 5aca3df..aac003d 100644
--- a/apps/web/.env.example
+++ b/.env.example
@@ -55,3 +55,15 @@ TTS_SPEECH_MODEL=mimo-v2.5-tts
# true → return a placeholder image instead of calling the image model.
# Text/story/voice still run normally. Great for iterating on TTS.
MOCK_IMAGE=false
+
+# ---- 6. Analytics · Umami (optional — leave blank to disable) ------
+# Privacy-friendly, cookieless page-view stats — no Cookie consent banner.
+# Cloud: sign up at https://cloud.umami.is, add your site, copy its ID into
+# NEXT_PUBLIC_UMAMI_WEBSITE_ID and use the cloud script URL:
+# NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
+# Self-host later: point SRC at your own instance — the integration is identical
+# (no code change), e.g. NEXT_PUBLIC_UMAMI_SRC=https://stats.example.com/script.js
+# Both blank → no script is injected (zero tracking). NEXT_PUBLIC_ vars are
+# inlined at BUILD time, so set them in the build env (Vercel project settings).
+NEXT_PUBLIC_UMAMI_SRC=
+NEXT_PUBLIC_UMAMI_WEBSITE_ID=
diff --git a/README.en.md b/README.en.md
index 50ae951..519065a 100644
--- a/README.en.md
+++ b/README.en.md
@@ -39,11 +39,11 @@ Free to play, no setup required: [infiplot.com](https://infiplot.com)
## One-click deploy
-InfiPlot deploys to both Vercel and Cloudflare Workers — pick whichever you prefer.
+InfiPlot deploys to both Vercel and Cloudflare Workers. Cloudflare deployment requires the Workers Paid Plan because the scene pipeline needs longer CPU time; for personal use, the one-click Vercel deploy is recommended.
-[](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) [](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot/tree/main/apps/web)
+[](https://vercel.com/new/clone?repository-url=https://github.com/zonghaoyuan/infiplot&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) [](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot)
-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`).
+After deploy, fill in the environment variables — see the [Configuration guide](#configuration-guide) below. The repo root is the app itself: Vercel needs no special root directory; on Cloudflare, just set the build command to `pnpm build:cf`.
---
@@ -77,20 +77,9 @@ We call each complete playthrough a **story**.
A story unfolds as a sequence of scenes. Each scene is one AI-painted background plus a short tree of beats — moments of narration, dialogue, and the occasional choice. You tap through a scene's beats and the image stays put; only when a choice leads somewhere genuinely new — another place, a new point of view, a jump in time — does the AI paint the next scene.
-```mermaid
-flowchart TD
- U["Your input: world setting + art style"] --> A["Architect
parses input → full story structure (first step)"]
- A --> W["Writer
directs this scene's beats: narration · dialogue · choices"]
- subgraph SCENE["Generating one scene"]
- direction TB
- W --> C["Character Designer
portrait + voice (parallel, per new character)"]
- W --> S["Cinematographer
shot composition + background prompt"]
- C --> P["Painter
renders the 16:9 background using portraits as reference"]
- S --> P
- end
- P --> SC["One scene: background image + beat tree"]
- SC -. speculatively pre-generate the next scene .-> W
-```
+
+

+
While you're reading one scene, the engine speculatively generates the scenes your choices could lead to — and, for unavoidable next steps, the scene after that. By the time you pick a direction, its image is usually already painted, so the cut feels instant. If you still notice some lag today, don't worry — we're working hard to bring it down.
@@ -118,7 +107,7 @@ Get in touch: hi@infiplot.com
Scan to join our **beta community on QQ** (group ID `575404333`) to share feedback and help shape the project:
-
+
---
@@ -143,11 +132,11 @@ Nine variables are required; TTS is optional (leave blank to run silently). Ther
|---|---|
| `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. |
-Where to set them (see `apps/web/.env.example` for the exact shape):
+Where to set them (see `.env.example` for the exact shape):
-- **Local dev** — `apps/web/.env.local`
+- **Local dev** — `.env.local`
- **Vercel** — Project Settings → Environment Variables
-- **Cloudflare Workers** — from `apps/web/`, run `wrangler secret put ` 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.
+- **Cloudflare Workers** — from the repo root, run `wrangler secret put ` 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**
diff --git a/README.ja.md b/README.ja.md
index 1885c20..c20ce2e 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -39,11 +39,11 @@ InfiPlot は、AI がコンテンツをリアルタイムに生成するイン
## ワンクリックデプロイ
-InfiPlot は Vercel と Cloudflare Workers の両方にそのままデプロイできます —— お好みの方をお選びください。
+InfiPlot は Vercel と Cloudflare Workers の両方にデプロイできます。Cloudflare へのデプロイはシーンパイプラインがより長い CPU 時間を必要とするため、Workers Paid Plan が必要です。個人利用には Vercel のワンクリックデプロイをおすすめします。
-[](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) [](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot/tree/main/apps/web)
+[](https://vercel.com/new/clone?repository-url=https://github.com/zonghaoyuan/infiplot&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) [](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot)
-デプロイ後、環境変数を設定してください —— 下記の[設定ガイド](#設定ガイド)を参照。両方のプラットフォームで、プロジェクトのルートを `apps/web` に設定する必要があります(Vercel のデプロイボタンが自動で渡します。Cloudflare では build root を `apps/web`、ビルドコマンドを `pnpm --filter @infiplot/web build:cf` に設定してください)。
+デプロイ後、環境変数を設定してください —— 下記の[設定ガイド](#設定ガイド)を参照。リポジトリのルートがアプリ本体です:Vercel では特別なルート設定は不要です。Cloudflare ではビルドコマンドを `pnpm build:cf` に設定するだけで済みます。
---
@@ -77,20 +77,9 @@ InfiPlot は Vercel と Cloudflare Workers の両方にそのままデプロイ
物語は一連のシーン(scene)として展開します。各シーンは、AI が描いた 1 枚の背景画と、短いビート(beat)のツリー —— ナレーション、セリフ、ときおりの選択肢 —— で構成されます。シーン内のビートをタップしていく間、画像はそのまま動きません。選択肢が本当に新しい場所 —— 別の空間、新しい視点、時間の跳躍 —— へ導いたときだけ、AI は次のシーンを描きます。
-```mermaid
-flowchart TD
- U["あなたの入力:世界設定 + 画風"] --> A["アーキテクト / Architect
入力を解析 → 物語の全体構造(第一歩)"]
- A --> W["脚本家 / Writer
このシーンのビートを生成:ナレーション · セリフ · 選択肢"]
- subgraph SCENE["1 シーンの生成"]
- direction TB
- W --> C["キャラクターデザイナー / Character Designer
立ち絵 + 声(新キャラごとに並行)"]
- W --> S["撮影監督 / Cinematographer
カメラ構成 + 背景プロンプト"]
- C --> P["絵師 / Painter
立ち絵を参照に 16:9 背景を描画"]
- S --> P
- end
- P --> SC["1 シーン:背景画 + ビートツリー"]
- SC -. 次のシーンを先回り生成 .-> W
-```
+
+

+
あなたがひとつのシーンを読んでいる間に、エンジンは選択肢が導きうるシーンを先回りして生成します —— 避けられない次の一歩については、そのさらに先のシーンまで。あなたが方向を選ぶ頃には、その画像はたいてい描き上がっているので、切り替えは一瞬に感じられます。いまはまだ多少の遅延を感じるかもしれませんが、ご安心ください —— 私たちは鋭意改善に取り組んでいます。
@@ -117,7 +106,7 @@ flowchart TD
**InfiPlot ベータ交流グループ**(QQ グループ番号 `575404333`)—— QR コードを読み取って参加し、フィードバックや共同開発にご参加ください:
-
+
---
@@ -142,11 +131,11 @@ InfiPlot は 4 種類のモデルプロバイダと通信します。**テキス
|---|---|
| `MOCK_IMAGE=true` | 画像生成をスキップし、レンダラが静的なプレースホルダを返します。ストーリー・音声・選択肢は通常どおり動作します。Runware のクレジットを消費せずに TTS を調整するのに最適です。 |
-設定場所(正確なフォーマットは `apps/web/.env.example` を参照):
+設定場所(正確なフォーマットは `.env.example` を参照):
-- **ローカル開発** —— `apps/web/.env.local`
+- **ローカル開発** —— `.env.local`
- **Vercel** —— Project Settings → Environment Variables
-- **Cloudflare Workers** —— `apps/web/` から各変数について `wrangler secret put ` を実行するか、ダッシュボード(Workers → infiplot → Settings → Variables and Secrets)で設定します。ステージング環境にアクセス制限を掛けたい場合は、Worker の前に [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/applications/) を挟むと、ゼロコードでメール許可リスト方式の認証が利用できます。
+- **Cloudflare Workers** —— リポジトリのルートから各変数について `wrangler secret put ` を実行するか、ダッシュボード(Workers → infiplot → Settings → Variables and Secrets)で設定します。ステージング環境にアクセス制限を掛けたい場合は、Worker の前に [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/applications/) を挟むと、ゼロコードでメール許可リスト方式の認証が利用できます。
**3. コストに注意**
diff --git a/README.md b/README.md
index 8926544..989fe9d 100644
--- a/README.md
+++ b/README.md
@@ -39,11 +39,11 @@ InfiPlot是一款AI实时生成内容的互动剧情游戏,这里没有预设
## 一键部署
-InfiPlot 同时支持部署到 Vercel 与 Cloudflare Workers —— 任选其一即可。
+InfiPlot 同时支持部署到 Vercel 与 Cloudflare Workers。Cloudflare 部署因场景流水线需要更长 CPU 时间,需要 Workers Paid Plan;个人使用推荐用 Vercel 一键部署。
-[](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) [](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot/tree/main/apps/web)
+[](https://vercel.com/new/clone?repository-url=https://github.com/zonghaoyuan/infiplot&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) [](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot)
-部署完成后,填好环境变量 —— 详见下方的[配置教程](#配置教程)。两个平台都需要把项目根目录设为 `apps/web`(Vercel 一键部署按钮会自动带上;在 Cloudflare 上请把 build root 设为 `apps/web`,构建命令设为 `pnpm --filter @infiplot/web build:cf`)。
+部署完成后,填好环境变量 —— 详见下方的[配置教程](#配置教程)。仓库根目录就是应用本身:Vercel 无需额外设置 root directory;在 Cloudflare 上把构建命令设为 `pnpm build:cf` 即可。
---
@@ -77,20 +77,9 @@ InfiPlot 同时支持部署到 Vercel 与 Cloudflare Workers —— 任选其一
故事以一连串场景(scene)的形式展开。每个场景由一张 AI 绘制的背景图,加上一棵简短的节拍(beat)树组成 —— 也就是旁白、对话和偶尔出现的选项。你逐拍点过一个场景时,画面始终不变;只有当某个选项把你带到真正全新的地方 —— 换了空间、换了视角、跳跃了时间 —— AI 才会绘制下一幕场景。
-```mermaid
-flowchart TD
- U["你的输入:世界设定 + 画风"] --> A["架构师 / Architect
解析输入 → 完整剧情结构(第一步)"]
- A --> W["编剧 / Writer
生成本幕节拍:旁白 · 对话 · 选项"]
- subgraph SCENE["每一幕场景的生成"]
- direction TB
- W --> C["角色设计师 / Character Designer
立绘 + 音色(每个新角色并行)"]
- W --> S["场景布置师 / Cinematographer
镜头编排 + 背景提示词"]
- C --> P["画家 / Painter
以立绘为参考渲染 16:9 背景"]
- S --> P
- end
- P --> SC["一幕场景:背景图 + 节拍树"]
- SC -. 预测式预生成下一幕 .-> W
-```
+
+

+
当你正在阅读一幕场景时,引擎会预测式地生成你的选项可能通向的那些场景 —— 对于无法回避的下一步,还会再往前生成一幕。等你真正选定方向时,那一幕的图通常已经画好了,于是切换瞬间完成、毫无停顿。如果你现在仍然感到有些延迟,别担心,我们正在努力优化它。
@@ -117,7 +106,7 @@ flowchart TD
欢迎扫码加入 **InfiPlot 内测交流群**(QQ 群号 `575404333`),一起反馈体验、参与共建:
-
+
---
@@ -142,11 +131,11 @@ InfiPlot 会与四类模型供应商通信。**文本(Text)和视觉(Visio
|---|---|
| `MOCK_IMAGE=true` | 跳过图像生成,渲染器返回一张静态占位图。剧情、语音、选项照常运行。非常适合在不消耗 Runware 额度的情况下调试 TTS。 |
-在哪里设置(确切字段见 `apps/web/.env.example`):
+在哪里设置(确切字段见 `.env.example`):
-- **本地开发** —— `apps/web/.env.local`
+- **本地开发** —— `.env.local`
- **Vercel** —— Project Settings → Environment Variables
-- **Cloudflare Workers** —— 在 `apps/web/` 目录下逐个执行 `wrangler secret put `,或在 dashboard 里设置(Workers → infiplot → Settings → Variables and Secrets)。如果要给 staging 加访问限制,可以在 Worker 前面挂一个 [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/applications/)(零代码,邮箱白名单)。
+- **Cloudflare Workers** —— 在仓库根目录下逐个执行 `wrangler secret put `,或在 dashboard 里设置(Workers → infiplot → Settings → Variables and Secrets)。如果要给 staging 加访问限制,可以在 Worker 前面挂一个 [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/applications/)(零代码,邮箱白名单)。
**3. 注意成本**
diff --git a/apps/web/app/api/beat-audio/route.ts b/app/api/beat-audio/route.ts
similarity index 100%
rename from apps/web/app/api/beat-audio/route.ts
rename to app/api/beat-audio/route.ts
diff --git a/apps/web/app/api/insert-beat/route.ts b/app/api/insert-beat/route.ts
similarity index 100%
rename from apps/web/app/api/insert-beat/route.ts
rename to app/api/insert-beat/route.ts
diff --git a/apps/web/app/api/scene/route.ts b/app/api/scene/route.ts
similarity index 100%
rename from apps/web/app/api/scene/route.ts
rename to app/api/scene/route.ts
diff --git a/apps/web/app/api/start/route.ts b/app/api/start/route.ts
similarity index 100%
rename from apps/web/app/api/start/route.ts
rename to app/api/start/route.ts
diff --git a/apps/web/app/api/vision/route.ts b/app/api/vision/route.ts
similarity index 100%
rename from apps/web/app/api/vision/route.ts
rename to app/api/vision/route.ts
diff --git a/apps/web/app/globals.css b/app/globals.css
similarity index 100%
rename from apps/web/app/globals.css
rename to app/globals.css
diff --git a/apps/web/app/layout.tsx b/app/layout.tsx
similarity index 95%
rename from apps/web/app/layout.tsx
rename to app/layout.tsx
index bf87079..ec8a719 100644
--- a/apps/web/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,5 +1,6 @@
import type { Metadata } from "next";
import { Cormorant_Garamond, Inter } from "next/font/google";
+import { Analytics } from "@/components/Analytics";
import "./globals.css";
// Editorial fonts: drive tailwind `font-serif`/`font-sans` via
@@ -44,6 +45,7 @@ export default function RootLayout({
{children}
+