Track how many users are connected to your application and which versions they're running. This is useful for admin dashboards, deployment monitoring, and understanding rollout progress.
sse or ws update strategies. It does not support polling or external adapters (Pusher/Ably).Enable connection tracking in your Nuxt config:
export default defineNuxtConfig({
skewProtection: {
connectionTracking: true
}
})
This feature is only for certain compatible environments currently:
polling strategy or external adapters (Pusher/Ably).The useActiveConnections() composable provides reactive access to connection statistics:
<script setup lang="ts">
import { useActiveConnections } from '#imports'
const { total, versions } = useActiveConnections()
</script>
<template>
<div>
<p>Active users: {{ total }}</p>
<ul>
<li v-for="(count, version) in versions" :key="version">
{{ version.slice(0, 8) }}: {{ count }} users
</li>
</ul>
</div>
</template>
| Property | Type | Description |
|---|---|---|
total | ComputedRef<number> | Total active connections |
versions | ComputedRef<Record<string, number>> | Map of buildId → connection count |
<script setup>
const { total, versions } = useActiveConnections()
const currentBuildId = useRuntimeConfig().app.buildId
const stats = computed(() => {
const current = versions.value[currentBuildId] || 0
const outdated = total.value - current
return {
total: total.value,
current,
outdated,
percentUpToDate: total.value ? Math.round((current / total.value) * 100) : 100
}
})
</script>
<template>
<div class="grid grid-cols-4 gap-4">
<div class="stat">
<span class="label">Total Users</span>
<span class="value">{{ stats.total }}</span>
</div>
<div class="stat">
<span class="label">On Latest</span>
<span class="value text-green">{{ stats.current }}</span>
</div>
<div class="stat">
<span class="label">On Old Version</span>
<span class="value text-orange">{{ stats.outdated }}</span>
</div>
<div class="stat">
<span class="label">Rollout Progress</span>
<span class="value">{{ stats.percentUpToDate }}%</span>
</div>
</div>
</template>
For advanced use cases, you can use hooks directly instead of the composable.
skew:messageListen to all messages from the SSE/WebSocket connection:
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hooks.hook('skew:message', (message) => {
if (message.type === 'stats') {
// Custom handling
console.log('Connections:', message.total)
console.log('Versions:', message.versions)
}
})
})
Build custom tracking logic with Nitro hooks:
import { defineNitroPlugin } from 'nitropack/runtime'
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('skew:connection:open', ({ id, version, send }) => {
console.log(`Client ${id} connected on ${version}`)
// Send custom welcome message
send({ type: 'welcome', serverTime: Date.now() })
})
nitroApp.hooks.hook('skew:connection:close', ({ id }) => {
console.log(`Client ${id} disconnected`)
})
})
See Nuxt Hooks and Nitro Hooks for full documentation.