Step-by-Step Guide: Build a Crypto Prediction Market App with SvelteKit and CoinGecko
Step-by-Step Guide: with SvelteKit and CoinGecko
The crypto world is changing fast. People used to just buy and hold coins for long-term gains. Now, many want to bet on short-term events and outcomes. This has made prediction markets very popular. Platforms like Polymarket and Kalshi are leading the way. Big exchanges are adding these features to attract more users and trading volume.
In this guide, you will learn
What is a Crypto Prediction Market?
A prediction market lets users trade on future events. Think: “Will Bitcoin hit $100,000 by December?” Users buy ‘Yes’ or ‘No’ shares. The price of shares shows the group’s best guess on the chance it happens. These markets often beat expert predictions because they use real money to show true beliefs.
Your app needs:
- Market creation with end dates and outcomes.
- Real-time betting and odds updates.
- Data from CoinGecko for prices and charts.
- Auto-resolution when events end.
This setup keeps users hooked with live data and easy bets.
Why Use SvelteKit and CoinGecko?
SvelteKit is fast and simple for full-stack apps. It handles server and client code well. TypeScript adds safety. TailwindCSS makes styling easy. Flowbite-Svelte gives ready components.
CoinGecko API is free for basics. It has prices, market caps, charts, and on-chain data for new tokens. No need for multiple APIs.
Step 1: Set Up Your Project
Create a new SvelteKit app:
npx sv create my-prediction-app
cd my-prediction-app
Choose TypeScript and TailwindCSS. Install Flowbite:
npm i -D flowbite-svelte flowbite
npm i -D flowbite-svelte-icons
Add your CoinGecko API key. Create .env:
COINGECKO_API_KEY=your-api-key-here
This keeps keys safe on the server.
Step 2: Define Data Types
Make clean types for data. Create src/lib/types/coinMarket.ts:
export interface CoinMarket {
id: string;
symbol: string;
name: string;
image: string;
current_price: number;
market_cap: number;
price_change_percentage_24h: number;
}
For predictions, marketPrediction.ts:
export interface MarketPrediction {
id: string;
coinId: string;
endDate: string;
targetPrice: number;
odds: OddsEntry[];
}
And oddsEntry.ts:
export interface OddsEntry {
outcome: 'yes' | 'no';
price: number;
volume: number;
}
These types make code error-free and easy to read.
Step 3: Build CoinGecko API Wrapper
Create src/lib/providers/CoinGecko.ts. This class fetches data cleanly:
import { COINGECKO_API_KEY } from '$env/static/private';
import type { CoinMarket } from '../types/coinMarket';
export class CoinGecko {
private baseUrl = 'https://api.coingecko.com/api/v3';
async getTopCoins(limit = 100): Promise<CoinMarket[]> {
const res = await fetch(`${this.baseUrl}/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=${limit}`);
return res.json();
}
async getCoinDetails(id: string) {
const res = await fetch(`${this.baseUrl}/coins/${id}`);
return res.json();
}
async getMarketChart(id: string, days: number) {
const res = await fetch(`${this.baseUrl}/coins/${id}/market_chart?vs_currency=usd&days=${days}`);
return res.json();
}
}
Use import { browser } from '$app/environment'; for client checks if needed.
Step 4: Create Market Card Component
Build src/lib/MarketCard.svelte. It shows coin info, odds, and bet buttons:
<script lang="ts">
import type { CoinMarket, MarketPrediction } from '$lib/types';
export let coin: CoinMarket;
export let prediction: MarketPrediction;
</script>
<div class="p-6 bg-white border rounded-lg shadow">
<img src={coin.image} alt={coin.name} class="w-12 h-12">
<h3>{coin.name} ({coin.symbol.toUpperCase()})</h3>
<p>Price: ${coin.current_price.toLocaleString()}</p>
<p>Will it hit ${prediction.targetPrice} by {new Date(prediction.endDate).toLocaleDateString()}?</p>
<div>
Yes: {prediction.odds.find(o => o.outcome === 'yes')?.price?.toFixed(2)}%
No: {prediction.odds.find(o => o.outcome === 'no')?.price?.toFixed(2)}%
</div>
<button class="bg-blue-500 text-white px-4 py-2 rounded">Bet Yes</button>
<button class="bg-red-500 text-white px-4 py-2 rounded ml-2">Bet No</button>
</div>
This card draws users in with clear info.
Step 5: Build the Dashboard Page
Edit src/routes/+page.svelte for a grid:
<script lang="ts">
import MarketCard from '$lib/MarketCard.svelte';
import type { CoinMarket, MarketPrediction } from '$lib/types';
export let data;
</script>
<div class="container mx-auto p-8">
<h1 class="text-3xl font-bold mb-8">Crypto Prediction Markets</h1>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{#each data.markets as pred (pred.id)}
<MarketCard coin={data.coins.find(c => c.id === pred.coinId)} prediction={pred} />
{/each}
</div>
</div>
Step 6: Add Core Services
Create src/lib/services/OddsService.ts:
import type { OddsEntry } from '../types/oddsEntry';
export class OddsService {
static recordClick(marketId: string, outcome: 'yes' | 'no') {
// Update yes/no counts and calc odds
// Simulate: odds = (clicks / total) * 100
}
static getOdds(marketId: string): OddsEntry[] {
// Return current odds
return [];
}
}
And PredictionMarketService.ts:
import type { MarketPrediction } from '../types/marketPrediction';
export class PredictionMarketService {
static async createMarket(coinId: string, endDate: string, targetPrice: number) {
// Add to data store
}
static async getMarkets(): Promise<MarketPrediction[]> {
// Load from JSON
return [];
}
static refreshMarkets() {
// Auto refresh after 30 days
}
}
Create empty src/lib/data/prediction_markets.json.
Step 7: Server-Side Logic
Add src/routes/+page.server.ts:
import { CoinGecko } from '$lib/providers/CoinGecko';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async () => {
const cg = new CoinGecko();
const coins = await cg.getTopCoins(50);
const markets = await PredictionMarketService.getMarkets();
return { coins, markets };
};
For actions like bets, add POST handlers.
Step 8: Handle Bets and Live Updates
In client, use fetch to POST bets:
async function bet(outcome: string) {
await fetch('/api/bet', {
method: 'POST',
body: JSON.stringify({ marketId, outcome })
});
// Reload data
}
Odds update live as users bet.
Step 9: Add On-Chain Memecoin Support
New memecoins are hot for predictions. Extend CoinGecko class:
async getTokenPrice(address: string, chain: string) {
const res = await fetch(`https://api.coingecko.com/api/v3/onchain/simple/token_price/${chain}/${address}`);
return res.json();
}
async getTokenInfo(address: string) {
const res = await fetch(`https://api.coingecko.com/api/v3/onchain/tokens/${address}/info`);
return res.json();
}
Check for honeypots. Show safe/unsafe icons in UI.
Create markets like “Will this memecoin 10x in 24h?”
Challenges and Solutions
Liquidity: Start with top coins. Use CoinGecko’s VWAP for fair prices.
Data Integrity: Aggregate from many exchanges to avoid pumps.
Security: Server-side API keys. Validate on-chain tokens.
Next Steps to Enhance Your App
- Add user wallets and real bets with crypto.
- WebSocket for live prices.
- Charts with market data.
- Admin panel for resolutions.
- Deploy to Vercel or Netlify.
Upgrade to CoinGecko paid for more limits and streams.
Run and Test
npm run dev. See your
You now have a solid base. Expand to full decentralized app. Prediction markets are the future of crypto info.
Keywords: