Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Clients

A Client defines the wire contract between browser clients and actors.

Everything else in Liminal hangs off that contract:

  • actors point at a client definition
  • external handlers implement the methods callable by connected clients
  • Auditions can merge multiple clients into one event stream and call surface
  • reducers derive local state from events after the initial hydration

Define a client

A client is a named state schema, external method table, and event table.

import { Schema as S } from "effect"
import { Client } from "liminal"
 
export const Player = S.Literals(["X", "O"])
export const Coordinate = S.Literals([0, 1, 2])
export const Coordinates = S.Tuple([Coordinate, Coordinate])
 
export class TicTacToeClient extends Client.Service<TicTacToeClient>()("examples/TicTacToeClient", {
  events: {
    GameStarted: {},
    MoveMade: {
      player: Player,
      position: Coordinates,
    },
    GameEnded: {
      winner: S.optional(Player),
    },
  },
  external: {
    Move: {
      payload: S.Struct({
        position: Coordinates,
      }),
      success: S.Void,
      failure: S.Never,
    },
  },
  state: {
    awaitingPartner: S.Boolean,
    name: Player,
  },
}) {}

Shape

  • state is the struct-fields record hydrated when the client connects.
  • external is a record of { payload, success, failure } methods callable through Client.fn(...).
  • events is a record of plain struct fields.
  • Liminal tags events automatically with _tag.

Next concepts

  • Methods covers reusable method definitions.
  • Client Calls covers Client.fn(...).
  • Events covers Client.events and replay.
  • Client State covers hydration and reducers.
  • Actors covers the server-side runtime for this protocol.