TypeScript client for the Atmosphere Framework. Supports WebSocket, SSE, and Long-Polling transports with first-class React, Vue, and Svelte hooks.
npm install atmosphere.jsimport { atmosphere } from 'atmosphere.js';
const subscription = await atmosphere.subscribe({
url: 'http://localhost:8080/chat',
transport: 'websocket',
}, {
message: (response) => console.log('Received:', response.responseBody),
open: (response) => console.log('Connected via:', response.transport),
close: (response) => console.log('Connection closed'),
error: (error) => console.error('Error:', error),
});
subscription.push({ user: 'John', message: 'Hello World' });All hooks require an <AtmosphereProvider> ancestor.
import { AtmosphereProvider } from 'atmosphere.js/react';
function App() {
return (
<AtmosphereProvider>
<Chat />
</AtmosphereProvider>
);
}Subscribe to an endpoint:
import { useAtmosphere } from 'atmosphere.js/react';
function Chat() {
const { data, state, push } = useAtmosphere<Message>({
request: { url: '/chat', transport: 'websocket' },
});
return state === 'connected'
? <button onClick={() => push({ text: 'Hello' })}>Send</button>
: <p>Connecting...</p>;
}Join a room with presence:
import { useRoom } from 'atmosphere.js/react';
function ChatRoom() {
const { joined, members, messages, broadcast } = useRoom<ChatMessage>({
request: { url: '/atmosphere/room', transport: 'websocket' },
room: 'lobby',
member: { id: 'user-1' },
});
return (
<div>
<p>{members.length} online</p>
{messages.map((m, i) => <div key={i}>{m.member.id}: {m.data.text}</div>)}
<button onClick={() => broadcast({ text: 'Hi' })}>Send</button>
</div>
);
}Lightweight presence tracking:
import { usePresence } from 'atmosphere.js/react';
function OnlineUsers() {
const { members, count, isOnline } = usePresence({
request: { url: '/atmosphere/room', transport: 'websocket' },
room: 'lobby',
member: { id: currentUser.id },
});
return <p>{count} users online. Alice is {isOnline('alice') ? 'here' : 'away'}.</p>;
}AI/LLM text streaming:
import { useStreaming } from 'atmosphere.js/react';
function AiChat() {
const { fullText, isStreaming, stats, routing, send } = useStreaming({
request: { url: '/ai/chat', transport: 'websocket' },
});
return (
<div>
<button onClick={() => send('Explain WebSockets')} disabled={isStreaming}>Ask</button>
<p>{fullText}</p>
{stats && <small>{stats.totalStreamingTexts} streaming texts</small>}
</div>
);
}Vue composables do not require a provider -- they create or accept an Atmosphere instance directly.
<script setup lang="ts">
import { useAtmosphere } from 'atmosphere.js/vue';
const { data, state, push } = useAtmosphere<ChatMessage>({
url: '/chat',
transport: 'websocket',
});
</script>
<template>
<p>Status: {{ state }}</p>
<button @click="push({ text: 'Hello!' })">Send</button>
</template><script setup lang="ts">
import { useRoom } from 'atmosphere.js/vue';
const { members, messages, broadcast } = useRoom<ChatMessage>(
{ url: '/atmosphere/room', transport: 'websocket' },
'lobby',
{ id: 'user-1' },
);
</script><script setup lang="ts">
import { usePresence } from 'atmosphere.js/vue';
const { members, count, isOnline } = usePresence(
{ url: '/atmosphere/room', transport: 'websocket' },
'lobby',
{ id: currentUser.id },
);
</script><script setup lang="ts">
import { useStreaming } from 'atmosphere.js/vue';
const { fullText, isStreaming, send, reset } = useStreaming({
url: '/ai/chat',
transport: 'websocket',
});
</script>
<template>
<button @click="send('What is Atmosphere?')">Ask</button>
<p>{{ fullText }}</p>
<span v-if="isStreaming">Generating...</span>
</template>Svelte integrations use the store pattern -- each factory returns a Svelte-compatible readable store plus action functions.
<script>
import { createAtmosphereStore } from 'atmosphere.js/svelte';
const { store: chat, push } = createAtmosphereStore({ url: '/chat', transport: 'websocket' });
</script>
<p>Status: {$chat.state}</p>
<button on:click={() => push({ text: 'Hello!' })}>Send</button><script>
import { createRoomStore } from 'atmosphere.js/svelte';
const { store: lobby, broadcast } = createRoomStore(
{ url: '/atmosphere/room', transport: 'websocket' },
'lobby',
{ id: 'user-1' },
);
</script>
<p>Members: {$lobby.members.map(m => m.id).join(', ')}</p>
<button on:click={() => broadcast({ text: 'Hello!' })}>Broadcast</button><script>
import { createPresenceStore } from 'atmosphere.js/svelte';
const presence = createPresenceStore(
{ url: '/atmosphere/room', transport: 'websocket' },
'lobby',
{ id: 'user-1' },
);
</script>
<p>{$presence.count} users online</p><script>
import { createStreamingStore } from 'atmosphere.js/svelte';
const { store, send, reset } = createStreamingStore({
url: '/ai/chat',
transport: 'websocket',
});
</script>
<button on:click={() => send('What is Atmosphere?')}>Ask</button>
<p>{$store.fullText}</p>
{#if $store.isStreaming}<span>Generating...</span>{/if}The server sends JSON messages using the Atmosphere AI streaming protocol:
{"type": "streaming-text", "data": "Hello", "sessionId": "abc-123", "seq": 1}
{"type": "progress", "data": "Thinking...", "sessionId": "abc-123", "seq": 2}
{"type": "metadata", "key": "model", "value": "gpt-4", "sessionId": "abc-123", "seq": 3}
{"type": "complete", "data": "Done", "sessionId": "abc-123", "seq": 10}
{"type": "error", "data": "Rate limited","sessionId": "abc-123", "seq": 11}Use subscribeStreaming for framework-agnostic streaming, or the hooks above for React/Vue/Svelte.
| Option | Type | Description |
|---|---|---|
url |
string |
Endpoint URL |
transport |
string |
'websocket', 'sse', 'long-polling', 'streaming' |
fallbackTransport |
string |
Transport to use if primary fails |
reconnect |
boolean |
Enable auto-reconnection |
reconnectInterval |
number |
Time between reconnections (ms) |
maxReconnectOnClose |
number |
Maximum reconnection attempts |
trackMessageLength |
boolean |
Enable message length tracking |
headers |
object |
Custom headers |
withCredentials |
boolean |
Include credentials |
- Chrome/Edge: last 2 versions
- Firefox: last 2 versions + ESR
- Safari: last 2 versions
- Mobile Safari (iOS): last 2 versions
- Chrome Android: last 2 versions
- AI Integration -- server-side
@AiEndpointandStreamingSession - Rooms & Presence -- server-side room management
- wAsync Java Client
- Module README