Update production deployment references

This commit is contained in:
2569718930@qq.com
2026-06-14 23:13:37 +08:00
parent e909f1f4c9
commit ef21a5808e
11 changed files with 22 additions and 26 deletions
+7 -5
View File
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
PolyWeather Pro — a paid institutional weather-intelligence terminal. 50 monitored cities with real-time METAR/AMOS/MADIS observations, DEB multi-model temperature blending, Mu probability calibration, and intraday bias correction. Pure meteorological decision workspace; no market/price layer. Next.js 15 + React 19 (Vercel) frontend, FastAPI backend (VPS), Telegram bot.
PolyWeather Pro — a paid institutional weather-intelligence terminal. 50 monitored cities with real-time METAR/AMOS/MADIS observations, DEB multi-model temperature blending, Mu probability calibration, and intraday bias correction. Pure meteorological decision workspace; no market/price layer. Next.js 15 + React 19 frontend (Docker / VPS, behind Cloudflare + Nginx), FastAPI backend (VPS), Telegram bot.
**Business model**: Paid-only, $10/month, no free tier, no trial. Landing page is public; `/terminal` requires login + active subscription.
@@ -47,10 +47,12 @@ docker compose down && docker compose up -d --build
## Architecture
```
Users → Next.js (Vercel) → FastAPI :8000 (VPS)
/terminal (paid gate) Weather Collector
/ (landing page) Analysis (DEB + Mu)
Payment Layer (USDC on Polygon)
Users → Cloudflare → Nginx → Docker Compose (VPS)
├── Next.js frontend → FastAPI :8000
│ /terminal (paid gate) Weather Collector
│ / (landing page) Analysis (DEB + Mu)
│ Payment Layer (USDC on Polygon)
└── Redis (SSE event store)
Telegram Bot → bot_listener.py
```
+1 -1
View File
@@ -84,7 +84,7 @@ See: [AGPL-3.0 & Commercial Boundary](docs/OPEN_CORE_POLICY.md)
```mermaid
flowchart LR
U["Users (Web / Telegram)"] --> FE["Next.js Frontend (Vercel)"]
U["Users (Web / Telegram)"] --> FE["Next.js Frontend (Docker / VPS)"]
U --> BOT["Telegram Bot (VPS)"]
FE --> API["FastAPI /web/app.py"]
BOT --> API
+2 -2
View File
@@ -83,7 +83,7 @@
```mermaid
flowchart LR
U["用户(Web / Telegram"] --> FE["Next.js 前端(Vercel"]
U["用户(Web / Telegram"] --> FE["Next.js 前端(Docker / VPS"]
U --> BOT["Telegram BotVPS"]
FE --> API["FastAPI /web/app.py"]
BOT --> API
@@ -218,7 +218,7 @@ POLYWEATHER_OPS_ADMIN_EMAILS=yhrsc30@gmail.com
- AGPL-3.0 边界:[docs/OPEN_CORE_POLICY.md](docs/OPEN_CORE_POLICY.md)
- Supabase 接入:[docs/SUPABASE_SETUP_ZH.md](docs/SUPABASE_SETUP_ZH.md)
- 配置与密钥管理:[docs/CONFIGURATION_ZH.md](docs/CONFIGURATION_ZH.md)
- 前端部署(Vercel):[docs/FRONTEND_DEPLOYMENT_ZH.md](docs/FRONTEND_DEPLOYMENT_ZH.md)
- 前端部署(Docker / VPS):[docs/FRONTEND_DEPLOYMENT_ZH.md](docs/FRONTEND_DEPLOYMENT_ZH.md)
- 技术债:[docs/TECH_DEBT_ZH.md](docs/TECH_DEBT_ZH.md)
- 机场实时数据源:[docs/AIRPORT_REALTIME_SOURCES.md](docs/AIRPORT_REALTIME_SOURCES.md)
- 机场市场监控(中文):[docs/AIRPORT_MARKET_MONITOR_ZH.md](docs/AIRPORT_MARKET_MONITOR_ZH.md)
+1 -1
View File
@@ -43,7 +43,7 @@
首次建议打开扩展"选项页"并确认:
- `网站基础地址`:你的前端域名(例如 `https://polyweather-pro.vercel.app`
- `网站基础地址`:你的前端域名(例如 `https://polyweather.top`
- `API 基础地址`:你的后端 API 域名(若同域也可填前端域名)
- `Bearer Token`:后端开启鉴权时填写
+2 -2
View File
@@ -12,12 +12,12 @@
<label class="field">
<span id="siteBaseLabel">Site Base URL</span>
<input id="siteBaseInput" type="text" placeholder="https://polyweather-pro.vercel.app" />
<input id="siteBaseInput" type="text" placeholder="https://polyweather.top" />
</label>
<label class="field">
<span id="apiBaseLabel">API Base URL</span>
<input id="apiBaseInput" type="text" placeholder="https://polyweather-pro.vercel.app" />
<input id="apiBaseInput" type="text" placeholder="https://polyweather.top" />
</label>
<label class="field">
+2 -2
View File
@@ -1,6 +1,6 @@
const DEFAULT_CONFIG = {
apiBase: "https://polyweather-pro.vercel.app",
siteBase: "https://polyweather-pro.vercel.app",
apiBase: "https://polyweather.top",
siteBase: "https://polyweather.top",
authToken: "",
selectedCity: ""
};
+2 -2
View File
@@ -1,8 +1,8 @@
const DEFAULT_CONFIG = {
apiBase: "https://polyweather-pro.vercel.app",
apiBase: "https://polyweather.top",
authToken: "",
selectedCity: "",
siteBase: "https://polyweather-pro.vercel.app"
siteBase: "https://polyweather.top"
};
const CACHE_VERSION = "v3";
const locale = String(navigator.language || "en").toLowerCase().startsWith("zh")
+1 -4
View File
@@ -55,10 +55,7 @@ export async function POST(req: NextRequest) {
...(body ?? {}),
payload: {
...payload,
cf_country:
req.headers.get("cf-ipcountry") ||
req.headers.get("x-vercel-ip-country") ||
"",
cf_country: req.headers.get("cf-ipcountry") || "",
user_agent: req.headers.get("user-agent") || "",
referer_header: req.headers.get("referer") || "",
},
+1 -4
View File
@@ -165,10 +165,7 @@ async function trackAuthDiagnosticEvent(
response_mode: responseMode,
user_id: normalizedUserId || undefined,
email_domain: email?.includes("@") ? email.split("@").pop() : undefined,
cf_country:
req.headers.get("cf-ipcountry") ||
req.headers.get("x-vercel-ip-country") ||
"",
cf_country: req.headers.get("cf-ipcountry") || "",
user_agent: req.headers.get("user-agent") || "",
referer_header: req.headers.get("referer") || "",
captured_at: new Date().toISOString(),
@@ -41,7 +41,7 @@ async function findSupabaseUserIdByEmail(email: string) {
.replace(/\/$/, "");
const serviceRoleKey = String(process.env.SUPABASE_SERVICE_ROLE_KEY || "").trim();
if (!supabaseUrl || !serviceRoleKey) {
throw new Error("Supabase service role is not configured on Vercel");
throw new Error("Supabase service role is not configured on the server");
}
const profileRes = await fetch(
`${supabaseUrl}/rest/v1/profiles?select=id&email=eq.${encodeURIComponent(email)}&limit=1`,
+2 -2
View File
@@ -34,8 +34,8 @@ self.addEventListener("fetch", (event) => {
// Do not cache-first Next.js build chunks. A user can keep an old app shell
// open across deployments; if checkout UI is loaded later, stale/missing
// chunks surface as a generic page fault. Let the browser/Vercel handle
// immutable _next/static asset caching instead.
// chunks surface as a generic page fault. Let the browser handle immutable
// _next/static asset caching instead.
if (CACHEABLE_PUBLIC_ASSETS.includes(url.pathname)) {
event.respondWith(
caches.open(CACHE_NAME).then((cache) =>