@surfjs/vue
v0.5.0
Published
Vue composables for the window.surf runtime — register local handlers, sync state, and surface Surf Live
Maintainers
Readme
@surfjs/vue
Vue composables for the window.surf runtime — register local handlers, sync state, and surface Surf Live.
A thin Vue 3 wrapper around @surfjs/web. Provides composables for registering local command handlers, syncing real-time state, and setting up WebSocket connections via Surf Live.
Install
npm install @surfjs/vueuseSurfCommands — Register local handlers
The primary composable. Register one or more command handlers that run locally in the browser — no server roundtrip.
<script setup>
import { useSurfCommands } from '@surfjs/vue'
useSurfCommands({
'canvas.addCircle': {
mode: 'local',
run: ({ x, y, radius }) => {
addCircleToCanvas({ x, y, radius })
return { ok: true }
}
},
'canvas.clear': {
mode: 'local',
run: () => {
clearCanvas()
return { ok: true }
}
}
})
</script>
<template>
<canvas id="main" />
</template>Handlers are automatically registered on mount and cleaned up on unmount.
Modes:
| Mode | Behavior |
|------|----------|
| 'local' | Runs only in browser. No server call. |
| 'sync' | Runs in browser, then POSTs to server in background. |
SurfProvider — WebSocket / Surf Live
Wrap your app with SurfProvider to establish a WebSocket connection for real-time state sync:
<script setup>
import { SurfProvider } from '@surfjs/vue'
</script>
<template>
<SurfProvider url="wss://myapp.com/surf/ws" endpoint="https://myapp.com">
<MyApp />
</SurfProvider>
</template>| Prop | Type | Description |
|------|------|-------------|
| url | string | WebSocket URL to connect to |
| auth | string? | Auth token to send on connect |
| channels | string[]? | Channels to subscribe to on connect |
| endpoint | string? | HTTP endpoint for manifest discovery |
useSurfState — Real-time state sync
Receive server-pushed state updates over the WebSocket connection:
<script setup>
import { useSurfState } from '@surfjs/vue'
const order = useSurfState<Order>('order.updated', null)
</script>
<template>
<p v-if="order">Status: {{ order.status }}</p>
<p v-else>Waiting for order...</p>
</template>Returns a Vue ref that auto-updates from surf:state and surf:patch events.
useSurf — Access context
Access the Surf context anywhere within a SurfProvider:
<script setup>
import { useSurf } from '@surfjs/vue'
const { execute, status, connected } = useSurf()
async function runCommand() {
const result = await execute('items.list', { limit: 10 })
console.log(result)
}
</script>useSurfEvent — Subscribe to events
<script setup>
import { useSurfEvent } from '@surfjs/vue'
useSurfEvent('notification.received', (data) => {
console.log('Got notification:', data)
})
</script>Automatically cleans up on component unmount.
SurfBadge — Floating agent indicator
<script setup>
import { SurfBadge } from '@surfjs/vue'
</script>
<template>
<MyApp />
<SurfBadge endpoint="https://myapp.com" :commands="commands" />
</template>Full example
<script setup>
import { SurfProvider, useSurfCommands, useSurfState, SurfBadge } from '@surfjs/vue'
useSurfCommands({
'canvas.addCircle': {
mode: 'local',
run: (params) => {
addCircleToCanvas(params)
return { ok: true }
}
}
})
const latestEvent = useSurfState('canvas.updated', null)
</script>
<template>
<SurfProvider url="wss://myapp.com/surf/ws">
<canvas id="main" />
<SurfBadge endpoint="https://myapp.com" />
</SurfProvider>
</template>Relationship to @surfjs/web
@surfjs/vue is a thin wrapper. Under the hood, useSurfCommands calls registerCommand from @surfjs/web and returns the cleanup function via onUnmounted. If you're not using Vue, use @surfjs/web directly.
