A prediction market dashboard tracking Polymarket predictions for major technology companies, providing real-time insights into market sentiment about tech company events and leadership.
- Multi-Company Tracking: View prediction markets for Apple, Google, Microsoft, Amazon, Meta, Tesla, and NVIDIA
- Enhanced Stock Metrics: Comprehensive daily data including current price, daily change %, day's high, and day's low
- Market Intelligence: Display active and resolved markets with yes/no probabilities, trading volume, and resolution dates
- Color-Coded Performance: Green for gains, red for losses with automatic calculation
- Hybrid Data Fetching: Intelligent API strategy that balances speed and coverage
- Automatic Daily Refresh: Data updates once per day via Vercel Cron
- Smart Caching: 5-minute page revalidation for fresher data, cache-busting on manual refresh
- Responsive Design: Mobile-first carousel navigation and adaptive grid layouts
- Admin-Only Manual Refresh: Secure manual data refresh with environment variable control and custom dialog
Copy .env.example to .env.local and fill in the required values:
cp .env.example .env.localDATABASE_URL (Required)
- PostgreSQL connection string from Neon
- Format:
postgresql://user:password@host/dbname?sslmode=require
FINNHUB_API_KEY (Required for stock prices)
- Get a free API key at: https://finnhub.io/dashboard
- Free tier: 60 requests per minute (more than sufficient for daily refresh)
CRON_SECRET (Required for data refresh)
- Used to protect the refresh endpoint
- Generate a secure random string:
openssl rand -hex 32 - Must be set both locally and in Vercel environment variables
MANUAL_DATA_REFRESH (Optional - for admin features)
- Controls visibility of manual data refresh button
- Set to 'true' to enable admin-only manual refresh feature
- When false or unset, refresh button is hidden and API endpoint returns 403
- Provides defense-in-depth security (frontend + backend enforcement)
The database schema includes three main tables:
companies: Tech companies being trackedstock_data: Current stock prices with comprehensive daily metrics (high, low, open, previous_close)polymarket_predictions: Prediction markets with event slug support
Create the database schema:
psql $DATABASE_URL -f scripts/create_schema.sqlThis script creates all tables, indexes, and inserts the initial set of tracked companies.
Optional: Clear predictions (when needed):
psql $DATABASE_URL -f scripts/clear_predictions.sqlUse this to remove all prediction market data and force a fresh fetch. Useful when:
- Testing changes to market filters
- Removing stale or duplicate markets
- Updating search logic
Once environment variables are configured:
Option A: Use the Dashboard UI (Requires MANUAL_DATA_REFRESH=true)
- Set environment variable:
MANUAL_DATA_REFRESH=true - Start your dev server:
npm run dev - Click the "Refresh Data" button in the dashboard header
- Enter your refresh key in the dialog
- Click OK and wait 5-10 seconds for data to load
Option B: Use cURL
curl -X POST http://localhost:3000/api/refresh \
-H "Authorization: Bearer $CRON_SECRET"This will fetch:
- Comprehensive stock data from Finnhub API (price, high, low, open, previous close) with 1-hour caching
- Prediction markets from Polymarket Gamma API (using hybrid events + pagination approach)
Note: After manual refresh, the page automatically reloads with cache-busting to show fresh data immediately. Pages revalidate every 5 minutes for automatic freshness.
The Vercel Cron job runs once daily at midnight UTC to automatically refresh all data.
Cron Schedule: 0 0 * * * (runs at 00:00 UTC)
Frequency: Once per day (Vercel free plan limit)
Expected Load: ~70 API calls per refresh (well within free tier limits)
GET /api/companies- List all active companies with stock dataGET /api/markets/[ticker]- Get prediction markets for a specific company (limit 25)POST /api/refresh- Trigger manual data refresh (requires Bearer token authorization)
- Frontend: Next.js 16 with App Router, React 19, Server Components
- Database: Neon PostgreSQL with Vercel Postgres SDK
- APIs:
- Finnhub Stock API (free tier: 60 calls/minute, comprehensive quote data)
- Polymarket Gamma API (no rate limits)
- Scheduling: Vercel Cron (daily refresh at midnight UTC)
- Styling: Tailwind CSS v4.1.9 with OKLCH color space and Polymarket branding
- UI Components: shadcn/ui (Radix UI primitives) + Embla Carousel
- Deployment: Vercel with ISR (5-minute revalidation)
Company tabs display comprehensive information:
- Full company name (e.g., "Meta (Facebook)")
- Stock ticker (e.g., "META")
- Current stock price (e.g., "$620.80")
Benefits: Users see all stock prices at a glance without switching tabs.
Replaced the large stock card with a responsive 4-column grid:
| Current Price | Daily Change | Day's High | Day's Low |
|---|---|---|---|
| $438.57 | +2.45% | $440.50 | $435.20 |
Features:
- Color-coded daily change (green for positive, red for negative)
- Automatic percentage calculation from previous close
- Responsive: 2 columns on mobile, 4 columns on desktop
- Subtle background with optimal spacing
The dashboard uses an intelligent hybrid approach to fetch Polymarket predictions:
-
Events-Based Primary (7-10 API calls):
- Efficient for companies with dedicated event pages (Apple, Google, Tesla, NVIDIA)
- Searches through events by company name, extracts markets
- ~5-7x faster than pagination
-
Pagination Fallback (50 API calls):
- Reliable for companies with scattered markets (Microsoft, Amazon, Meta)
- Searches through individual markets in batches of 100
- Guarantees coverage even when events-based fails
-
Max Selection Logic:
- If events-based finds <5 markets, trigger pagination
- Return whichever approach found MORE markets
- Result: 31% fewer API calls with 25-75% better coverage
- Alternate Search Terms: Company-specific keywords (e.g., "gemini" for Google, "iphone" for Apple) capture product-specific markets
- Word Boundary Matching: Prevents false positives (e.g., "Amazon" won't match "Amazonia")
- Stale Data Cleanup: Automatically removes markets >7 days old
Polymarket groups related markets under shared event pages (e.g., "Next CEO of Apple?" contains multiple candidates). The dashboard:
- Tracks parent
event_slugfor grouped markets - Uses
event_slugwhen present, falls back tomarket_slugfor standalone markets - Ensures all prediction links navigate to the correct Polymarket page
# Install dependencies
npm install
# Run development server
npm run dev
# Build for production
npm run build
# Start production server
npm start- API Implementation:
/documentation/apiImplementation.md- Comprehensive guide to data fetching strategies, enhanced stock metrics, caching, and critical technical decisions - Design System:
/documentation/design.md- UI/UX specifications, Polymarket branding, and component guidelines
- API Efficiency: 31% fewer calls than baseline pagination approach (~34 calls per company avg)
- Coverage: 25-75% more markets found for major companies (Apple, Google)
- Stock Data: Comprehensive 6-field capture (price, high, low, open, previous_close, market_cap)
- Page Performance: 5-minute ISR revalidation balances freshness with speed
- Cache Strategy: 1-hour stock API caching protects against refresh spam
- Cost: $0/month (within free tier limits for all services)
- Freshness: Daily automated updates at midnight UTC + manual refresh with cache-busting
When adding new companies or features:
- Add company to
companiestable (updatescripts/create_schema.sqlor add via SQL INSERT) - Add alternate search terms to
getAlternateSearchTerms()in/app/api/refresh/route.ts - Test using manual refresh before enabling automatic updates
- Update documentation to reflect changes
MIT