This document summarizes the prediction markets frontend infrastructure that has been implemented.
File: /web/src/lib/types/prediction-markets.ts
Exports:
Platform- 'kalshi' | 'polymarket'PredictionMarket- Core market data interfaceMarketPricePoint- Historical price pointWatchlistItem- User's watchlist entryThesisMarketLink- Link between thesis and marketMarketFilters- Filter/sort options
File: /web/src/lib/stores/prediction-markets-store.ts
State Management:
- Markets list with pagination
- User watchlist (persisted to localStorage)
- Filter state (persisted to localStorage)
- Loading states and error handling
- Selected market for detail view
Actions:
setFilters()- Update filter statesetMarkets()/appendMarkets()- Manage market dataaddToWatchlist()/removeFromWatchlist()- Watchlist managementupdateWatchlistItem()- Update watchlist entryisInWatchlist()- Check if market is watchedreset()- Clear all state
Persistence:
- Watchlist and filters are persisted to localStorage
- Markets data is session-only (not persisted)
File: /web/src/lib/api/prediction-markets.ts
Functions:
fetchTrendingMarkets(options)- Get trending markets with filterssearchMarkets(query)- Search markets by textfetchMarketDetail(platform, marketId)- Get detailed market info
All functions return typed responses with optional mock flag.
File: /web/src/hooks/usePredictionMarkets.ts
The main hook for using prediction markets in React components.
Exports:
loadMarkets()- Fetch markets based on current filterssearchMarkets(query)- Search marketsloadMarketDetail(platform, marketId)- Load detailed infotoggleWatchlist(market)- Add/remove from watchlistsetFilters()- Update filter state- All store state (markets, watchlist, selectedMarket, etc.)
File: /web/src/app/api/prediction-markets/route.ts
- Endpoint:
GET /api/prediction-markets - Params:
limit,category,source - Returns: Array of trending markets
- Mock Data: 8 sample markets when backend unavailable
File: /web/src/app/api/prediction-markets/search/route.ts
- Endpoint:
GET /api/prediction-markets/search?q={query} - Params:
q(required) - Returns: Filtered markets matching query
- Mock Data: Filters mock markets by title/category
File: /web/src/app/api/prediction-markets/[platform]/[marketId]/route.ts
- Endpoint:
GET /api/prediction-markets/{platform}/{marketId} - Returns: Detailed market info with price history
- Mock Data: 3 detailed mock markets
File: /PREDICTION_MARKETS_USAGE.md
Comprehensive guide with examples for:
- Basic market list
- Search functionality
- Filters and sorting
- Watchlist management
- Market detail view
- Direct API usage
- Direct store usage
All API routes automatically fall back to realistic mock data when the backend is unavailable. This allows:
- Frontend development independent of backend
- UI testing without live data
- Graceful degradation in production
Mock markets include:
- Fed rate decisions (Kalshi)
- Bitcoin price predictions (Polymarket)
- NVIDIA earnings (Kalshi)
- Tesla deliveries (Polymarket)
- Inflation data (Kalshi)
- SPY price levels (Polymarket)
- Oil prices (Kalshi)
- Apple market cap (Polymarket)
- Watchlist saved to localStorage (survives page refresh)
- Filter preferences saved to localStorage
- Markets data is session-only (refetched on page load)
Full TypeScript support throughout:
- All interfaces exported from central types file
- Strict typing on API responses
- Type-safe store actions
- Typed hook return values
useCallbackhooks prevent unnecessary re-renders- Zustand store partialize for selective persistence
- No-cache policy on API routes for fresh data
- Efficient watchlist lookups
The hook pattern (usePredictionMarkets) abstracts all complexity:
const { markets, loadMarkets, toggleWatchlist } = usePredictionMarkets();- Types: Pure TypeScript interfaces
- Store: State management only
- API Client: Data fetching only
- Hook: Business logic and state integration
- API Routes: Backend proxy with fallbacks
- All data structures support responsive layouts
- Zustand store works in any React context
- No dependencies on window size or viewport
- Semantic data structures (categories, labels)
- Clear loading/error states
- Keyboard-friendly (no mouse-only interactions)
- Screen reader friendly text
Expected backend endpoints (in /api/predictions/):
GET /api/predictions/trending?limit={n}&category={cat}&source={src}GET /api/predictions/search?q={query}GET /api/predictions/market/{platform}/{marketId}
Backend should return snake_case, frontend converts to camelCase.
NEXT_PUBLIC_API_URL=http://127.0.0.1:8000The ThesisMarketLink interface is ready for:
- Linking markets to investment theses
- AI analysis of correlation
- Confidence scoring
- User notes
Example future usage:
// Link a market to a thesis
const link: ThesisMarketLink = {
id: 'link-1',
thesisId: 'thesis-abc',
platform: 'polymarket',
externalMarketId: 'MOCK-BTC-100K',
marketTitle: 'Bitcoin above $100K',
relationship: 'supports',
aiAnalysis: 'This market outcome would validate the Bitcoin bull thesis',
confidenceScore: 85,
priceAtLink: 0.65,
createdAt: new Date().toISOString(),
};Store structure supports WebSocket updates:
// In a WebSocket handler
usePredictionMarketsStore.getState().setMarkets(updatedMarkets);Easy to add analytics:
const { markets, filters } = usePredictionMarkets();
trackEvent('markets_viewed', { count: markets.length, filters });// Test store actions
import { usePredictionMarketsStore } from '@/lib/stores/prediction-markets-store';
test('adds market to watchlist', () => {
const store = usePredictionMarketsStore.getState();
store.addToWatchlist({
platform: 'kalshi',
externalMarketId: 'TEST-123',
marketTitle: 'Test Market',
});
expect(store.watchlist).toHaveLength(1);
});// Test hook with React Testing Library
import { renderHook, waitFor } from '@testing-library/react';
import { usePredictionMarkets } from '@/hooks/usePredictionMarkets';
test('loads markets on mount', async () => {
const { result } = renderHook(() => usePredictionMarkets());
result.current.loadMarkets();
await waitFor(() => {
expect(result.current.markets.length).toBeGreaterThan(0);
});
});// Test full user flow
test('user can add market to watchlist', async ({ page }) => {
await page.goto('/markets');
await page.click('[data-testid="market-card-watchlist-btn"]');
await page.goto('/watchlist');
expect(await page.locator('[data-testid="watchlist-item"]').count()).toBe(1);
});Target metrics:
- Initial load: < 3s (with mock data)
- Search response: < 500ms
- Filter change: < 100ms (UI only)
- Watchlist toggle: < 50ms (localStorage update)
- Semantic HTML structure in examples
- Clear loading states
- Descriptive error messages
- Keyboard navigation support (via standard buttons)
- ARIA labels in component examples
- Screen reader testing (to be done in UI implementation)
- Color contrast compliance (to be done in UI styling)
- Focus management (to be done in UI implementation)
-
Create UI Components (Phase 4)
- MarketCard component
- MarketList component
- MarketDetail component
- WatchlistPanel component
- MarketFilters component
-
Add Real-Time Updates
- WebSocket integration
- Optimistic updates
- Price change notifications
-
Thesis Integration
- Link markets to theses
- AI correlation analysis
- Confidence scoring
-
Charts and Visualizations
- Price history charts
- Probability curves
- Volume charts
-
Advanced Features
- Price alerts
- Portfolio tracking
- Market comparisons
- Export to CSV
To verify the implementation:
# 1. Check all files exist
ls -la web/src/lib/types/prediction-markets.ts
ls -la web/src/lib/stores/prediction-markets-store.ts
ls -la web/src/lib/api/prediction-markets.ts
ls -la web/src/hooks/usePredictionMarkets.ts
ls -la web/src/app/api/prediction-markets/route.ts
ls -la web/src/app/api/prediction-markets/search/route.ts
ls -la web/src/app/api/prediction-markets/[platform]/[marketId]/route.ts
# 2. TypeScript compilation
cd web
npx tsc --noEmit --skipLibCheck
# 3. Start dev server and test endpoints
npm run dev
# Then visit:
# http://localhost:3000/api/prediction-markets
# http://localhost:3000/api/prediction-markets/search?q=bitcoin
# http://localhost:3000/api/prediction-markets/polymarket/MOCK-BTC-100K
# 4. Test in a component
# Create a test page at web/src/app/test-markets/page.tsx
# Use the examples from PREDICTION_MARKETS_USAGE.mdIssue: TypeScript can't find module
- Fix: Make sure tsconfig.json has
"@/*": ["./src/*"]path mapping - Fix: Restart TypeScript server in VS Code
Issue: API route returns 404
- Fix: Check directory names use brackets:
[platform],[marketId] - Fix: Restart Next.js dev server
Issue: Watchlist not persisting
- Fix: Check browser localStorage quota
- Fix: Check if browser allows localStorage
Issue: Mock data not showing
- Fix: Check console for backend connection errors
- Fix: Verify NEXT_PUBLIC_API_URL is set correctly
- TypeScript strict mode enabled
- All exports have JSDoc comments
- Consistent naming (camelCase for variables, PascalCase for types)
- No
anytypes (except in controlled backend JSON parsing) - Error handling on all async operations
- Loading states for all data fetching
The prediction markets frontend infrastructure is now complete and ready for UI component development. All core functionality is implemented with:
- Full TypeScript type safety
- Robust error handling and mock fallbacks
- Persistent state management
- Clean, documented API
- Performance optimizations
- Accessibility considerations
The implementation follows all the patterns established in the existing codebase (thesis-store, market API routes, etc.) and is ready for integration with the backend when available.