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 asobiEverything 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)- alsoregister,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
addToMatchmakerononConnected. - 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 guestdeviceSecretseparately. - Auth expiry stops reconnect. On
onAuthExpired, re-auth (client.auth.refresh()) and reconnect. On Flutter Web useuseSsl: trueso the socket iswss://.