66 lines
3.2 KiB
Markdown
66 lines
3.2 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
@AGENTS.md
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
npm run dev # Start dev server (localhost:3000)
|
|
npm run build # Production build (standalone output)
|
|
npm run start # Start production server
|
|
npm run lint # ESLint (eslint-config-next/core-web-vitals + typescript)
|
|
```
|
|
|
|
Docker deployment: port 8019. Default `docker-compose.yml` uses `.env.production` and external network `sinobridge`; Coolify uses `docker-compose.coolify.yml` with runtime env from Coolify and external network `coolify`.
|
|
|
|
## Architecture
|
|
|
|
Next.js 16 App Router analytics dashboard for an API gateway. React 19, TypeScript strict mode, Tailwind CSS 4, Recharts 3, PostgreSQL.
|
|
|
|
**TypeScript: Never use `any` type.** Always define proper interfaces/types for all data structures. Use `unknown` with type narrowing if the type is truly unknown.
|
|
|
|
### Three Global Contexts (wrapped in `components/ClientProviders.tsx`)
|
|
|
|
1. **ThemeProvider** (`lib/theme.tsx`) — light/dark/system, localStorage `theme`, supports iframe embedding via `?theme=` query param and postMessage sync
|
|
2. **I18nProvider** (`lib/i18n.tsx`) — zh/en, localStorage `locale`, all translation keys in a single `translations` object
|
|
3. **TimeRangeProvider** (`lib/time-range-context.tsx`) — today/7d/30d/all/custom, localStorage `time-range`, exposes `getEffectiveRange()` returning `{ start?, end? }` unix timestamps (seconds)
|
|
|
|
Pages consume these via `useTheme()`, `useI18n()`, `useTimeRange()`. The `TimeRangeSelector` component reads from context (no props).
|
|
|
|
### Data Flow
|
|
|
|
Pages call `getEffectiveRange()` → `buildQuery("/api/...", { start, end })` → API route → `lib/queries.ts` SQL → PostgreSQL → JSON response → Recharts/tables.
|
|
|
|
### Database Layer (`lib/db.ts`, `lib/queries.ts`)
|
|
|
|
- `pg` pool (max 10 connections), env var `PG_CONNECTION_STRING`
|
|
- All queries filter `type = 2`, timezone `Asia/Shanghai`
|
|
- Real model name resolution: `COALESCE(other::jsonb->>'upstream_model_name', model_name)`
|
|
- Quota to USD: `quota / 500000`
|
|
- Parameterized queries with `$N` positional params
|
|
|
|
### API Routes (all GET, query-param driven)
|
|
|
|
| Route | Key Params | Returns |
|
|
|-------|-----------|---------|
|
|
| `/api/overview` | start, end | Aggregate stats (calls, tokens, users, models, channels) |
|
|
| `/api/trends` | start, end, granularity (day/week/month) | Time-series array |
|
|
| `/api/rankings` | start, end, type (user/model/channel), limit | Ranked items |
|
|
| `/api/detail/[type]/[id]` | start, end | Stats + breakdown (models or users) |
|
|
| `/api/logs` | start, end, page, page_size, username, model, token_name | Paginated logs |
|
|
| `/api/aggregation` | start, end | All users aggregated (top 500) |
|
|
|
|
### Styling
|
|
|
|
CSS variables in `globals.css` — dark theme default (cyan `#00e5ff` accent), light theme (blue `#0284c7`). Key classes: `.glass` (glassmorphic card), `.gradient-text`, `.btn-accent`, `.input-glass`, `.row-glow`. Portal page (`/portal`) has its own extensive animation system.
|
|
|
|
### Path Alias
|
|
|
|
`@/*` maps to project root (tsconfig).
|
|
|
|
### Fonts
|
|
|
|
Outfit (sans, `--font-geist-sans`) and JetBrains Mono (mono, `--font-geist-mono`) via `next/font/google`.
|