5.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
PolyWeather Pro — a paid institutional weather-intelligence terminal for temperature settlement markets. 50 monitored cities, DEB multi-model temperature blending, Mu probability calibration, Polymarket CLOB/WS price integration. Next.js 15 + React 19 (Vercel) frontend, 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.
Environment & Preferences
- Working directory: repo root
- Python:
python(not python3), venv atvenv/ - Frontend:
cd frontend && npm run dev→ localhost:3000 - Backend:
uvicorn web.app:app --reload --host 0.0.0.0 --port 8000 - Package manager: npm (not yarn/pnpm)
- Commit language: Chinese (简体中文) ONLY
- NEVER start commit messages with
@— Chinese directly, no prefix
Commands
# Frontend
cd frontend
npm run dev # dev server :3000
npm run build # production build
npm run typecheck # tsc --noEmit
npm run test:business # 21 business state tests
# Backend
uvicorn web.app:app --reload --host 0.0.0.0 --port 8000
python bot_listener.py # Telegram bot
# Python tests
python -m pytest tests/
python -m pytest tests/test_supabase_entitlement.py
# Lint
ruff check .
ruff format .
# Docker (VPS)
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 + Polymarket scan)
Payment Layer (USDC on Polygon)
Telegram Bot → bot_listener.py
Frontend Structure
| Path | Purpose |
|---|---|
app/page.tsx |
Landing page (InstitutionalLandingPage) |
app/terminal/page.tsx |
Paid terminal (ScanTerminalDashboard) |
app/account/ |
Account center with payment/subscription |
app/auth/ |
Supabase login/signup |
components/dashboard/scan-terminal/ |
Terminal sub-components |
components/account/ |
Account + payment hooks |
components/landing/ |
Institutional landing page |
components/subscription/ |
UnlockProOverlay payment overlay |
lib/dashboard-types.ts |
All TypeScript types |
Terminal Component Map
ScanTerminalDashboard.tsx— entry, auth gate,ProductAccessRequiredPolyWeatherTerminal— main layout: sidebar + region tabs + 2-column gridCityRegionList— city list panel (left top)CityContractDetail— contract table panel (left bottom)LiveTemperatureThresholdChart— temperature trend + market thresholds (right)TrainingDashboard— DEB + Mu accuracy charts (sidebar tab)MarketOverviewView— regional heat + top opportunities (sidebar tab)GroupedMarketTable— contract comparison tablecontinent-grouping.ts— 7 trading regions, city-to-region mapping, timezone detection
Account Module
AccountCenter.tsx(~1280 lines) — main componentuseAccountPayment.ts— master payment hook, composes sub-hooksuseWalletBind.ts— EVM/WalletConnect bindingusePaymentFlow.ts— intent creation, payment, confirmationuseBilling.ts— subscription recovery, billing computation
Backend Key Files
| Path | Purpose |
|---|---|
web/routers/city.py |
City detail/summary/market-scan endpoints |
web/routers/scan.py |
Scan terminal aggregation |
web/services/city_payloads.py |
Market scan with Polymarket integration |
web/scan_terminal_city_row.py |
Builds terminal rows from analysis data |
src/data_collection/city_registry.py |
50-city registry with tz_offset |
src/data_collection/polymarket_readonly.py |
Market discovery, CLOB prices, WS cache |
src/data_collection/polymarket_ws_cache.py |
WebSocket quote cache |
src/analysis/deb_algorithm.py |
DEB prediction + Mu calibration + accuracy |
Auth Gating
Middleware (middleware.ts) handles two layers:
- Terminal gate (
handleTerminalGate):/terminal/*→ redirect to/auth/loginif no Supabase session - Global auth (
handleSupabaseAuthGate): enforced whenPOLYWEATHER_AUTH_REQUIRED=true
Client-side gate (ProductAccessRequired): /terminal checks auth + subscription via /api/auth/me, shows paywall if needed.
Local dev bypass: set NEXT_PUBLIC_POLYWEATHER_LOCAL_FULL_ACCESS=false to test auth locally.
Polymarket Integration
Price pipeline:
Gamma API (slug discovery) → CLOB REST + WS cache → market_scan → terminal rows
resolve_city_clob_tokens()— timezone-aware market discoverycollect_all_clob_token_ids()— all YES/NO tokens for WS subscriptionPolymarketWsQuoteCache— WebSocket quote cache (daemon thread)- Prices flow to terminal via
**rowspread in_build_terminal_row
Trading Regions
7 regions: east_asia, southeast_asia, central_asia, west_asia, europe_africa, south_america, north_america. Mappings in continent-grouping.ts (CITY_REGION_FALLBACK — all 50 cities hardcoded) and scan_terminal_filters.py (market_region_from_tz_offset). Default region auto-detected from browser timezone.
Code Style
- No
\uXXXXescapes — write characters directly in UTF-8 - Use
var(--color-*)CSS tokens, not hardcoded hex - Minimum font size: 10px (
text-[10px]) - Avoid
!importantexcept Leaflet map overrides - Remove dead code immediately when features are removed