This commit is contained in:
richarjiang
2026-03-13 11:00:01 +08:00
commit fa4c458eda
51 changed files with 8843 additions and 0 deletions

54
CLAUDE.md Normal file
View File

@@ -0,0 +1,54 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
OpenClaw Market is a real-time global heatmap dashboard that visualizes AI agent ("lobster") activity worldwide. Agents install the `openclaw-reporter` skill, which sends anonymous heartbeats and task summaries to this server. The frontend renders a 3D globe and dashboard panels showing live activity via SSE.
## Commands
```bash
pnpm dev # Start dev server with Turbopack (localhost:3000)
pnpm build # Production build
pnpm lint # ESLint
pnpm db:generate # Generate Drizzle migrations
pnpm db:push # Push schema to database (no migration files)
pnpm db:migrate # Run migrations
pnpm db:studio # Open Drizzle Studio GUI
bash scripts/deploy.sh # Build locally, rsync to server, restart PM2
```
## Architecture
### Data Flow
1. **Reporter skill** (`skill/openclaw-reporter/SKILL.md`) runs inside Claude Code sessions on user machines. It calls `/api/v1/register` once, then sends periodic heartbeats and task reports via Bearer token auth.
2. **API routes** (`app/api/v1/`) validate requests, update MySQL via Drizzle, cache state in Redis, and publish events to a Redis Pub/Sub channel (`channel:realtime`).
3. **SSE endpoint** (`/api/v1/stream`) subscribes to Redis Pub/Sub and streams events to the browser.
4. **Frontend** is a single-page "use client" app. The homepage renders a 3D globe (`react-globe.gl`), dashboard panels, and a continent drill-down page. Data arrives via polling (`use-heatmap-data`) and SSE (`use-sse`).
### Key Layers
- **Auth**: Bearer token via `lib/auth/api-key.ts`. API keys are generated at registration, cached in Redis for 1 hour.
- **Geo**: IP geolocation via `ip-api.com`, results cached in `geo_cache` MySQL table. Country-to-continent mapping in `lib/geo/ip-location.ts`.
- **Real-time**: Redis Pub/Sub (`lib/redis/index.ts`) for event broadcasting. SSE stream route creates a per-connection Redis subscriber.
- **Validation**: Zod schemas in `lib/validators/schemas.ts`.
- **Database**: Drizzle ORM with MySQL (`mysql2` driver). Schema in `lib/db/schema.ts`. Tables: `lobsters`, `heartbeats`, `tasks`, `geo_cache`.
- **Redis**: ioredis with two singleton clients (main + subscriber). Stores online status, active lobster sorted sets, global/region stats, hourly activity, heatmap cache.
### Frontend Structure
- `components/globe/` — 3D globe view using `react-globe.gl` (dynamically imported, no SSR)
- `components/map/` — 2D continent maps using `react-simple-maps`
- `components/dashboard/` — Stats panel, region ranking, activity timeline, lobster feed
- `components/layout/` — Navbar, particle background, view switcher, install banner
- `app/continent/[slug]/page.tsx` — Continent drill-down page
## Environment Variables
See `.env.example`: `DATABASE_URL` (MySQL), `REDIS_URL`, `IP_API_URL`, `NEXT_PUBLIC_APP_URL`.
## Deployment
Production runs on a remote server via `scripts/deploy.sh` — builds locally, rsyncs to server, installs prod deps, restarts via PM2 on port 3003.