CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
PolySignal β a real-time prediction market intelligence dashboard. It fetches market data from Polymarket, enriches it with financial news via Finnhub, runs AI sentiment analysis (ModernFinBERT + Qwen3-8B), and displays signals on an interactive world map. No real trading β pure analysis and virtual simulation. Built for CIFO Barcelona La Violeta Hackathon (May 2026). UI and docs are in Spanish, base currency is Euro (β¬).
Common Commands
# Development (backend + frontend simultaneously)
npm run dev:all
# Backend only (with --watch)
npm run dev
# Frontend only (Vite @ :5173)
npm run dev:frontend
# Production build (frontend)
npm run build:frontend
# Database
npm run db:migrate # Apply Prisma migrations
npm run db:generate # Regenerate Prisma client
npm run db:studio # Open Prisma Studio GUI
# Docker
docker-compose up --build # Full stack on port 7860
Node.js β₯24.0.0 is required (enforced in package.json engines).
First-time setup:
npm install
cp .env.example .env # then fill in API keys
npm run db:migrate && npm run db:generate
Architecture
Monorepo with two workspaces: backend/ (Express 5 + Socket.io) and frontend/ (Vanilla JS + Vite).
Backend (backend/src/)
Follows a strict Controller β Service β Repository β Client layered pattern. Each domain lives in its own directory:
| Directory | Responsibility |
|---|---|
markets/ |
Polymarket Gamma API client + sync job |
signals/ |
AI pipeline (aiPipeline.js) + signals service |
finnhub/ |
Finnhub news client + service |
positions/ |
Virtual position simulator + Kelly Criterion sizing |
watchlist/ |
User-saved markets |
alerts/ |
Telegram Bot notification delivery |
auth/ |
JWT + bcryptjs login |
socket/ |
Socket.io broadcaster |
middlewares/ |
Auth, validation, error handling, rate limiting |
utils/ |
Pino logger, HTTP client, Prisma singleton |
Entry points: src/index.js (HTTP server + Socket.io setup) β src/app.js (Express middleware + route mounting) β src/scheduler.js (cron jobs).
Environment/config validated at startup via Zod in src/config.js β the app crashes fast if required env vars are missing.
Scheduler Jobs
| Job | Frequency | What it does |
|---|---|---|
syncMarkets |
30s | Fetches top 100 active Polymarket markets, broadcasts price changes via Socket.io |
generateSignals |
5m | Runs full AI pipeline on top 20 active markets |
updatePositionsPnL |
30s | Recalculates P&L for open virtual positions |
processAlerts |
1m | Checks watchlist thresholds, fires Telegram alerts |
AI Signal Pipeline (signals/aiPipeline.js)
Three-phase flow with automatic fallbacks:
- News filtering β Finnhub headlines β ModernFinBERT (HF Space) β keep only scores β₯ 0.65, drop neutral
- Signal generation β market data + filtered news β Qwen3-8B (HF Space) β
{ signal, confidence, summary, keyRisk } - Fallback chain: HF Space β HF direct inference API β OpenRouter (deepseek-chat) β rule-based (price-trend logic)
Frontend (frontend/src/)
Single-page app with no framework. Key modules:
| File | Role |
|---|---|
app.js |
SPA routing, DOM rendering, Socket.io listeners |
api.js |
REST client wrapper with JWT token management |
map.js |
Leaflet world map (bubble size = volume, color = signal) |
charts.js |
Chart.js sparklines + 7-day price history |
simulator.js |
Virtual buy/sell logic |
filters.js |
Market filtering by category, country, continent, trend |
Vite proxies /api and /socket.io to backend (localhost:7860) during development.
Database (SQLite via Prisma)
Schema at backend/prisma/schema.prisma. Key models:
Marketβ Polymarket data (prices, volume, category, country code)AISignalβ sentiment signals with confidence and risk summaryPositionβ virtual trades with entry/exit prices and P&LWatchlist/Alertβ user market tracking and Telegram historyUserβ auth + optional Telegram chat ID
Real-time Communication
REST API at /api/v1/* + WebSocket events via Socket.io:
market_updateβ price/volume changesai_signalβ new sentiment signalsprice_alertβ watchlist threshold triggers
Deployment Target
The app is designed to run on HuggingFace Spaces (port 7860). The Dockerfile uses node:22-slim, installs backend deps, copies the frontend dist/, runs Prisma generate, and starts the server. The frontend is served as static files by Express in production.
Key Environment Variables
See .env.example for the full list. Critical ones:
HF_SPACE_MODERNFINBERT_URL # HuggingFace Space for FinBERT
HF_SPACE_QWEN_URL # HuggingFace Space for Qwen3-8B
HF_TOKEN # HF inference API key (fallback)
OPENROUTER_API_KEY # LLM fallback if HF is down
FINNHUB_API_KEY # News source
TELEGRAM_BOT_TOKEN # Alert delivery
JWT_SECRET # Must be β₯32 characters
PORT=7860 # Required by HF Spaces
DATABASE_URL=file:./backend/prisma/polysignal.db