State and schema

A schema describes shared state and gives both server and client TypeScript types. Put it in irtio/schema.ts and import it on both sides.

// irtio/schema.ts
import {
  bool,
  defineSchema,
  entity,
  enumOf,
  f32,
  list,
  ref,
  singleton,
  str,
  u8,
  u16,
} from '@irtio/schema';

import { rpc } from './rpc.js';

export const schema = defineSchema(
  {
    players: entity({ x: f32, y: f32, name: str(24), score: u16 }),
    cards: entity({ x: f32, y: f32, faceUp: bool, heldBy: ref('players').opt }),
    match: singleton(
      { phase: enumOf('lobby', 'play', 'over'), round: u8, log: list(str(48), 20) },
      { serverOwned: true },
    ),
  },
  {
    project: 'p_c0ffee1234abcd56',
    roles: ['player', 'spectator'] as const,
    rpc,
  },
);

Choose a collection

Use entity() for keyed records such as players or items. Use singleton() for one shared object such as the match phase. The room creates and updates these records; clients can write instances they own.

Choose field types that fit your values. For example, u8 holds integers from 0 to 255 and str(24) holds up to 24 UTF-8 bytes. f32 stores a 32-bit float. Optional values use .opt; defaults use .default(value).

The schema reference lists all field types, collection methods, options, and limits. See ownership for creating player records and controlling writes.