Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.spatius.ai/llms.txt

Use this file to discover all available pages before exploring further.

What is Direct Mode for Web?

Direct Mode for Web is the simplest way to put a Spatius avatar in a browser app. @spatius/avatarkit connects directly to Motion Server, sends avatar speech audio, and renders motion locally — no agent worker or relay backend needed beyond a Session Token endpoint.

When to use

  • You have or generate avatar speech audio in the browser — your own TTS output, prerecorded clips, or agent audio fetched server-side.
  • You want the smallest backend footprint: a single Session Token endpoint.
  • You want the client to own rendering and don’t need backend-controlled audio or transport.

Run the demo

Web SDK quickstart

speech-to-avatar-quickstart in 5 minutes — minimal smoke test.

Multi-framework reference

React, Vue, vanilla JavaScript, and Next.js reference clients.

Install

pnpm add @spatius/avatarkit

Build tool configuration

Required: The SDK uses WASM files that need special build configuration. Configure your build tool before initializing the SDK, or .wasm requests will fail.
Add the official plugin to vite.config.ts:
vite.config.ts
import { defineConfig } from 'vite'
import { avatarkitVitePlugin } from '@spatius/avatarkit/vite'

export default defineConfig({
  plugins: [
    avatarkitVitePlugin(),
  ],
})
  • Dev server: serves .wasm files with the correct MIME type
  • Build: copies WASM files to dist/assets/
  • Cloudflare Pages: generates a _headers file
  • Vite options: configures optimizeDeps, assetsInclude, assetsInlineLimit
vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  optimizeDeps: {
    exclude: ['@spatius/avatarkit'],
  },
  assetsInclude: ['**/*.wasm'],
  build: {
    assetsInlineLimit: 0,
    rollupOptions: {
      output: {
        assetFileNames: (assetInfo) => {
          if (assetInfo.name?.endsWith('.wasm')) {
            return 'assets/[name][extname]'
          }
          return 'assets/[name]-[hash][extname]'
        },
      },
    },
  },
  configureServer(server) {
    server.middlewares.use((req, res, next) => {
      if (req.url?.endsWith('.wasm')) {
        res.setHeader('Content-Type', 'application/wasm')
      }
      next()
    })
  },
})
For deeper toolchain explanation, see Toolchain Setup.

Minimum integration

The smallest end-to-end flow with @spatius/avatarkit:
1

Initialize the SDK

import { AvatarSDK, DrivingServiceMode } from '@spatius/avatarkit'

await AvatarSDK.initialize('your-app-id', {
  region: 'us-west',
  drivingServiceMode: DrivingServiceMode.sdk, // default
})

AvatarSDK.setSessionToken('your-session-token')
The runtime accepts region, but the published types in @spatius/[email protected] do not yet expose it. Add a single declaration-merging file to your project so TypeScript stops complaining:
avatarkit-region.d.ts
import '@spatius/avatarkit'

declare module '@spatius/avatarkit' {
  interface Configuration {
    readonly region?: string
  }
}
A future SDK release will add region natively and this file can be deleted.
2

Load the avatar

import { AvatarManager } from '@spatius/avatarkit'

const avatar = await AvatarManager.shared.load('your-avatar-id', (progress) => {
  // progress.progress is in 0..1; multiply by 100 to render as a percentage.
  const percent = Math.round((progress.progress ?? 0) * 100)
  console.log(`Loading: ${percent}%`)
})
3

Mount the view

import { AvatarView } from '@spatius/avatarkit'

// Container must have non-zero width and height.
const container = document.getElementById('avatar-container')!
const avatarView = new AvatarView(avatar, container)
4

Initialize audio (inside a user gesture)

initializeAudioContext() must be called inside a user-gesture handler (a click, touchstart, or similar listener). Browsers reject AudioContext creation outside user gestures and the call fails silently.
button.addEventListener('click', async () => {
  await avatarView.controller.initializeAudioContext()
})
5

Connect and send audio

import { ConnectionState } from '@spatius/avatarkit'

await avatarView.controller.start()

await new Promise<void>((resolve, reject) => {
  avatarView.controller.onConnectionState = (state) => {
    if (state === ConnectionState.connected) resolve()
    else if (state === ConnectionState.failed) reject(new Error('Connection failed'))
  }
})

// Stream PCM16 mono audio at the configured sample rate (default 16 kHz)
avatarView.controller.send(audioChunk, /* end */ false)

// Mark end of the conversation round
avatarView.controller.send(lastChunk, /* end */ true)
6

Cleanup

avatarView.controller.close()
avatarView.dispose()
For full API signatures, types, audio format details, lifecycle management, error codes, browser compatibility, and common issues, see Web SDK Reference.

Next steps

Web SDK reference

Complete Web SDK API: AvatarSDK, AvatarManager, AvatarView, AvatarController, types, errors.

Browse all demos

Every runnable demo by platform and integration path.