PK Battle

TikTok-style live PK battles between hosts with real-time scoring and split-screen views

Overview

PK Battle enables live competitive interactions between two or more hosts. Hosts are placed in a shared battle room where viewers can watch both streams side-by-side and send scores (gifts, votes, likes) that update in real time. State is managed entirely via room metadata and data channels — no Redis required.

N-Host Support

Support 2 or more hosts in a single battle

Real-time Scoring

Scores update instantly via data channel

Custom Duration

Configurable battle length from 10s to 1 hour

Auto Winner

Winner determined automatically at battle end

Battle Lifecycle

Each PK battle progresses through a series of states:

invitedBattle created, waiting for invited hosts to respond
acceptedAll hosts accepted, ready to start
countdown3-2-1 countdown before battle begins
activeBattle in progress — scores are being tracked
resultBattle ended, winner displayed
endedBattle fully concluded

Quick Start

Get a PK battle running in minutes

1

Create a PK Battle

1import { useBaxCloud } from '@baxcloud/react';
2
3const client = useBaxCloud();
4
5const battle = await client.createPKBattle({
6  duration: 300, // 5 minutes
7  creatorIdentity: 'host-a',
8  creatorName: 'Streamer A',
9});
10console.log(battle.id); // battle ID
2

Invite another host

1await client.inviteToPK(battle.id, {
2  inviteeIdentity: 'host-b',
3  inviteeName: 'Streamer B',
4});
3

Host B accepts the invite

1const { state, token, serverUrl } = await client.joinPK(battle.id, {
2  identity: 'host-b',
3  name: 'Streamer B',
4});
5// Use token + serverUrl to join the PK battle room
4

Start the battle

1await client.startPKBattle(battle.id, 3); // 3-second countdown
5

Send scores during battle

1await client.sendPKScore(battle.id, {
2  hostIdentity: 'host-a',
3  value: 100,
4  type: 'gift',
5});
6

End the battle

1const result = await client.endPKBattle(battle.id);
2console.log(result.winner); // identity of the winner

React UI Components

Pre-built split-screen battle view and hook

PKBattleView Component

Drop-in split-screen component that displays hosts side-by-side with live scores, countdown overlay, and result screen. Fully customizable via render props.

1import { PKBattleView } from '@baxcloud/react';
2
3function MyBattlePage({ battleId }: { battleId: string }) {
4  return (
5    <PKBattleView
6      battleId={battleId}
7      layout="horizontal"
8      pollInterval={1000}
9      onPKEvent={(event, data) => {
10        console.log('PK event:', event, data);
11      }}
12      onStateChange={(state) => {
13        console.log('Battle state:', state.status);
14      }}
15      style={{ width: '100%', height: 400 }}
16    />
17  );
18}

usePKBattle Hook

Full-featured hook for building custom PK battle UIs with state management, countdown timer, event listener, and all battle actions.

1import { usePKBattle } from '@baxcloud/react';
2
3function CustomBattleUI({ battleId }: { battleId: string }) {
4  const {
5    state,
6    countdown,
7    loading,
8    error,
9    lastEvent,
10    sendScore,
11    end,
12    refresh,
13  } = usePKBattle({ battleId, pollInterval: 1000 });
14
15  if (loading) return <div>Loading...</div>;
16  if (!state) return <div>No battle</div>;
17
18  return (
19    <div>
20      <h2>Status: {state.status}</h2>
21      {countdown > 0 && <h1>{countdown}</h1>}
22      {state.hosts.map((host) => (
23        <div key={host.identity}>
24          {host.name}: {host.score}
25          <button onClick={() => sendScore({
26            hostIdentity: host.identity,
27            value: 1,
28          })}>
29            +1
30          </button>
31        </div>
32      ))}
33      {state.winner && <p>Winner: {state.winner}</p>}
34    </div>
35  );
36}

API Reference

MethodDescriptionEndpoint
createPKBattle()Create a new PK battle with duration and creatorPOST /v1/pk/create
inviteToPK()Invite another host to the battlePOST /v1/pk/:id/invite
joinPK()Accept and join a PK battle (returns token)POST /v1/pk/:id/join
declinePK()Decline a PK battle invitationPOST /v1/pk/:id/decline
startPKBattle()Start the battle with optional countdownPOST /v1/pk/:id/start
sendPKScore()Send a score/gift/vote to a hostPOST /v1/pk/:id/score
endPKBattle()End the battle and determine winnerPOST /v1/pk/:id/end
getPKBattle()Get current battle stateGET /v1/pk/:id
listPKBattles()List all active battlesGET /v1/pk
getPKViewerToken()Get a viewer token for the PK roomPOST /v1/pk/:id/viewer-token
updatePKSettings()Update duration or metadataPUT /v1/pk/:id/settings

Webhook Events

Subscribe to PK battle events in your webhook settings

EventDescription
pk.startedPK battle began (after countdown)
pk.score_updateA host's score changed during the battle
pk.endedPK battle finished with final scores and winner
pk.cancelledPK battle was cancelled or declined before starting

Real-time Data Channel Events

Events broadcast via sendData for instant updates

These events are sent to all participants in the PK battle room via the data channel. Use onPKEvent() in client SDKs or the usePKBattle hook in React to listen for them.

EventWhen
pk.invitedA host was invited
pk.acceptedA host accepted the invite
pk.declinedA host declined
pk.countdownCountdown started
pk.startedBattle began
pk.score_updateScore changed
pk.endedBattle ended
pk.cancelledBattle cancelled
pk.host_joinedA host joined the room
pk.host_leftA host left the room
pk.settings_updatedBattle settings changed
PK Battle state is stored in room metadata. No database or Redis is needed — all state syncs through the room. When the room closes, the battle data is gone. For persistence, use webhook events (pk.ended) to store final results in your own database.