Integrating Socket.IO with Nuxt and Nitro
Introduction
Socket.IO enables real-time, bidirectional communication between web clients and servers. In this guide, we'll learn how to integrate Socket.IO with Nuxt 3 and Nitro to create real-time applications.
What is Socket.IO?
Socket.IO is a JavaScript library that provides real-time communication between clients and servers. It offers:
- Automatic reconnection
- Fallback to HTTP long-polling
- Room-based messaging
- Cross-browser compatibility
Project Setup
First, create a new Nuxt 3 project and install Socket.IO:
# Create a new Nuxt project
npx nuxi@latest init socket-io-demo
cd socket-io-demo
# Install Socket.IO dependencies
npm install socket.io socket.io-client
Basic Socket.IO Server Setup
Create a server plugin to initialize Socket.IO:
import { Server } from 'socket.io'
export default defineNitroPlugin((nitroApp) => {
const io = new Server(nitroApp.h3App.server, {
cors: {
origin: 'http://localhost:3000',
methods: ['GET', 'POST']
}
})
// Store the io instance globally
nitroApp.h3App.io = io
// Handle socket connections
io.on('connection', (socket) => {
console.log('Client connected:', socket.id)
// Handle disconnection
socket.on('disconnect', () => {
console.log('Client disconnected:', socket.id)
})
// Handle custom events
socket.on('message', (data) => {
console.log('Received message:', data)
// Broadcast the message to all connected clients
io.emit('message', {
id: socket.id,
message: data.message,
timestamp: new Date().toISOString()
})
})
})
console.log('Socket.IO server initialized')
})
TypeScript Support
Add TypeScript definitions:
import type { Server as SocketIOServer } from 'socket.io'
declare module 'nitropack' {
interface NitroApp {
h3App: {
server: any
io: SocketIOServer
}
}
}
export interface ChatMessage {
id: string
message: string
timestamp: string
}
Client-Side Socket.IO Integration
Create a composable for client-side Socket.IO management:
import { io } from 'socket.io-client'
export const useSocket = () => {
const socket = ref(null)
const isConnected = ref(false)
const messages = ref<ChatMessage[]>([])
const connect = () => {
if (socket.value?.connected) return
socket.value = io('http://localhost:3000')
socket.value.on('connect', () => {
console.log('Connected to Socket.IO server')
isConnected.value = true
})
socket.value.on('disconnect', () => {
console.log('Disconnected from Socket.IO server')
isConnected.value = false
})
socket.value.on('message', (message: ChatMessage) => {
messages.value.push(message)
})
}
const disconnect = () => {
if (socket.value) {
socket.value.disconnect()
socket.value = null
isConnected.value = false
}
}
const sendMessage = (message: string) => {
if (!socket.value?.connected) return
socket.value.emit('message', { message })
}
// Auto-connect on client-side
if (process.client) {
onMounted(() => {
connect()
})
onUnmounted(() => {
disconnect()
})
}
return {
socket: readonly(socket),
isConnected: readonly(isConnected),
messages: readonly(messages),
connect,
disconnect,
sendMessage
}
}
Building a Simple Chat Application
Create a basic chat page:
<script setup lang="ts">
const { isConnected, messages, sendMessage } = useSocket()
const newMessage = ref('')
const handleSendMessage = () => {
if (!newMessage.value.trim()) return
sendMessage(newMessage.value)
newMessage.value = ''
}
</script>
<template>
<UContainer>
<UPageHeader
title="Simple Chat"
description="A basic Socket.IO chat application"
/>
<UPageBody>
<div class="max-w-2xl mx-auto space-y-4">
<!-- Connection Status -->
<UCard>
<div class="flex items-center gap-2">
<div
class="w-3 h-3 rounded-full"
:class="isConnected ? 'bg-green-500' : 'bg-red-500'"
/>
<span class="text-sm">
{{ isConnected ? 'Connected' : 'Disconnected' }}
</span>
</div>
</UCard>
<!-- Chat Messages -->
<UCard>
<template #header>
<h3 class="text-lg font-semibold">Messages</h3>
</template>
<div class="h-96 overflow-y-auto space-y-2 mb-4">
<div
v-for="message in messages"
:key="message.timestamp"
class="p-3 bg-gray-50 rounded-lg"
>
<div class="flex items-center gap-2 mb-1">
<span class="text-sm font-medium text-blue-600">
{{ message.id }}
</span>
<span class="text-xs text-gray-500">
{{ new Date(message.timestamp).toLocaleTimeString() }}
</span>
</div>
<p class="text-sm">{{ message.message }}</p>
</div>
</div>
<div class="flex gap-2">
<UInput
v-model="newMessage"
placeholder="Type your message..."
@keyup.enter="handleSendMessage"
class="flex-1"
/>
<UButton @click="handleSendMessage" :disabled="!isConnected">
Send
</UButton>
</div>
</UCard>
</div>
</UPageBody>
</UContainer>
</template>
Basic Error Handling
Add simple error handling to your Socket.IO setup:
// ... existing code ...
const connect = () => {
if (socket.value?.connected) return
socket.value = io('http://localhost:3000', {
reconnection: true,
reconnectionAttempts: 3,
timeout: 10000
})
socket.value.on('connect', () => {
console.log('Connected to Socket.IO server')
isConnected.value = true
})
socket.value.on('connect_error', (error) => {
console.error('Connection error:', error)
isConnected.value = false
})
socket.value.on('disconnect', () => {
console.log('Disconnected from Socket.IO server')
isConnected.value = false
})
socket.value.on('message', (message: ChatMessage) => {
messages.value.push(message)
})
}
Production Configuration
For production, update your server configuration:
export default defineNitroPlugin((nitroApp) => {
const io = new Server(nitroApp.h3App.server, {
cors: {
origin: process.env.NODE_ENV === 'production'
? 'https://yourdomain.com'
: 'http://localhost:3000',
methods: ['GET', 'POST']
}
})
// ... rest of the socket logic
})
Conclusion
This basic setup provides a foundation for real-time communication in your Nuxt 3 application. You can extend this with:
- Room-based messaging
- User authentication
- Typing indicators
- Message persistence
- Advanced error handling
The combination of Nuxt 3, Nitro, and Socket.IO creates a powerful stack for building real-time applications.
Resources
Happy coding! ๐
Coolify - Self Hosting on Steroids
Coolify is an open-source, self-hosted alternative to Vercel, Heroku, and Netlify that allows developers to host their applications on their own infrastructure.
User Auth and Session Management in Nuxt 3 with @sidebase/nuxt-auth and GitHub
A article about Nuxt 3 with @sidebase/nuxt-auth to authenticate and manage sessions with GitHub.