Deploying Real-Time Dashboards on Serverless Frontend Hosts
Learn how to build and deploy real-time dashboards using serverless frontend hosting solutions like Vercel, Netlify, and Cloudflare Workers.
In today’s data-driven world, real-time dashboards have become essential tools for monitoring, analytics, and decision-making. Serverless frontend hosting platforms provide an excellent foundation for building and deploying these dashboards with minimal operational overhead.
Why Serverless for Real-Time Dashboards?
Serverless architecture offers several advantages for real-time dashboard applications:
- Scalability: Automatic scaling to handle varying loads without manual intervention
- Cost-Effectiveness: Pay only for the resources you use, with no idle server costs
- Reduced Operational Overhead: No server management or maintenance required
- Global Distribution: Edge networks ensure low-latency access worldwide
- Rapid Deployment: Quick updates and deployments with minimal downtime
Setting Up a Basic Real-Time Dashboard
Let’s create a simple real-time dashboard using Next.js and Socket.IO, which we’ll deploy to Vercel.
1. Initialize a New Next.js Project
npx create-next-app@latest realtime-dashboard --typescript
cd realtime-dashboard
npm install socket.io-client socket.io chart.js react-chartjs-2
2. Create a Socket.IO Server
Create a new API route for handling WebSocket connections:
import { Server } from 'socket.io';
import type { NextApiRequest, NextApiResponse } from 'next';
let io: Server | null = null;
export default function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (!io) {
const httpServer = res.socket.server;
// @ts-ignore - Workaround for Next.js API routes
io = new Server(httpServer, {
path: '/api/socketio',
addTrailingSlash: false,
});
io.on('connection', (socket) => {
console.log('Client connected:', socket.id);
// Send initial data
socket.emit('update', {
timestamp: new Date().toISOString(),
value: Math.random() * 100
});
// Update data every second
const interval = setInterval(() => {
socket.emit('update', {
timestamp: new Date().toISOString(),
value: Math.random() * 100
});
}, 1000);
socket.on('disconnect', () => {
console.log('Client disconnected:', socket.id);
clearInterval(interval);
});
});
// @ts-ignore - Workaround for Next.js API routes
httpServer.io = io;
}
res.status(200).json({ status: 'WebSocket server is running' });
}
3. Create the Dashboard
// Initialize dashboard with vanilla JavaScript
function initializeDashboard() {
const data = [];
let socket = null;
let isConnected = false;
let chart = null;
// Initialize WebSocket connection
function connectWebSocket() {
const socketInstance = io({
path: '/api/socketio',
});
socketInstance.on('connect', () => {
console.log('Connected to WebSocket server');
isConnected = true;
updateConnectionStatus();
});
socketInstance.on('update', (newData) => {
data.push(newData);
// Keep only the last 20 data points
while (data.length > 20) {
data.shift();
}
updateChart();
updateDataPoints();
});
socketInstance.on('disconnect', () => {
console.log('Disconnected from WebSocket server');
isConnected = false;
updateConnectionStatus();
});
socket = socketInstance;
return socketInstance;
}
// Update connection status in the UI
function updateConnectionStatus() {
const statusElement = document.getElementById('connection-status');
if (statusElement) {
statusElement.textContent = `Status: ${isConnected ? 'Connected' : 'Disconnected'}`;
statusElement.style.color = isConnected ? 'green' : 'red';
}
}
// Initialize chart
function initChart() {
const ctx = document.getElementById('chart');
if (!ctx) return null;
return new Chart(ctx.getContext('2d'), {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'Real-time Data',
data: [],
borderColor: 'rgb(75, 192, 192)',
tension: 0.1,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true
}
}
}
});
}
// Update chart with new data
function updateChart() {
if (!chart) return;
chart.data.labels = data.map(d => new Date(d.timestamp).toLocaleTimeString());
chart.data.datasets[0].data = data.map(d => d.value);
chart.update();
}
// Update data points list
function updateDataPoints() {
const container = document.getElementById('data-points');
if (!container) return;
// Clear existing points
container.innerHTML = '';
// Add points in reverse order (newest first)
[...data].reverse().forEach((point, index) => {
const li = document.createElement('li');
li.textContent = `${new Date(point.timestamp).toLocaleTimeString()}: ${point.value.toFixed(2)}`;
container.appendChild(li);
});
}
// Initialize the dashboard
function init() {
// Initialize chart
chart = initChart();
// Connect to WebSocket
connectWebSocket();
// Return cleanup function
return () => {
if (socket) {
socket.disconnect();
}
};
}
// Start the dashboard when the DOM is loaded
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
// Create dashboard HTML
const dashboardHTML = `
Real-time Dashboard
Status: Connecting...
Latest Data Points
`;
// Return the dashboard HTML
return dashboardHTML;
}
4. Include the Dashboard in Your HTML
Add this to your HTML file to include the dashboard:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Real-time Dashboard</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div id="app"><!-- Dashboard will be rendered here --></div>
<script src="js/dashboard.js"></script>
</body>
</html>
Deploying to Vercel
Deploying our real-time dashboard to Vercel is straightforward:
# Install Vercel CLI if you haven't already
npm install -g vercel
# Login to your Vercel account
vercel login
# Deploy your application
vercel
# For production deployment
vercel --prod
Alternative: Using Server-Sent Events (SSE)
For simpler use cases, you can use Server-Sent Events instead of WebSockets. Here’s a basic example:
import { NextApiRequest, NextApiResponse } from 'next';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// Set headers for SSE
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.setHeader('Content-Encoding', 'none');
// Send initial data
res.write(`data: ${JSON.stringify({
timestamp: new Date().toISOString(),
value: Math.random() * 100
})}nn`);
// Send updates every second
const interval = setInterval(() => {
res.write(`data: ${JSON.stringify({
timestamp: new Date().toISOString(),
value: Math.random() * 100
})}nn`);
}, 1000);
// Clean up on client disconnect
req.on('close', () => {
clearInterval(interval);
res.end();
});
}
Conclusion
Building and deploying real-time dashboards with serverless technologies provides a scalable, cost-effective solution for modern web applications. By leveraging platforms like Vercel, Netlify, or Cloudflare Workers, you can focus on building great user experiences without worrying about infrastructure management.
Key takeaways:
- Serverless architectures simplify deployment and scaling of real-time applications
- WebSockets provide full-duplex communication for real-time updates
- Server-Sent Events offer a simpler alternative for one-way communication
- Platforms like Vercel make deployment and hosting effortless