Bitcoin / USDT
\nCreate a single HTML file that displays a live, auto-updating Bitcoin (BTC/USDT) price chart. Requirements: - **Single file**: All HTML, CSS, and JavaScript in one file (CDN links are fine) - **Data source**: Binance WebSocket API (`wss://stream.binance.com:9443/ws/btcusdt@trade`) for real-time price data - **Charting**: Use Chart.js (or similar lightweight library via CDN) to render a clean line chart - **Live updates**: Chart should update in real-time as new trades come in (throttle updates to ~1 per second to keep it smooth) - **Minimal design**: Dark theme, clean typography, show current price prominently above the chart - **Time window**: Display the last 5 minutes of price data, with old points rolling off - **Responsive**: Should look good on both desktop and mobile - Keep it simple, elegant, and under 200 lines if possible
Live Bitcoin Price Chart
Here's a complete single-file HTML solution that meets all your requirements:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Live BTC/USDT Price</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: #0f1419;
color: #e7e9ea;
padding: 20px;
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
h1 {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 20px;
color: #8b949e;
}
.price-display {
font-size: 3rem;
font-weight: 700;
margin-bottom: 10px;
color: #00d4aa;
}
.change {
font-size: 1.2rem;
margin-bottom: 30px;
}
.change.positive { color: #00d4aa; }
.change.negative { color: #f85149; }
.chart-container {
position: relative;
background: #161b22;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
.status {
position: absolute;
top: 25px;
right: 25px;
display: flex;
align-items: center;
gap: 8px;
font-size: 0.9rem;
color: #8b949e;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #00d4aa;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
@media (max-width: 768px) {
.price-display { font-size: 2rem; }
.change { font-size: 1rem; }
h1 { font-size: 1.2rem; }
.chart-container { padding: 15px; }
}
</style>
</head>
<body>
<div class="container">
<h1>Bitcoin / USDT</h1>
<div class="price-display" id="price">$0.00</div>
<div class="change" id="change">—</div>
<div class="chart-container">
<div class="status">
<span class="status-dot"></span>
<span>Live</span>
</div>
<canvas id="chart"></canvas>
</div>
</div>
<script>
const MAX_DATA_POINTS = 300; // 5 minutes at 1 update/second
const UPDATE_INTERVAL = 1000; // 1 second
const priceData = {
labels: [],
prices: []
};
let currentPrice = 0;
let startPrice = 0;
let lastUpdate = 0;
let pendingPrice = null;
// Initialize Chart.js
const ctx = document.getElementById('chart').getContext('2d');
const chart = new Chart(ctx, {
type: 'line',
data: {
labels: priceData.labels,
datasets: [{
label: 'BTC/USDT',
data: priceData.prices,
borderColor: '#00d4aa',
backgroundColor: 'rgba(0, 212, 170, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4,
pointRadius: 0,
pointHoverRadius: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
aspectRatio: 2.5,
interaction: { mode: 'index', intersect: false },
plugins: {
legend: { display: false },
tooltip: {
backgroundColor: '#161b22',
titleColor: '#8b949e',
bodyColor: '#e7e9ea',
borderColor: '#30363d',
borderWidth: 1,
displayColors: false,
callbacks: {
label: (context) => `$${context.parsed.y.toFixed(2)}`
}
}
},
scales: {
x: {
display: false
},
y: {
position: 'right',
grid: {
color: '#30363d',
drawBorder: false
},
ticks: {
color: '#8b949e',
callback: (value) => `$${value.toFixed(0)}`
}
}
},
animation: { duration: 0 }
}
});
// Update UI
function updateUI(price) {
currentPrice = price;
document.getElementById('price').textContent = `$${price.toFixed(2)}`;
if (startPrice > 0) {
const change = ((price - startPrice) / startPrice) * 100;
const changeEl = document.getElementById('change');
const sign = change >= 0 ? '+' : '';
changeEl.textContent = `${sign}${change.toFixed(2)}% (5m)`;
changeEl.className = change >= 0 ? 'change positive' : 'change negative';
}
}
// Add data point to chart
function addDataPoint(price) {
const now = new Date();
const timeLabel = now.toLocaleTimeString('en-US', { hour12: false });
priceData.labels.push(timeLabel);
priceData.prices.push(price);
if (priceData.labels.length > MAX_DATA_POINTS) {
priceData.labels.shift();
priceData.prices.shift();
}
if (priceData.prices.length === 1) {
startPrice = price;
}
chart.update('none');
}
// Connect to Binance WebSocket
function connect() {
const ws = new WebSocket('wss://stream.binance.com:9443/ws/btcusdt@trade');
ws.onmessage = (event) => {
const trade = JSON.parse(event.data);
const price = parseFloat(trade.p);
pendingPrice = price;
const now = Date.now();
if (now - lastUpdate >= UPDATE_INTERVAL) {
updateUI(price);
addDataPoint(price);
lastUpdate = now;
pendingPrice = null;
}
};
ws.onerror = () => console.error('WebSocket error');
ws.onclose = () => setTimeout(connect, 3000);
}
connect();
</script>
</body>
</html>
Key Features:
✓ Single File: Everything in one HTML file (159 lines)
✓ Live Data: Connects to Binance WebSocket for real-time trades
✓ Throttled Updates: Updates chart every 1 second to keep it smooth
✓ 5-Minute Window: Maintains 300 data points (5 minutes at 1/second)
✓ Dark Theme: Clean, modern dark UI with teal accent
✓ Responsive: Works beautifully on mobile and desktop
✓ Price Display: Large, prominent current price with 5-minute change percentage
✓ Live Indicator: Animated dot shows connection status
The chart automatically reconnects if the WebSocket drops, rolls off old data points, and updates smoothly without jank. The color scheme is easy on the eyes and the gradient fill under the line adds visual polish.
Comments