Nuxt Recipe
The SDK is framework-agnostic. Keep Vue-specific glue in the consuming app so the SDK stays testable and portable.
Singleton client
ts
// composables/useSimulatorClient.ts
import { createSimulatorClient } from '@my-swu/simulator-client'
import type { SimulatorClient } from '@my-swu/simulator-client'
let simulatorClient: SimulatorClient | undefined
export function useSimulatorClient(): SimulatorClient {
if (simulatorClient == null) {
const config = useRuntimeConfig()
// Keep one client instance per app runtime.
simulatorClient = createSimulatorClient({ baseUrl: config.public.simulatorBaseUrl })
}
return simulatorClient
}Expose simulatorBaseUrl via nuxt.config.ts:
ts
export default defineNuxtConfig({
runtimeConfig: {
public: {
// Public because browser clients need this origin for HTTP and sockets.
simulatorBaseUrl: 'http://127.0.0.1:4000',
},
},
})Reactive match state
ts
// composables/useMatch.ts
import type { GameEvent, GameState, MatchSession } from '@my-swu/simulator-client'
export function useMatch() {
const simulatorClient = useSimulatorClient()
// Store authoritative state and append-only event log separately.
const matchSnapshot = ref<GameState | null>(null)
const gameEvents = ref<GameEvent[]>([])
let matchSession: MatchSession | undefined
async function connect(matchId: string, seatToken: string) {
// Seat token is private; pass it only to the socket-owning client.
matchSession = simulatorClient.session.create({ matchId, seatToken })
await matchSession.connect()
matchSnapshot.value = matchSession.snapshot ?? null
matchSession.on('snapshot', nextMatchSnapshot => {
// Replace state on each snapshot.
matchSnapshot.value = nextMatchSnapshot
})
matchSession.on('event', gameEvent => {
// Events drive timeline UI and animations.
gameEvents.value.push(gameEvent)
})
}
// Close sockets when the composable owner unmounts.
onBeforeUnmount(() => matchSession?.close())
return { connect, session: () => matchSession, events: gameEvents, snapshot: matchSnapshot }
}SSR safety
The SDK uses fetch and WebSocket globals. In Nuxt 3 server contexts:
fetchis available natively.WebSocketis not. GuardmatchSession.connect()behind a client-only boundary, for example insideonMountedor a<ClientOnly>wrapper.
