@sourceregistry/sveltekit-websockets
v1.0.9
Published
Typed WebSocket infrastructure for SvelteKit — per-request or continuous connections, full back-end lifecycle, and a reactive Svelte component.
Maintainers
Readme
@sourceregistry/sveltekit-websockets
Typed WebSocket infrastructure for SvelteKit — per-request or continuous connections, full back-end lifecycle, and a reactive Svelte component for the client.
⚠️ Node-only. This package requires
@sveltejs/adapter-node. WebSockets are not supported on serverless or edge adapters.
Features
- 🔌 Per-request WebSockets tied to SvelteKit form actions
- 🔁 Persistent WebSocket routes via controller-based routing
- 🧠 Lifecycle hooks:
connect,disconnect,error,destroy - 🧩 Reactive Svelte component with auto-connect and snippets for streamed messages
- ⚙️ Vite plugin that wires up
.upgrade()handling in dev and preview - 🔐 Ephemeral, single-use connection keys with TTL and automatic cleanup
Installation
npm install @sourceregistry/sveltekit-websocketsQuick start
1. Register the Vite plugin (required)
WebSocket upgrades need a hook into the dev/preview HTTP server. Add the plugin in vite.config.ts:
import {defineConfig} from 'vite';
import {sveltekit} from '@sveltejs/kit/vite';
import {websockets} from '@sourceregistry/sveltekit-websockets/vite';
export default defineConfig({
plugins: [
sveltekit(),
websockets(), // ADD THIS
],
server: {
ws: {
port: 5174, // REQUIRED — see note below
},
},
});Without the plugin, .upgrade() requests fail in dev and preview (production builds on adapter-node are
patched automatically at build time).
⚠️ Also set
server.ws.portto a different port, as shown above. The plugin intercepts every'upgrade'request on the dev server's HTTP port and closes any that don't match a registered route. Vite's own HMR client connects over a WebSocket on that same port by default, so without a dedicatedws.portit gets killed too — the browser loses its HMR connection, keeps retrying, and the page reloads in a loop.
2. Per-request WebSockets (use())
Bind a single-use WebSocket to a SvelteKit form action. The client gets back a one-time URL that expires automatically.
// src/routes/chat/+page.server.ts
import {websockets} from '@sourceregistry/sveltekit-websockets/server';
export const actions = {
ws: (event) => ({
url: websockets.use(event, (socket) => {
socket.send('Connected!');
socket.addEventListener('message', (msg) => {
console.log('Client says:', msg.data);
});
}),
}),
};3. Persistent WebSockets (continuous())
Register a long-lived endpoint independent of any single request, typically from src/hooks.server.ts:
import {websockets} from '@sourceregistry/sveltekit-websockets/server';
const chat = websockets.continuous('/chat', {useConnectionKeys: false});
chat.on('connect', (socket) => {
socket.send('Welcome to /chat');
socket.addEventListener('message', (msg) => socket.send(`Echo: ${msg.data}`));
});Now reachable at ws://localhost:5173/chat.
4. Svelte client component
<script lang="ts">
import WebSocket from '@sourceregistry/sveltekit-websockets';
</script>
<WebSocket action="?/ws">
{#snippet message(data)}
<p>{new Date().toLocaleTimeString()}: {data}</p>
{/snippet}
</WebSocket>| Prop | Type | Description |
|--------------|-----------|-------------------------------------------------|
| action | string | Form action that returns { url } |
| url | string | Direct WebSocket URL, as an alternative to action |
| data | T[] | Bindable, reactive array of received messages |
| auto_open | boolean | Auto-connect on mount (default: true) |
| controller | snippet | Render callback for manual open() / close() |
| message | snippet | Render callback per received message |
Full API reference
For every configuration option, server event, low-level socket API (broadcast, send, raw(),
graceful shutdown, rate limiting, timeouts, etc.), and the client-side Action/ActionSocket helpers, see
API.md.
Contributing
See CONTRIBUTING.md.
License
Apache-2.0
