About serverpod-streams
A Serverpod skill for defining endpoint methods that accept or return streams, with generated client stubs and WebSocket-managed connections. It is for developers building streaming interactions between Serverpod clients and endpoints.
Key features
- 01Stream parameters and return values
- 02WebSocket-managed client stubs
- 03Generated stubs via serverpod generate
- 04Stream lifecycle and cancellation handling
- 05Serializable exception propagation
Use cases
- 01Echo client messages from an endpoint
- 02Build server-to-client streaming methods
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ serverpod/ serverpod --skill serverpod-streamsAfter installing, type/serverpod-streamsin Claude Code to confirm it loaded.
Details
From the project READMEServerpod Streams
Endpoint methods that take or return Stream<T> get WebSocket-managed client stubs. Types must be serializable.
It's a common use case to use streams together with server events. See Server Events.
Defining a streaming method
class ExampleEndpoint extends Endpoint {
Stream<String> echoStream(Session session, Stream<String> stream) async* {
await for (var message in stream) {
yield message;
}
}
}
Run serverpod generate for client stubs.
Client usage
var inStream = StreamController<String>();
var outStream = client.example.echoStream(inStream.stream);
outStream.listen((message) => print('Received: $message'));
inStream.add('Hello');
Close the StreamController when done. Cancelling the subscription closes both sides. We can use the in/out stream independently (often only need for stream from server). Methods may take multiple stream parameters when needed. Keep the API shape explicit and regenerate after changes.
Lifecycle
- Each call creates a server
Session; for return-stream methods, the session stays alive until the returned stream completes or is cancelled. - WebSocket disconnect closes streams on both sides.
- Return-stream methods stay alive until cancelled or completed.
Error handling
Throwing a serializable exception closes the stream; the client receives it in onError. Exceptions can flow in both directions. Define exception types in .spy.yaml.
Example combined with server events (simplified)
class PixelDrawingEndpoint extends Endpoint {
static const _channelPixelAdded = 'pixel-added';
final _pixelData = Uint8List(_numPixels);
Future<void> setPixel(
Session session, {
required int colorIndex,
required int pixelIndex,
}) async {
_pixelData[pixelIndex] = colorIndex;
// Notify all connected clients that we set a pixel, by posting a message
// to the _channelPixelAdded channel.
session.messages.postMessage(
_channelPixelAdded,
ImageUpdate(
pixelIndex: pixelIndex,
colorIndex: colorIndex,
),
);
}
/// Returns a stream of image updates. The first message will always be a
/// `ImageData` object, which contains the full image. Sequential updates
/// will be `ImageUpdate` objects, which contains a single updated pixel.
Stream imageUpdates(Session session) async* {
var updateStream =
session.messages.createStream<ImageUpdate>(_channelPixelAdded);
yield ImageData(
pixels: _pixelData.buffer.asByteData(),
width: _imageWidth,
height: _imageHeight,
);
await for (var imageUpdate in updateStream) {
yield imageUpdate;
}
}
}