- Adopt TanStack React Query for all data fetching/caching.
- Call all available API endpoints with correct shapes.
- Handle WebSocket streams for live updates.
- Maintain clean separation: api client, hooks, UI.
- GET
/signals/top?window=24h&limit=5- Response:
{ tokenId, chain, address, symbol?, score, label, at }[]
- Response:
- GET
/signals/:chain/:address- Response:
{ tokenId, score, label, at }[]
- Response:
- GET
/prophecies/today- Response:
{ tokenId, chain, address, symbol?, score, rank, signalHash, txHash?, postedAt }[]
- Response:
- GET
/health- Response:
{ ok: boolean, db: 'ok'|'error' }
- Response:
Environment
NEXT_PUBLIC_API_URLe.g.,http://localhost:3001
apps/frontend/lib/api/client.ts— fetch wrapper (baseURL, headers, error normalize)lib/api/types.ts— DTO types mirroring backendlib/query/keys.ts— central query keyslib/query/hooks.ts— React Query hookslib/ws/socket.ts— WS client, listenersproviders/query-provider.tsx— QueryClientProvider (retry, staleTime, etc.)components/— UI consuming hooks
export type ApiSignalTop = {
tokenId: string;
chain: string;
address: string;
symbol?: string;
score: number;
label: 'HYPE_BUILDING'|'FAKE_PUMP'|'DEAD_ZONE'|'WHALE_PLAY';
at: string;
};
export type ApiTokenSignals = {
tokenId: string;
score: number;
label: ApiSignalTop['label'];
at: string;
}[];
export type ApiProphecy = {
tokenId: string;
chain: string;
address: string;
symbol?: string;
score: number;
rank: number;
signalHash: string;
txHash?: string;
postedAt: string;
};export const qk = {
signals: {
top: (window: '1h'|'24h'|'7d', limit: number) => ['signals','top', window, limit] as const,
token: (chain: string, address: string, limit?: number) => ['signals','token', chain, address, limit] as const,
},
prophecies: {
today: () => ['prophecies','today'] as const,
},
health: () => ['health'] as const,
};useTopSignals(window='24h', limit=10)- GET
/signals/top - staleTime: 10s; refetchInterval: 10–15s (plus WS updates)
- GET
useTokenSignals(chain, address, limit=50)- GET
/signals/:chain/:address - staleTime: 15s; refetch on window focus
- GET
usePropheciesToday()- GET
/prophecies/today - staleTime: 60s; refetchInterval: 60s (plus WS updates)
- GET
useHealth()- GET
/health - staleTime: 30s; retry: false
- GET
- WS URL:
ws://<API_HOST>:<PORT> - Subscriptions:
type: 'signals:live'→ payload{ tokenId, score, label, at }type: 'prophecies:today'→ payloadApiProphecy[](batch)
- Strategy:
- On
signals:live, optimistic updateqk.signals.topcache by preprending/re-sorting if token exists. - On
prophecies:today, invalidateqk.prophecies.today()and optionally merge payload. - Gracefully degrade: if WS closed, rely on refetch intervals.
- On
- Dashboard
- Replace ad-hoc fetch in
components/signal-table.tsxwithuseTopSignals. - Add filter controls for window (1h/24h/7d) and limit.
- Live updates via WS + cache update.
- Replace ad-hoc fetch in
- Token detail page
- Use
useTokenSignalsfor recent scores; small trend chart client-side.
- Use
- Simple Prophecies section
- Use
usePropheciesTodayto list rank, token, score, posted time.
- Use
- Add
QueryClientProviderat root layout:- defaultOptions:
{ queries: { retry: 1, refetchOnWindowFocus: false } } - Devtools optional for local.
- defaultOptions:
- Centralized
ErrorFallbackandSkeletoncomponents. - For 429/5xx, show inline retry CTA; surface rate limit hints.
- Mock API via MSW for component tests of hooks.
- Manual E2E:
- Run worker+API.
- Verify dashboard updates from WS without manual refresh.
- Switch window filters and see query keys/result change.
- Add QueryClientProvider, api client, types, keys.
- Migrate dashboard list to
useTopSignals+ WS updates. - Add token detail with
useTokenSignals. - Add prophecies list with
usePropheciesToday+ WS invalidation. - Polish: error states, loading, empty states.
- Frontend (Next.js) is present and can run independently; it expects API at
NEXT_PUBLIC_API_URL(defaulthttp://localhost:3001). - WebSocket support in API is functional; enabling
REDIS_URLimproves live updates.
Direction: focus on polishing components and hooking live WS events to UI charts; add local dev docker compose to run API + Worker + Redis for integrated testing.