Skip to content

About

Broadcast graphics for OBS, as React components. No server, no backend, nothing to deploy. Easy.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

Single Studio

npm licence

Broadcast graphics for OBS, as React components. Scoreboards, lower thirds, tickers and clocks, driven from an operator's board that runs inside OBS as a custom browser dock.

No server. No backend. Nothing to deploy but static files — and the graphics keep working when the network doesn't.

See a studio running →  ·  Documentation →

Start

Press Use this template, then:

npm install
npm run dev

The board opens at the printed URL. Its header menu lists every graphic's browser-source URL with a copy button — that is what you paste into OBS.

A studio in two files

Both halves name the same path. That is the whole model.

// src/control/Control.jsx — the operator's board, in an OBS dock
import { Field, Panel, Stepper } from '@single-studio/core/control'

export default function Control() {
  return (
    <Panel title="Scores">
      <Field name="home.name" label="Home" />
      <Stepper name="home.score" label="Home score" />
    </Panel>
  )
}
// src/sources/Scoreboard.jsx — one file per OBS browser source
import { Scene, Variable } from '@single-studio/core/source'

export default function Scoreboard() {
  return (
    <Scene>
      <Variable name="home.name" fallback="Home" />
      <Variable name="home.score" fallback="0" />
    </Scene>
  )
}

Press + on the board and the scoreboard changes. There is nothing to declare, no store to configure, and no wiring between the two files.

What you get

It keeps working. A studio is static files and its state lives on the machine running it. A dropped connection mid-show costs you collaboration, not your graphics.

Scores that add up. Two operators both pressing +1 make +2. The obvious implementation makes +1 — a scoreboard quietly lying on air, with nothing to report it.

Clocks that agree. Every machine shows the same number on the same countdown, including the one whose system clock is four seconds out.

Nothing flashes. A graphic switched on mid-show paints its real values, not a frame of placeholder text over the programme.

Collaboration when you want it. Off until somebody pastes a link. Then a producer drives the scores from their own laptop, over a service you own, end-to-end encrypted with a key that service never sees. Their entire setup is pasting one link into an OBS dock.

The pieces

Template Start here. A studio, wired up, ready to edit
Demo Four graphics and a board — live
@single-studio/core The framework
@single-studio/provider-supabase Multi-operator collaboration, over a project you own
@single-studio/plugin-obs The live scene, stream and record state, over obs-websocket
@single-studio/plugin-rocket-league Score, clock, goals and the stat feed, over Psyonix's own API
@single-studio/plugin-twitch Chat, follows, subs, gifts, cheers and raids — no backend
@single-studio/plugin-sheets A shared spreadsheet as a data source, on an API key
Plugin template Build your own — public domain, take it and go

Documentation

fourcourtjester.github.io/Single-Studio

Requirements

React 18 or 19, and a Chromium-based browser at 114 or newer — which is what OBS embeds. Tested against React 19; the >=18 peer range is deliberate, so a studio already on 18 does not have to move to take a framework update.

Licence

MIT — see LICENSE. Changes are in CHANGELOG.md.

About

Broadcast graphics for OBS, as React components. No server, no backend, nothing to deploy. Easy.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages