docs
TypeScript SDKCore Concepts

React Providers

UrunProvider, useApp, and the auth bridges that connect your React app to a deployed uRun app

UrunProvider configures the app proxy; useApp() hands you the deployed app; auth bridges supply the browser's access tokens. That is the whole entry point — there is no separate session/compositor provider tree to assemble.

The provider stack

A typical app nests an auth bridge around UrunProvider:

import '@urun-sh/react/styles.css'
import { UrunProvider, useApp } from '@urun-sh/react'
import { UrunWorkOSProvider } from '@urun-sh/react/workos'   // Next.js: '@urun-sh/react/next-workos'

export default function App() {
  return (
    <UrunWorkOSProvider clientId="client_...">
      <UrunProvider baseUrl="https://urun.sh" orgId="your-org-id" authProvider="workos" appId="my-app">
        <Player />
      </UrunProvider>
    </UrunWorkOSProvider>
  )
}

UrunProvider

UrunProvider configures the app proxy that useApp() returns. In the explicit-JWT setup shown above, the browser sends orgId plus a user/session JWT (resolved by the auth bridge); uRun validates it server-side.

PropTypeRequiredDescription
baseUrlstringif jwt/orgId setBase URL of your uRun backend (e.g. https://urun.sh)
orgIdstringif jwt setYour organization ID
appIdstringyesThe deployed app useApp() resolves
authProviderstringAuth provider id, e.g. "workos"

UrunProvider also supports a self-mint mode that omits baseUrl/orgId/jwt entirely and fetches a token server-side instead — see the full prop reference on the Providers page.

useApp()

useApp() returns the deployed app proxy. Each property access is a deployed Python function; calling it returns a render-safe Session.

function Player() {
  const app = useApp()
  const session = app.generate({ prompt: 'a sunset' })   // render-safe
  const video = session.stream('video')

  useEffect(() => {
    if (video.track && ref.current) ref.current.srcObject = new MediaStream([video.track])
  }, [video.track])

  return <video ref={ref} autoPlay muted />
}

useApp() is render-safe: repeated app.generate(args) calls with the same args during re-renders reuse the same session. session.stream(name) and session.doc(name) are likewise stable. See the App reference for the full Session surface (.stream, .doc, .onPhase, .disconnect).

Auth bridges

UrunProvider needs a source of short-lived access tokens. Pick the bridge that matches your auth:

BridgeImportUse for
UrunWorkOSProvider@urun-sh/react/workosPure React WorkOS apps
UrunWorkOSProvider@urun-sh/react/next-workosNext.js WorkOS apps
UrunAuthProvider@urun-sh/reactAny provider — supply a getAccessToken callback
UrunJwtProvider@urun-sh/reactA static JWT (tests / customer-JWT)
// Generic provider with your own token source:
import { UrunAuthProvider } from '@urun-sh/react'

<UrunAuthProvider getAccessToken={async () => myTokenStore.current()}>
  <UrunProvider baseUrl="https://urun.sh" orgId="your-org-id" authProvider="workos" appId="my-app">
    {children}
  </UrunProvider>
</UrunAuthProvider>

No secrets in the browser

The bridges forward short-lived user JWTs only. Never pass a server API key or the urun_… deploy key to a browser client.

Errors

Wrap your app in UrunErrorBoundary to catch session/transport errors and render a fallback instead of crashing the tree.

Media components

Below the provider, media I/O is declarative: send with <Camera> / <Mic>, show with <Video> / <Image> / <Audio>, loop voice with <Voice> — one session per <Session>, or an explicit session prop per component. Copy-paste recipes: Inputs & outputs.

Related:

On this page