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. -[![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)   [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot/tree/main/apps/web) +[![Deploy with Vercel](https://vercel.com/button)](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)   [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](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 -``` +
+ InfiPlot story generation pipeline +
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: -InfiPlot beta community QQ group QR code +InfiPlot beta community QQ group QR code --- @@ -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 のワンクリックデプロイをおすすめします。 -[![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)   [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot/tree/main/apps/web) +[![Deploy with Vercel](https://vercel.com/button)](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)   [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](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 -``` +
+ InfiPlot 物語生成パイプライン +
あなたがひとつのシーンを読んでいる間に、エンジンは選択肢が導きうるシーンを先回りして生成します —— 避けられない次の一歩については、そのさらに先のシーンまで。あなたが方向を選ぶ頃には、その画像はたいてい描き上がっているので、切り替えは一瞬に感じられます。いまはまだ多少の遅延を感じるかもしれませんが、ご安心ください —— 私たちは鋭意改善に取り組んでいます。 @@ -117,7 +106,7 @@ flowchart TD **InfiPlot ベータ交流グループ**(QQ グループ番号 `575404333`)—— QR コードを読み取って参加し、フィードバックや共同開発にご参加ください: -InfiPlot ベータ交流グループ QQ QRコード +InfiPlot ベータ交流グループ QQ 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 一键部署。 -[![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)   [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/zonghaoyuan/infiplot/tree/main/apps/web) +[![Deploy with Vercel](https://vercel.com/button)](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)   [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](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 -``` +
+ InfiPlot 生成流水线流程图 +
当你正在阅读一幕场景时,引擎会预测式地生成你的选项可能通向的那些场景 —— 对于无法回避的下一步,还会再往前生成一幕。等你真正选定方向时,那一幕的图通常已经画好了,于是切换瞬间完成、毫无停顿。如果你现在仍然感到有些延迟,别担心,我们正在努力优化它。 @@ -117,7 +106,7 @@ flowchart TD 欢迎扫码加入 **InfiPlot 内测交流群**(QQ 群号 `575404333`),一起反馈体验、参与共建: -InfiPlot 内测交流群 QQ 二维码 +InfiPlot 内测交流群 QQ 二维码 --- @@ -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} + ); diff --git a/apps/web/app/new/page.tsx b/app/new/page.tsx similarity index 100% rename from apps/web/app/new/page.tsx rename to app/new/page.tsx diff --git a/apps/web/app/page.tsx b/app/page.tsx similarity index 99% rename from apps/web/app/page.tsx rename to app/page.tsx index 2b2a59d..d859020 100644 --- a/apps/web/app/page.tsx +++ b/app/page.tsx @@ -744,6 +744,8 @@ export default function HomePage() { 目前,内测期间生成的内容不会被保存,如有需要,请通过录屏或截图等方式保存游玩体验,并记录下生成故事时的提示词与风格选项等。
AI 生成的内容不代表本团队立场。 +
+ 本站使用开源的 Umami 进行隐私友好的匿名访问统计:不使用 Cookie、不收集个人信息、不做跨站追踪。

diff --git a/apps/web/app/play/page.tsx b/app/play/page.tsx similarity index 100% rename from apps/web/app/play/page.tsx rename to app/play/page.tsx diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts deleted file mode 100644 index 29b64b4..0000000 --- a/apps/web/next.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import path from "node:path"; -import type { NextConfig } from "next"; - -const config: NextConfig = { - reactStrictMode: true, - typedRoutes: false, - transpilePackages: [ - "@infiplot/engine", - "@infiplot/ai-client", - "@infiplot/types", - "@infiplot/tts-client", - ], - turbopack: { - root: path.join(__dirname, "..", ".."), - }, -}; - -export default config; diff --git a/apps/web/package.json b/apps/web/package.json deleted file mode 100644 index 571477f..0000000 --- a/apps/web/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@infiplot/web", - "version": "0.1.0", - "private": true, - "type": "module", - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint", - "typecheck": "tsc --noEmit", - "build:cf": "opennextjs-cloudflare build", - "preview:cf": "opennextjs-cloudflare preview", - "deploy:cf": "opennextjs-cloudflare deploy" - }, - "dependencies": { - "@infiplot/ai-client": "workspace:*", - "@infiplot/engine": "workspace:*", - "@infiplot/types": "workspace:*", - "next": "^16.0.0", - "react": "^19.0.0", - "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", - "wrangler": "^4.96.0" - } -} diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json deleted file mode 100644 index 203069b..0000000 --- a/apps/web/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "noEmit": true, - "incremental": true, - "plugins": [{ "name": "next" }], - "paths": { - "@/*": ["./*"] - } - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/components/Analytics.tsx b/components/Analytics.tsx new file mode 100644 index 0000000..375e3cc --- /dev/null +++ b/components/Analytics.tsx @@ -0,0 +1,18 @@ +import Script from "next/script"; + +// Privacy-friendly, cookieless page-view analytics (Umami). Both env vars +// unset → render nothing, so local dev and forks never report to our instance. +export function Analytics() { + const src = process.env.NEXT_PUBLIC_UMAMI_SRC; + const websiteId = process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID; + if (!src || !websiteId) return null; + + return ( +