Introduction
Building a responsive Flutter chat UI is essential for any modern messaging app. Stream Chat SDK simplifies real-time messaging by providing prebuilt widgets and robust backend support. In this intermediate tutorial, you’ll learn how to integrate Stream Chat SDK into your Flutter project, initialize a chat client, and assemble a fully functional chat interface. We’ll also explore customizing message bubbles and adding avatars to your Flutter chat interface.
Setup
First, create a new Flutter project or open your existing codebase. Add the Stream Chat Flutter package to your pubspec.yaml:
dependencies:
flutter:
sdk: flutter
stream_chat_flutter
Run flutter pub get to install the package. You’ll need a Stream Chat API key—sign up at getstream.io, create an app, and copy your API key.
In your main.dart, import the SDK:
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
Initializing Stream Chat
Initialize the StreamChatClient before rendering your chat UI. This client handles authentication and channel management.
final client = StreamChatClient(
'YOUR_STREAM_API_KEY',
logLevel: Level.INFO,
);
void main() {
runApp(MyApp(client: client));
}
class MyApp extends StatelessWidget {
final StreamChatClient client;
MyApp({required this.client});
@override
Widget build(BuildContext context) {
return StreamChat(
client: client,
child: MaterialApp(
home: ChannelListPage(),
),
);
}
}Authenticate a user and connect to Stream:
await client.connectUser(
User(id: 'user-id', extraData: {'name': 'Alice'}),
client.devToken('user-id'),
);
Building the Chat UI
With the client ready, build a channel list and chat screen. Stream’s widgets like ChannelListView, ChannelHeader, and MessageListView speed up development.
Channel List Screen:
class ChannelListPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChannelsBloc(
child: ChannelListView(
filter: Filter.in_('members', [StreamChat.of(context).currentUser!.id]),
sort: [SortOption('last_message_at')],
pagination: PaginationParams(limit: 20),
channelPreviewBuilder: (_, channel) {
return ListTile(
title: Text(channel.extraData['name'] ?? 'No Name'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => ChatScreen(channel: channel),
),
);
},
);
},
),
);
}
}Chat Screen:
class ChatScreen extends StatelessWidget {
final Channel channel;
ChatScreen({required this.channel});
@override
Widget build(BuildContext context) {
return StreamChannel(
channel: channel,
child: Scaffold(
appBar: ChannelHeader(),
body: Column(
children: [
Expanded(child: MessageListView()),
MessageInput(),
],
),
),
);
}
}This creates a Flutter messaging UI where messages and input are wired automatically. The MessageListView listens to new events, ensuring real-time updates.
Customizing Message Components
Stream Chat SDK supports deep customization. You can override default message bubbles, avatar widgets, and date separators to match your brand.
Replace MessageListView with a custom builder:
MessageListView(
messageBuilder: (context, details, messages, defaultMessage) {
final isOwnMessage = details.message.user!.id == StreamChat.of(context).currentUser!.id;
return Align(
alignment: isOwnMessage ? Alignment.centerRight : Alignment.centerLeft,
child: Container(
margin: EdgeInsets.symmetric(vertical: 4, horizontal: 8),
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: isOwnMessage ? Colors.blueAccent : Colors.grey.shade200,
borderRadius: BorderRadius.circular(16),
),
child: Text(
details.message.text ?? '',
style: TextStyle(color: isOwnMessage ? Colors.white : Colors.black87),
),
),
);
},
headerBuilder: (context, _) => Center(
child: Text('Today', style: TextStyle(color: Colors.grey)),
),
),You can also customize the avatar and timestamp:
final customAvatar = (BuildContext ctx, User user) {
return CircleAvatar(
backgroundImage: NetworkImage(user.image ?? ''),
radius: 16,
);
};
MessageListView(
avatarBuilder: customAvatar,
showUserAvatars: true,
showMessageTimestamp: true,
);Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
In this tutorial, you learned to set up Stream Chat SDK, initialize the client, and assemble a Flutter chat UI complete with channel listing, message streaming, and input handling. We also covered customizing message bubbles and avatars for a unique look. With these building blocks, you can implement advanced features such as typing indicators, read receipts, and thread support. Explore Stream’s documentation to deepen your Flutter messaging UI.