flutter pub add stream_chat_flutterGetting Started
This guide walks you through adding a fully working chat screen to a Flutter app in minutes using the stream_chat_flutter package.
Add the dependency
Or add it to pubspec.yaml manually:
dependencies:
stream_chat_flutter: ^10.0.0Initialize the client
Create a StreamChatClient with your API key and connect the current user before entering the widget tree:
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
final client = StreamChatClient('YOUR_API_KEY', logLevel: Level.OFF);
await client.connectUser(
User(id: 'user-id', name: 'Jane Doe'),
client.devToken('user-id').rawValue, // dev token only — use a real token in production
);Wrap your app in StreamChat
StreamChat provides the client, theme, and config to all widgets below it:
MaterialApp(
builder: (context, child) => StreamChat(
client: client,
child: child!,
),
home: const ChannelListPage(),
)Add a channel list screen
StreamChannelListView renders a scrollable, real-time channel list. Tapping a row navigates to the channel screen:
class ChannelListPage extends StatefulWidget {
const ChannelListPage({super.key});
@override
State<ChannelListPage> createState() => _ChannelListPageState();
}
class _ChannelListPageState extends State<ChannelListPage> {
late final _controller = StreamChannelListController(
client: StreamChat.of(context).client,
filter: Filter.in_('members', [StreamChat.of(context).currentUser!.id]),
channelStateSort: const [SortOption<ChannelState>.desc('last_message_at')],
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const StreamChannelListHeader(),
body: StreamChannelListView(
controller: _controller,
onChannelTap: (channel) => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => StreamChannel(
channel: channel,
child: const ChannelPage(),
),
),
),
),
);
}
}Add a channel (chat) screen
A channel screen combines three widgets stacked in a Scaffold:
class ChannelPage extends StatelessWidget {
const ChannelPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const StreamChannelHeader(),
body: Column(
children: [
Expanded(
child: StreamMessageListView(
threadBuilder: (_, parentMessage) => StreamChannel(
channel: StreamChannel.of(context).channel,
child: ThreadPage(parent: parentMessage),
),
),
),
const StreamMessageComposer(),
],
),
);
}
}StreamChannel (the InheritedWidget wrapping ChannelPage in the navigation call above) makes the channel available to StreamChannelHeader, StreamMessageListView, and StreamMessageComposer without any additional wiring.
Platform requirements
Android
The package uses photo_manager for media access. Follow the Android 10+ wiki to configure permissions.
iOS
Add usage descriptions to Info.plist as required by flutter_file_picker, video_player, and image_picker.
Web
Add oncontextmenu="return false;" to the <body> tag in index.html to let the SDK override right-click behavior.
macOS
Add the file_selector entitlements for network and file access to both Release.entitlements and DebugProfile.entitlements.
Next steps
- Theming — change colors, fonts, and spacing
- Customizing Widgets — replace components with your own
- StreamMessageListView — message list deep dive
- StreamMessageComposer — composer configuration and customization