Files
PolyWeather/CLAUDE.md
T

137 lines
5.5 KiB
Markdown

# 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 at `venv/`
- 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
```bash
# 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, `ProductAccessRequired`
- `PolyWeatherTerminal` — main layout: sidebar + region tabs + 2-column grid
- `CityRegionList` — 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 table
- `continent-grouping.ts` — 7 trading regions, city-to-region mapping, timezone detection
### Account Module
- `AccountCenter.tsx` (~1280 lines) — main component
- `useAccountPayment.ts` — master payment hook, composes sub-hooks
- `useWalletBind.ts` — EVM/WalletConnect binding
- `usePaymentFlow.ts` — intent creation, payment, confirmation
- `useBilling.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:
1. **Terminal gate** (`handleTerminalGate`): `/terminal/*` → redirect to `/auth/login` if no Supabase session
2. **Global auth** (`handleSupabaseAuthGate`): enforced when `POLYWEATHER_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 discovery
- `collect_all_clob_token_ids()` — all YES/NO tokens for WS subscription
- `PolymarketWsQuoteCache` — WebSocket quote cache (daemon thread)
- Prices flow to terminal via `**row` spread 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 `\uXXXX` escapes — write characters directly in UTF-8
- Use `var(--color-*)` CSS tokens, not hardcoded hex
- Minimum font size: 10px (`text-[10px]`)
- Avoid `!important` except Leaflet map overrides
- Remove dead code immediately when features are removed