Omen is a full-stack Polymarket analytics app. It combines a Next.js frontend, a FastAPI backend, Postgres/Redis-backed ingestion jobs, and subgraph data to explore markets, users, positions, price history, order books, and holder behavior.
- Search for Polymarket markets and wallets from one command-style search bar.
- Open market pages with price charts, order books, rules, top holders, and holder PnL.
- Open user pages with PnL, open/closed positions, activity, and selectable market charts.
- Add markets and users to local watchlists.
- Use the home page Top Movers widget to find markets with large recent price changes.
frontend/- Next.js app with the main product UI.backend/- FastAPI service, API routes, Polymarket clients, DB models, and ingestion jobs.backend/docs/- notes for the upstream Polymarket APIs and subgraph queries used by the backend.backend/openapi.json- generated OpenAPI schema used for frontend API types.
Next.js frontend
-> FastAPI backend
-> Postgres
-> Redis
-> Polymarket Gamma/CLOB/Data APIs
-> GraphQL subgraphs
The frontend talks to the backend through NEXT_PUBLIC_API_URL. The backend stores market, trade, position, profile, and price-history data in Postgres, uses Redis for cached/worker data, and calls public Polymarket APIs plus subgraph endpoints for enriched analytics.
Requirements:
- Docker and Docker Compose for the backend, Postgres, and Redis.
- Node.js plus
pnpmfor the frontend. - Python 3.11 plus
uvif you want to run backend commands outside Docker.
cd backend
cp .env.example .env
docker compose -f docker-compose.dev.yml up --buildThe API will be available at http://localhost:8000.
For backend commands outside Docker, install/sync the Python environment with:
cd backend
uv sync --devPopulate local data from a second terminal:
cd backend
docker compose -f docker-compose.dev.yml exec app python -m src.db.db_init --reset
docker compose -f docker-compose.dev.yml exec app python -m src.db.db_populate_markets
docker compose -f docker-compose.dev.yml exec app python -m src.db.db_populate_trades
docker compose -f docker-compose.dev.yml exec app python -m src.db.db_populate_positions
docker compose -f docker-compose.dev.yml exec app python -m src.db.db_populate_price_historyTop Movers are based on price_delta, so the widget needs two price-history refreshes to show movement: the first run stores baseline prices, and a later run computes deltas against that baseline.
cd frontend
cp .env.example .env
pnpm install
pnpm devOpen http://localhost:3000.
If port 3000 is busy, run pnpm dev -- --port 3001 and update NEXT_PUBLIC_SITE_URL if you need exact local metadata URLs.
- Start the backend and frontend.
- Populate markets, trades, positions, and price history.
- Open the home page and use Top Movers or search to choose a market.
- Search for a wallet or open a holder from a market page.
- On a user page, click a position row or checkbox to show trade details and add that market to the chart area.
# frontend
cd frontend
pnpm lint
pnpm type-check
pnpm build
# backend
cd backend
uv sync --dev
uv run ruff check .
uv run ruff format .
uv run pip-audit
uv run python scripts/generate_types.py
# regenerate frontend API types from backend/openapi.json
cd frontend
pnpm type-genThis repo intentionally does not include secrets. Start from:
frontend/.env.examplebackend/.env.example
Most read-only product flows use public Polymarket APIs. Backend jobs that need authenticated CLOB access require POLYMARKET_PRIVATE_KEY; leave it empty unless you are intentionally running those flows with a dedicated development wallet.
- Omen is an analytics app, not investment advice or an automated trading system.
- Data quality depends on third-party APIs and indexed subgraphs.
- Local watchlists and dismissed UI hints are stored in browser local storage.
- If you fork this repo, rotate any local keys you previously used and run a secret scan before publishing your own copy.