# Flutter Introduction

The Flutter SDK enables you to build any type of chat or messaging experience for Android, iOS, Web and Desktop.

## Start here

- [Flutter tutorial](https://getstream.io/chat/sdk/flutter/tutorial/): Build a working chat app from an empty project.
- [UI components](https://getstream.io/chat/docs/sdk/flutter/): The full stream_chat_flutter widget library documentation.
- [Server-side overview](https://getstream.io/chat/docs/flutter-dart/server-side/): Tokens, app settings and everything else that runs on your backend.

>
> **Note:** This SDK is the client half of your integration. App settings, permissions, webhooks, push templates and data retention are configured from your backend with a server-side SDK or the REST API, and the token your app connects with has to be signed there too. See the [server-side overview](https://getstream.io/chat/docs/flutter-dart/server-side/) for what belongs there.
>

## How the SDK is structured

The SDK consists of 4 packages:

- [stream_chat](https://pub.dev/packages/stream_chat): A pure Dart package that can be used on any Dart project. It provides a low-level client to access the Stream Chat service.

- [stream_chat_flutter_core](https://pub.dev/packages/stream_chat_flutter_core): Provides business logic to fetch common things required for integrating Stream Chat into your application. The `core` package allows more customization and hence provides business logic but no UI components.

- [stream_chat_flutter](https://pub.dev/packages/stream_chat_flutter): This library includes both a low-level chat SDK and a set of reusable and customisable UI components. The full documentation for this package is available [here](https://getstream.io/chat/docs/sdk/flutter/).

- [stream_chat_persistence](https://pub.dev/packages/stream_chat_persistence): Provides a persistence client for fetching and saving chat data locally.

```mermaid
flowchart LR
  app[Your app] --> ui[UI widgets]
  app -. custom UI .-> core
  ui --> core[Core]
  core --> client[Client]
  persist[Persistence] -. caches for .-> client
  client <--> api[Stream API]
```

Build prototypes with the full UI package: `stream_chat_flutter` ships widgets already integrated with Stream's API, and it is the fastest way to get chat running in your app.

If you're building a very custom UI, the `core` package is the lean option. It exposes the SDK's logic for users, messages and channels through providers and builders, with no UI widgets.

The [online API tour](https://getstream.io/chat/tour/) shows how the API works; it runs JavaScript in the browser, but the ideas are the same in Dart.

## Build with Stream CLI and Agent Skills

The [Stream CLI](https://getstream.io/cli/docs/) and [Agent Skills](https://getstream.io/agent-skills/docs/) provide AI coding agents, such as Claude Code, Cursor, and Codex, with the tools and knowledge necessary to build apps with Stream.

Install the CLI and add the skills to your project:

```bash
curl -fsSL https://getstream.io/cli.sh | bash
getstream skills stream-flutter
```

Once installed, invoke it from your agent:

```text
/stream Add Stream Chat to my Flutter app.
```

The `/stream` skill acts as a router, reading your request and dispatching it to the specialist skill. You can also invoke the `/stream-flutter` skill directly.

Stream Agent Skills can also be installed from [skills.sh](https://www.skills.sh/getstream/agent-skills/stream).

## Getting started

This guide will quickly help you get up to speed on [Stream’s Chat API](https://getstream.io/chat/). The API is flexible and allows you to build any type of chat or messaging application.

Add one of the 3 packages to your app dependencies, to do that just open `pubspec.yaml` and add it inside the  **dependencies**  section.

```text label="None"
dependencies:
	# client + UX
 stream_chat_flutter: ^1.0.1-beta
	# core business logic widgets
 stream_chat_flutter_core: ^1.0.1-beta
	# client only
 stream_chat: ^1.0.2-beta
```

## Chat client

```dart label="Dart"
final apiKey = "{{ api_key }}";
final userToken = "{{ chat_user_token }}";

/// Create a new instance of [StreamChatClient] passing the apikey obtained from
/// your project dashboard.
final client = StreamChatClient(
  's2dxdhpxd94g',
  logLevel: Level.INFO,
);

/// Set the current user and connect the websocket.
/// In a production scenario, this should be done using a backend to generate
/// a user token using our server SDK.
/// Please see the following for more information:
/// https://getstream.io/chat/docs/ios_user_setup_and_tokens/
 await client.connectUser(
  User(id: 'super-band-9'),
  userToken,
 );
```

The user token is typically provided by your backend when you login or register in the app. If authentication is disabled for your app you can also use a `client.devToken(userId)` to generate an insecure token for development. You should **never** launch into production with authentication disabled.

For more complex token generation and expiration examples have a look at the [token provider documentation](https://getstream.io/chat/docs/android/tokens-and-authentication/).

## Channels

Let’s continue by watching your first channel. A channel contains messages and a list of members who are permanently associated with the channel and a list of watchers currently watching the channel. The example below shows how to set up a channel:

```dart label="Dart"
final channel = client.channel(
  'messaging',
  id: 'flutterdevs',
  extraData: {
   'name': 'Flutter devs',
  },
);

await channel.watch();
```

The first two arguments are the Channel Type and the Channel ID ( `messaging` and `flutterdevs` in this case). The Channel ID is optional; if you leave it out, the ID is determined based on the list of members. The channel type controls the settings we’re using for this channel.

There are 5 default types of channels:

- livestream

- messaging

- team

- gaming

- commerce

These five options above provide you with the most suitable defaults for those use cases. You can also define custom channel types if the 5 defaults don’t work for your use-case.

The third argument is an object containing the channel data. You can add as many custom fields as you would like as long as the total size of the object is less than 5KB.

## Messages

Now that we have the channel set up, let's send our first chat message:

```dart label="Dart"
final message = Message(
  text:
    'I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.',
  extraData: {
   'customField': '123',
  },
 );
 await channel.sendMessage(message);
```

Similar to users and channels, the sendMessage method allows you to add custom fields. When you send a message to a channel, Stream Chat automatically broadcasts to all the people that are watching this channel and updates in real-time.

## Querying channels

The `client.queryChannels` method enables you to retrieve a list of channels. You can specify a filter and sort order. The client keeps the channels list updates as new messages, reactions and new channels arrive.

```dart label="Dart"
final filter = Filter.and([
 Filter.equal('type', 'messaging'),
 Filter.in_('members', ['john']),
]);

final sort = [SortOption<ChannelState>.desc('last_message_at')];

final channels = await client.queryChannels(
 filter: filter,
 channelStateSort: sort,
);
```

To learn more about which fields you can query and sort on have a look at the query channels documentation.

## What's next

Now that you understand the building blocks of a fully functional chat integration, these are good places to go deeper. The [sample chat application](https://github.com/GetStream/flutter-samples/) is a fully-fledged messaging app built from our widgets.

- [Tokens and authentication](https://getstream.io/chat/docs/flutter-dart/tokens-and-authentication/): Generate user tokens on your server and handle expiry and revocation.
- [Querying channels](https://getstream.io/chat/docs/flutter-dart/query-channels/): Filters, sorting and pagination for building channel lists.
- [Channel types](https://getstream.io/chat/docs/flutter-dart/channel-features/): The settings behind each channel type, and how to define your own.

## FAQ

**Can I try it without my own backend?**

Yes. With the app in development mode and _Disable Authentication Checks_ toggled in the dashboard, [developer tokens](https://getstream.io/chat/docs/flutter-dart/tokens-and-authentication/#developer-tokens) let clients connect without a token service.

**How long do tokens last?**

Indefinitely, by default. For expiring tokens, pass a [token provider](https://getstream.io/chat/docs/flutter-dart/tokens-and-authentication/#token-providers) instead of a static string.

**Can users report messages?**

Yes. Any user can flag a message or another user, and flagged content lands in the dashboard review queue. See [moderation](https://getstream.io/chat/docs/flutter-dart/moderation/#flag).

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/flutter-dart/](https://getstream.io/chat/docs/flutter-dart/).