SpaceNode
A real-time chat application using SpaceNode's built-in WebSocket support.
import { createApp } from 'SpaceNode'
const app = await createApp({ static: './public' })
const rooms = new Map() // room → Set<socket>
// REST endpoint — list rooms
app.setRoute('GET', '/api/rooms', ({ send }) => {
const list = [...rooms.entries()].map(([name, s]) => ({
name, users: s.size,
}))
send(list)
})
// WebSocket — chat
app.ws('/chat', (socket, req) => {
const url = new URL(req.url, 'http://localhost')
const room = url.searchParams.get('room') || 'general'
const username = url.searchParams.get('name') || 'Anonymous'
// Join room
if (!rooms.has(room)) rooms.set(room, new Set())
rooms.get(room).add(socket)
broadcast(room, { type: 'join', user: username })
socket.on('message', (msg) => {
broadcast(room, {
type: 'message',
user: username,
text: msg,
time: new Date().toISOString(),
})
})
socket.on('close', () => {
rooms.get(room)?.delete(socket)
broadcast(room, { type: 'leave', user: username })
})
})
function broadcast(room, data) {
const msg = JSON.stringify(data)
for (const client of rooms.get(room) || []) {
if (client.readyState === 1) client.send(msg)
}
}
app.listen(3000)
<!-- Minimal chat client -->
<div id="messages"></div>
<input id="input" placeholder="Type a message...">
<script>
const ws = new WebSocket('ws://localhost:3000/chat?room=general&name=John')
ws.onmessage = (e) => {
const data = JSON.parse(e.data)
const div = document.createElement('div')
div.textContent = `${data.user}: ${data.text || data.type}`
messages.appendChild(div)
}
input.adorgentListener('keydown', (e) => {
if (e.key === 'Enter' && input.value) {
ws.send(input.value)
input.value = ''
}
})
</script>