.html file and open it in a browser.
Single market
market.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Live prediction</title>
<link rel="preconnect" href="https://app.kash.bot" />
<style>
body { font-family: system-ui, sans-serif; max-width: 640px; margin: 2rem auto; padding: 0 1rem; }
iframe { width: 100%; height: 520px; border: 0; border-radius: 12px; }
</style>
</head>
<body>
<h1>What do you think?</h1>
<iframe
src="https://app.kash.bot/markets/93f1445c-912c-47b4-8065-d1ff5a6b8dfc/iframe"
loading="lazy"
allow="clipboard-write"
title="Kash prediction market"
></iframe>
</body>
</html>
Thread
thread.html
<iframe
src="https://app.kash.bot/threads/00000001-0000-4000-a000-000000000003/iframe"
width="100%"
height="900"
frameborder="0"
loading="lazy"
allow="clipboard-write"
title="Kash prediction markets"
></iframe>
Custom cards without an iframe
This page fetches live markets from the public API, renders its own cards, and gives each outcome a “Predict on X” button that uses the deep-link endpoint.custom-cards.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Live markets</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 1100px; margin: 2rem auto; padding: 0 1rem; background: #111; color: #eee; }
#grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
.card { background: #1c1c1c; border-radius: 12px; padding: 16px; }
.card h3 { font-size: 1rem; margin: 0 0 12px; }
.card a { color: inherit; text-decoration: none; }
.card button { margin: 4px 4px 0 0; padding: 6px 10px; border-radius: 8px; border: 1px solid #444; background: #222; color: #eee; cursor: pointer; }
.meta { color: #999; font-size: 0.8rem; margin-top: 8px; }
</style>
</head>
<body>
<h1>Live prediction markets</h1>
<div id="grid">Loading…</div>
<script>
const API = 'https://app.kash.bot/api';
const AMOUNT = 10; // whole USDC
function usd(atomic) {
return '$' + Math.round(Number(atomic) / 1e6).toLocaleString();
}
async function predict(marketId, outcomeIndex) {
const tab = window.open('', '_blank'); // open now so popup blockers allow it
const res = await fetch(`${API}/markets/${marketId}/twitter-link?outcomeIndex=${outcomeIndex}&amount=${AMOUNT}`);
const body = await res.json();
if (!res.ok) { tab && tab.close(); alert(body.message); return; }
if (tab) tab.location.href = body.twitterUrl;
}
function render(markets) {
const grid = document.getElementById('grid');
grid.innerHTML = '';
for (const m of markets) {
const card = document.createElement('div');
card.className = 'card';
const link = document.createElement('a');
link.href = `https://app.kash.bot/markets/${m.id}`;
link.target = '_blank';
link.rel = 'noopener noreferrer';
const title = document.createElement('h3');
title.textContent = m.title;
link.appendChild(title);
card.appendChild(link);
for (const o of m.outcomes) {
const btn = document.createElement('button');
btn.textContent = `${o.label} · ${Math.round(o.impliedChance * 100)}%`;
btn.disabled = !m.tradable;
btn.onclick = () => predict(m.id, o.outcomeIndex);
card.appendChild(btn);
}
const meta = document.createElement('div');
meta.className = 'meta';
meta.textContent = `${usd(m.totalVolume)} volume · ${m.participantCount} traders`;
card.appendChild(meta);
grid.appendChild(card);
}
}
fetch(`${API}/markets?status=active&tradableOnly=true&sortBy=total_volume&limit=12`)
.then((r) => r.json())
.then(({ markets }) => render(markets))
.catch(() => { document.getElementById('grid').textContent = 'Could not load markets.'; });
</script>
</body>
</html>
textContent rather than innerHTML, so market titles are never interpreted as HTML.
Next steps
Market and thread iframes
Attributes, sandboxing and events
JavaScript examples
A reusable API client