Files
trumpsignal-frontend/CLAUDE.md
T
k ee3648c4cb docs: add CLAUDE.md — AI-agent project entry doc
Convention file every new Claude session reads first when opening this
repo. Documents:

  - Next.js 16 quirks (proxy.ts replaces middleware.ts, async params,
    i18n shelved).
  - Full route + component map.
  - API layer + auth model (EIP-191 signed envelopes).
  - Design system tokens (oklch colors, .macro-* classes, dark mode).
  - "Looks like a bug but isn't" section — including the /en/btc → /en/macro
    rename + the isZh=false i18n-shelved pattern.
  - SEO/GEO surface (layout.tsx JSON-LD + public/llms.txt + sitemap) that
    must be kept in sync when renaming features.
  - Cross-repo coupling points with the backend.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 11:04:19 +08:00

10 KiB
Raw Blame History

Trump Alpha — Frontend (trumpsignal.com)

Next.js 16 dashboard for the Trump Alpha backend. Real-time signals, Hyperliquid position management UI, KOL talks-vs-trades view, Macro Vibes regime panel. Read-only for the public; wallet-bound features (Pro) for auto-trade subscribers.

This is the AI-readable entry doc. Read this first on entering the repo.


What this repo is

  • Pure frontend — Next.js 16 App Router, TypeScript, server components + client components, deployed to Vercel.
  • Talks to a Python backend at https://api.trumpsignal.com (or localhost:8000 in dev). All trading state, signals, AI scoring, Hyperliquid integration lives in the sibling /Users/k/Public/Claude/ backend repo. See its CLAUDE.md.
  • No server-side trading logic lives here. Frontend is a thin layer over the API + WebSocket — even "open a position" routes to a backend endpoint that does the signed-request verification + HL call.

Stack quirks (Next.js 16 specific)

  • proxy.ts replaces middleware.ts in Next.js 16. Routes that need CORS / locale rewriting go through proxy.ts at the root.
  • params is async (Promise<{...}>) in all dynamic routes. ALL page components await it:
    export default async function Page({ params }: { params: Promise<{ locale: string }> }) {
      const { locale } = await params
      ...
    }
    
    Forgetting the await redirects to /undefined/... silently. Several pages were broken this way pre-v2.0 — be alert if you copy older patterns.
  • i18n is shelved. The [locale] segment exists, messages/zh.json exists, but Chinese branches are kept as dead code with a comment // i18n shelved — see messages/zh.json. Don't activate without an ADR. Currently isZh = false is hardcoded in metadata generators.
  • runtime = 'edge' on a few routes (app/icon.tsx, OG image generator). Edge runtime has no fs / no Node APIs — don't import server-side libs there.

Route map

app/
├── layout.tsx              Root layout: JSON-LD schema.org, fonts, meta
├── page.tsx                / (root) → redirects to /en
├── icon.tsx                Dynamic favicon (α on dark bg, edge runtime)
├── apple-icon.tsx          PWA install icon
├── opengraph-image.tsx     OG card generator (1200x630)
├── manifest.ts             PWA manifest
├── sitemap.ts              SEO sitemap.xml
├── robots.ts               robots.txt
└── api/
    └── proxy/[...path]/    Catch-all proxy to backend (CORS workaround)

app/[locale]/
├── page.tsx                Landing — pinned signals, live ticker, Trump feed
├── DashboardClient.tsx     Main 'use client' wrapper for the home dashboard
├── trump/page.tsx          /en/trump — Trump Truth Social signal stream
├── macro/page.tsx          /en/macro — Macro Vibes regime panel ★ renamed from /btc
├── kol/page.tsx            /en/kol — KOL talks-vs-trades
├── trades/page.tsx         /en/trades — closed trade history
├── posts/page.tsx          /en/posts — all Posts (signal + Trump)
├── archive/page.tsx        /en/archive — historical / paginated
├── settings/page.tsx       /en/settings — wallet connect, HL key, prefs
├── analytics/page.tsx      /en/analytics — performance metrics
├── case-studies/page.tsx   /en/case-studies — documented event walkthroughs
├── methodology/page.tsx    /en/methodology — how signals work
├── glossary/page.tsx       /en/glossary — AHR999, MVRV-Z, KOL, etc.
├── privacy/page.tsx
├── terms/page.tsx
├── contact/page.tsx
└── globals.css             Design system tokens + .macro-* classes

Components map (the meaningful ones)

components/
├── nav/Navbar.tsx              Top nav + tabs (Trump | Macro Vibes | KOL ...)
├── signals/
│   ├── SignalMonitor.tsx       Live signal stream (WS-driven)
│   ├── SourceChips.tsx         Filter chips per source
│   ├── SystemControl.tsx       Sys1/sys2 toggle widgets, Auto-Trade switch
│   └── ConfirmCloseTrade.tsx   Modal for manual close
├── dashboard/
│   ├── PostCards.tsx           Trump post cards
│   ├── SignalMonitor.tsx       (older — being consolidated)
│   └── BtcReversalAlert.tsx    Pinned alert when sys2 fires
├── btc/MacroPanel.tsx          ★ 8-indicator Macro Vibes layout (4 sections,
│                                 composite needle, threshold chips, peak-trail viz)
├── positions/
│   ├── OpenPositions.tsx       Polls /positions/open + /positions/today every 15s
│   └── TradeCard.tsx           Single trade row w/ grow toggle + close button
├── kol/KolDigest.tsx           Daily KOL summary widget
├── telegram/
│   ├── TelegramCard.tsx        Settings — connect via 6-char code
│   └── SignConfirmSheet.tsx    EIP-191 signed request preview
├── nav/WalletConnect.tsx       Wagmi-style wallet connect (MetaMask etc.)
├── ui/
│   ├── InfoTip.tsx             CSS-only tooltip with `?` icon
│   ├── PageHint.tsx            Strong page subtitle (replaces page-sub)
│   ├── Toast.tsx
│   └── Modal.tsx
└── ws/WsProvider.tsx           WebSocket singleton context provider

API layer

All API calls go through lib/api.ts. Single fetchJson<T> wrapper:

  • Reads base URL from env (NEXT_PUBLIC_API_URL) or proxies through /api/proxy/[...path]/ for same-origin CORS-free calls.
  • Wallet-scoped reads (/user/.../public, /positions/open) pass wallet as query param + signed ts/sig.
  • Mutations (subscribe, manual_close, set_auto_trade, manual-window) build an EIP-191 signed payload via wagmi → POST signed envelope.

Auth model: no sessions, no cookies. Wallet address + signed timestamp

  • signature on every mutating call. Verification lives in the backend (signed_request.verify_signed_request). The same wallet that signed the HL API key envelope at subscribe time is the only one that can later mutate the subscription.

State management

  • No global store (no Redux/Zustand). Tree-local state + props.
  • SWR-style cache in lib/cache.ts for the API-heavy pages.
  • WebSocket singleton via WsProvider — used by SignalMonitor and live price tickers.
  • localStorage holds wallet address only (for re-connect UX). HL API keys NEVER touch the client — they're submitted once at subscribe, sent encrypted, and decrypted only inside the backend.

Design system

Tokens in app/[locale]/globals.css:

  • Colorsoklch() color space throughout. Brand orange = #f5a524, brand dark = #0a0907. var(--up) green / var(--down) red / var(--ink-1..3) text tiers.
  • Dark mode via [data-theme="dark"] attribute on <html>. Most components use oklch(L% c h) so dark/light switching is automatic.
  • Macro Vibes specific — extensive .macro-* classes for the 8-indicator layout. Threshold chips have :not(.active) { opacity: 0.45 } and .active is tone-filled (green/red/amber).

Things that LOOK like bugs but aren't

  • Old code references "/en/btc" — Macro Vibes was renamed from "BTC Signal" in v2.0. All routes are now /en/macro. If you find a stale /en/btc reference, it's a real bug — fix it (we've found and fixed 3).
  • isZh = false in metadata generators — i18n was shelved pre-launch. See "Stack quirks" above.
  • Multiple proxy.ts patterns — Next.js 16 split middleware behaviour. Keep proxy logic in the single proxy.ts at root.
  • 'use client' directives on many pages — necessary for client-side WS / wallet interactions. Don't try to convert without verifying the WS
    • wagmi imports work in server components.

How to verify changes locally

# Type check (must pass with 0 errors)
npx tsc --noEmit

# Production build (catches missing pages, stale imports)
rm -rf .next && npx next build

# Dev server
npm run dev

# Pages-200 sweep (every locale page returns 200)
for p in /en /en/trump /en/macro /en/kol /en/trades /en/posts /en/settings \
         /en/methodology /en/glossary /en/case-studies /en/privacy /en/terms; do
  echo "$p $(curl -so /dev/null -w '%{http_code}' http://localhost:3000$p)"
done

SEO / GEO surface (don't break)

  • app/layout.tsx has JSON-LD schema.org markup (Organization, SoftwareApplication, FAQ). Search engines + AI crawlers read this.
  • public/llms.txt — canonical doc for AI crawlers (Perplexity, ChatGPT browse, Google AI Overviews). Edit BOTH this file AND layout.tsx when renaming product features.
  • app/sitemap.ts — sitemap.xml. Add new routes here.
  • OG imageapp/opengraph-image.tsx dynamically renders the social card. Keep the brand pill list in sync with current features.

Coupling to backend

  • API contract lives in TypeScript types under lib/api.ts (e.g. OpenPositionsResponse, TodayStats, BotTrade). These must match the backend Pydantic models in app/api/*/positions.py etc.
  • When backend adds a field (e.g. BotTrade.released_at), this repo's lib/api.ts types may need updating to surface it in the UI. Currently released trades are FILTERED OUT by the backend's /positions/open — they don't appear here, so no UI for "managed vs released" yet.
  • When backend renames a route (e.g. /btc/page.tsx/macro/page.tsx), search for ALL references (including telegram deep-link map in backend/app/services/telegram.py).

Deploy

Vercel auto-deploys main branch pushes. No special build flags. Env vars in Vercel dashboard:

  • NEXT_PUBLIC_API_URL — backend HTTPS origin
  • NEXT_PUBLIC_SITE_URL — canonical site URL (used for OG, sitemap)
  • NEXT_PUBLIC_WS_URL — WebSocket endpoint (usually wss://api...)

Sibling repo

  • /Users/k/Public/Claude/backend — Python/FastAPI backend, includes Hyperliquid integration, Telegram bot, AI scoring (DeepSeek), all signal scanners, the adoption/release flow. See its CLAUDE.md.