Skip to main content
Web DevelopmentTutorials

Building a Real-Time Dashboard with Nuxt and WebSockets

Create a live-updating analytics dashboard using Nuxt 3 server-sent events and WebSocket connections for real-time data.

Mbeah Essilfie

Mbeah Essilfie

July 3, 2026 at 06:03 AM

10 min read 569 views
Building a Real-Time Dashboard with Nuxt and WebSockets

Real-Time Without Complexity

Not every real-time feature needs WebSockets. Let's explore the spectrum and pick the right tool.

Server-Sent Events (SSE)

Perfect for one-way data: server pushes to client.

// server/api/events.get.ts
export default defineEventHandler(async (event) => {
  setHeader(event, 'Content-Type', 'text/event-stream')
  setHeader(event, 'Cache-Control', 'no-cache')
  setHeader(event, 'Connection', 'keep-alive')

  const encoder = new TextEncoder()
  const stream = new ReadableStream({
    start(controller) {
      const interval = setInterval(async () => {
        const metrics = await getLatestMetrics()
        const data = `data: ${JSON.stringify(metrics)}\n\n`
        controller.enqueue(encoder.encode(data))
      }, 1000)

      // Cleanup on disconnect
      event.node.req.on('close', () => {
        clearInterval(interval)
        controller.close()
      })
    },
  })

  return sendStream(event, stream)
})

Client-side:

<script setup lang="ts">
const metrics = ref<Metrics | null>(null)

onMounted(() => {
  const source = new EventSource('/api/events')
  source.onmessage = (event) => {
    metrics.value = JSON.parse(event.data)
  }
  onUnmounted(() => source.close())
})
</script>

When to Use WebSockets

Use WebSockets when you need bidirectional communication:

  • Chat applications
  • Collaborative editing
  • Gaming
SSE is simpler, auto-reconnects, and works through most proxies. Choose WebSockets only when you need client-to-server streaming.

Dashboard Layout

<template>
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 p-6">
    <MetricCard
      v-for="metric in metrics"
      :key="metric.id"
      :label="metric.label"
      :value="metric.value"
      :trend="metric.trend"
    />
  </div>

  <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 p-6">
    <LiveChart :data="chartData" />
    <ActivityFeed :events="recentEvents" />
  </div>
</template>

Performance Tips

  1. Throttle updates — Don't push more than the UI can render (16ms frames)
  2. Use shallowRef — Avoid deep reactivity for frequently updated data
  3. Virtual scrolling — For long lists of real-time events
  4. Reconnection logic — Always handle disconnects gracefully

Real-time features delight users. With SSE and Nuxt, you can add them in under an hour.

TypeScriptNuxtNode.js
Mbeah Essilfie

Written by Mbeah Essilfie

Fullstack Software Developer

Read next

The Complete Guide to Vue 3 Composables
12 min read

The Complete Guide to Vue 3 Composables

Understand the power of Vue 3's Composition API through practical, real-world composable patterns that you can use today.

Mbeah EssilfieMbeah Essilfie
983