Docs / Quick start - Dart

Quick start - Dart

Connect a plain Dart or Flutter app to a running Asobi server in about five minutes. Building a Flame game? See the Flame quickstart instead. No server yet? Run the server quickstart first - it gives you a backend on localhost:8084 with a default match mode.

1. Add the package

The package is asobi. Its only dependencies are http and web_socket_channel.

dart pub add asobi

Everything is exported from one barrel - import 'package:asobi/asobi.dart';.

2. Authenticate and connect

Construct the client, get a guest session, subscribe to the realtime streams, then connect. The realtime hooks are broadcast streams - subscribe before calling connect(), and wait for onConnected before queueing.

import 'dart:async';
import 'package:asobi/asobi.dart';

Future<void> main() async {
  final client = AsobiClient('localhost', port: 8084);

  // Same deviceId + deviceSecret resumes the guest; a new pair creates one.
  // You generate and persist deviceSecret (>= 32 CSPRNG bytes, base64).
  await client.auth.guest(deviceId, deviceSecret);

  final connected = Completer<void>();
  client.realtime.onConnected.stream.listen((_) {
    if (!connected.isCompleted) connected.complete();
  });
  client.realtime.onMatchmakerMatched.stream.listen((m) => print('match ${m.matchId}'));
  client.realtime.onMatchState.stream.listen((s) => render(s.players));

  await client.realtime.connect();
  await connected.future.timeout(const Duration(seconds: 5));

  // No join(mode) call - queue the matchmaker; the server pushes the match.
  await client.realtime.addToMatchmaker(mode: 'default');
}

Then send input with the fire-and-forget sendMatchInput (payload shape is game-specific): client.realtime.sendMatchInput({'move_x': 1, 'move_y': 0});.

Core API

  • AsobiClient(host, {port = 8084, useSsl = false, tokenStore}).
  • client.auth.guest(deviceId, deviceSecret) - also register, login, upgradeGuest, refresh.
  • client.realtime.connect() / addToMatchmaker(mode: 'default') / sendMatchInput(map).
  • Broadcast streams: onConnected, onMatchmakerMatched, onMatchState, onMatchFinished, onAuthExpired (consume via .stream.listen(...)).

Gotchas

  • Subscribe before connect. Broadcast streams don't buffer, so a late listener misses early frames. Gate addToMatchmaker on onConnected.
  • Persist tokens yourself. The access token is memory-only; inject a TokenStore (e.g. flutter_secure_storage) to persist the refresh token, and store the guest deviceSecret separately.
  • Auth expiry stops reconnect. On onAuthExpired, re-auth (client.auth.refresh()) and reconnect. On Flutter Web use useSsl: true so the socket is wss://.

What's next