Frosty: a Flutter Twitch client built around third party emote support
A mobile Twitch client for iOS and Android with 7TV, BetterTTV (BTTV), and FrankerFaceZ (FFZ) support.
At a glance
- What is it?
- Frosty is a mobile Twitch client for iOS and Android written in Dart and Flutter, and its entire reason to exist is that the official app renders emote text names instead of the images, which makes chat unreadable in the many channels that rely on 7TV, BetterTTV or FrankerFaceZ. The repository is AGPL-3.0, uses MobX for state, and ships on both app stores.
- Who is it for?
- Frosty fits a Twitch viewer on mobile who reads chat in channels full of third party emotes and who is willing to install a third party app rather than use the official client.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly Dart, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem, which is a rendering bug that makes chat unusable
Frosty is a mobile Twitch client for iOS and Android with 7TV, BetterTTV and FrankerFaceZ support, and the Why section explains the motivation in one paragraph.
The official Twitch mobile app does not support emotes from 7TV, BetterTTV and FrankerFaceZ, which are third party extensions for Twitch used by millions. As a result, only emote text names are rendered rather than their actual image or GIF, making the chat unreadable in many channels.
That is a precise problem statement, and it explains the shape of the project. This is not a Twitch client trying to be a better streaming app. It is a client that fixes one specific and very common failure, and everything else in the feature list is in service of the same thing: a readable chat next to a stream on a phone.
The consequence for a user is worth stating plainly. Installing a third party client to watch Twitch means the application holds your Twitch credentials, and the emote support that justifies it comes from three separate third party services, each of which has to be integrated. The AGPL-3.0 licence is the cost side of that trade, and it is the licence a reader will find on the LICENSE file in the repository root.
The distribution is normal for a mobile app. The download section links to the Apple App Store entry for Frosty for Twitch, and to the Google Play listing under the package name com.tommychow.frosty. The homepage is frostyapp.io, which also carries a more detailed overview of the features than the README does.
The primary language is Dart, the default branch is main, and the repository is not archived with the last push on 2026-10-07. The recent releases are v5.2.0 on 2026-08-16, v5.1.0 on 2026-06-14 and v5.0.5 on 2026-01-09, so the project is on a 5.x line with regular releases. The topic tags describe the stack accurately: flutter, dart, mobx, firebase, fastlane, github-actions, ios, android, frontend and vscode, plus chat, irc, stream, video and the chat application tag.
The feature list, read as the parts of the official app it replaces
The feature list is short, and reading it against the official client shows what a replacement has to cover.
Support for 7TV, BetterTTV and FrankerFaceZ emotes and badges is the first entry, and the word badges matters as much as emotes. A channel with 7TV has not just custom emotes but subscriber and role badges, and a chat without badges loses the information about who is speaking.
The rest is the standard surface of a Twitch client, and it is the right list for judging whether the app is usable in place of the official one. Browse followed streams, top streams and top categories. Search for channels and categories. Watch live streams with chat. See and filter chatters in a channel, which is a moderation-adjacent feature that also serves as a way to find a person in a busy chat.
Then the quality of life items that a mobile client genuinely needs. Autocomplete for emotes and user mentions, so you can type a name without remembering the exact spelling. Local chat user message history, so your own messages in a channel are still there when you come back. An emote menu for picking from what the channel is using. Theater and fullscreen mode and picture-in-picture mode, which are the three video presentation modes a phone user switches between. A sleep timer, which is the one everybody adds after the first time they fall asleep watching a stream. Block and report users, which is a moderation control that has to exist in any client with a chat. And light, dark and black themes, where the black theme is for OLED screens, which on a phone is a battery characteristic rather than a preference.
The ordering of the list is a small tell. The emote support is first because it is the reason the project exists, and the video modes are near the end because they are table stakes. The feature list closes with And more..., and the more detailed overview is on frostyapp.io.
One entry is worth pausing on. The topics include irc, which is the protocol Twitch chat actually uses. A modern client might be expected to use a gateway or a websocket, and the presence of irc in the topics suggests the chat connection is a direct IRC session rather than something built on Twitch's newer chat gateway, which is a deliberate choice with real trade-offs around third party message and moderation events.
Development setup, and the MobX trap
The development setup is seven steps, and the parts that would actually stop you are the third and the seventh.
First, install Flutter. Second, clone the repository, with git clone https://github.com/tommyxchow/frosty.git as the example. Third, go to the Twitch dev console and register a new application to retrieve a client id and a client secret. Fourth, copy .env.example to .env and fill in the credentials, which is just:
cp .env.example .envThe .env.example in the repository is two lines, CLIENT_ID= and SECRET=, so the whole credential set for a local build is those two values. And that is also the whole credential set for a shipped build, which is worth pausing on: the application talks to Twitch with a client id and secret, and a user logs in with their own account through the same path.
Fifth, run flutter pub get to fetch the dependencies. Sixth, choose an emulator or device and run the app, and the included VS Code launch configurations automatically read your .env file, which is a small convenience that removes a whole class of local setup confusion.
Seventh, optionally, run dart run scripts/get_twitch_token.dart to quickly get a user auth token, and then long-press the Anonymous account tile in the app to log in.
The Anonymous account tile is a detail worth understanding. It means the application can be used before you sign in, and the long-press is where you supply credentials. So the flow is: install, browse, and sign in only when you want your own identity in chat, which is also why the token script is optional.
Then the important warning, marked as important in the documentation. Frosty uses MobX for state management, and you are told to refer to the documentation about code generation, otherwise your changes within MobX stores may not be applied.
That is a real trap for a contributor and it is the kind of thing that wastes an afternoon. MobX is a state management library where the observable state is usually written through generated code, and if you skip the code generation step your edits to a store simply do not take effect at run time, with no compile error to tell you. The topic tags confirm mobx is a dependency of the frontend, and the lib/ directory at the top level is where the stores live.
The repository layout backs this up as a Flutter project with the usual platform directories. There is android/, ios/ and web/ for the platform targets, lib/ for the Dart source, assets/ for bundled files, test/ for the tests, docs/ for the documentation, scripts/ for the helper scripts, and pubspec.yaml with pubspec.lock for the dependency manifest. There is also a firebase.json, a .mcp.json, an analysis_options.yaml for the Dart linter configuration, and a .vscode/ directory.
What the emote services actually mean for the user
There is a practical consequence to the emote support that is worth spelling out, because it changes the character of the application rather than just adding a feature to it.
The chat in Frosty is not text. It is a stream of image and GIF requests to four services: Twitch's own, plus 7TV, BetterTTV and FrankerFaceZ. Every emote in a busy channel is a network fetch and a decode, on a phone, on a mobile connection, while a video stream is also running. The official app makes one request for the chat text; Frosty makes many.
That is why the picture-in-picture mode and the sleep timer are on the feature list rather than treated as extras. A client that is doing real work in the background alongside a video stream needs to be considerate of the battery, and the sleep timer is the acknowledgement of that. The three themes, light, dark and black for OLED screens, are the same consideration applied to the display.
The dependency on the three third party services is also not something the user installs or configures. A channel has emote support from whichever extensions its moderators have enabled, and the channels where Frosty is worth installing are the ones with extensions on. A channel with none enabled looks the same in either app, which is a useful thing to know before switching.
The picture-in-picture mode deserves a specific mention, because on mobile it is the mode you actually use. Reading chat while the video is in a small floating window over another app is the arrangement most people end up in, and the app supports the three video presentation modes a phone user switches between: theater, fullscreen and picture-in-picture.
So the honest characterisation is that Frosty is a heavier client than the official app, and it trades weight for a readable chat. For a viewer who reads chat in emote-heavy channels that is a good trade, and for a viewer who does not, it is not, which is why the app supports an anonymous account tile and lets you browse before signing in.
The offline and network behaviour of the emote fetches is not described in the documentation, so how gracefully the app degrades when an emote service is unreachable is something you would have to observe rather than read.
What the AGPL licence means here, and what to check in the app
The licence is the one thing in this repository that changes what a user can do rather than what a developer can build, so it is worth being precise about.
Frosty is licensed under AGPL-3.0-or-later, and the LICENSE file is at the repository root.
AGPL is the network-facing relative of the GPL. Its practical effect on a mobile app is that a user who receives a modified build of the app has a right to the corresponding source. For a personal build on your own phone that is academic, but for anyone who distributes a Frosty build, whether as a fork, a repackaged APK or a themed variant, the source of that modification has to be offered. That is a materially different constraint from the MIT or Apache terms a client like this might otherwise carry, and it is a genuine consideration for anyone who wanted to contribute a feature and then ship their own build.
The other thing worth checking in the app is narrower and more practical. The whole premise of the project is that the chat is rendered with images and GIFs fetched from three separate emote services, 7TV, BetterTTV and FrankerFaceZ, plus Twitch's own emotes and badges. So a Frosty user is making requests to four services from their phone while watching a stream, and the app's data use and its battery use are both higher than the official client's, which renders only text.
That is a direct consequence of the feature, not a flaw, and it is the trade the user makes. The official app shows you a wall of KEWB and KYPER; Frosty shows you the pictures. Anyone who does not read chat in emote-heavy channels has no reason to switch, and the ones who do are accepting a heavier client for a readable chat.
The supporting services are also a dependency the user does not install. Each of 7TV, BTTV and FFZ is a separate third party with its own availability, and the app's emote support for a given channel depends on which of them the channel's moderators have enabled. A channel with no extensions enabled looks the same in both apps.
For a developer evaluating a contribution, the practical checks are the same ones the documentation gives. You need your own Twitch application, you need to run the code generation for MobX, and you need to accept that the licence obliges you to share source for a distributed build. The app is on both app stores, so the fastest way to understand its current behaviour is to install it.
Editorial conclusion
Frosty fits a Twitch viewer on mobile who reads chat in channels full of third party emotes and who is willing to install a third party app rather than use the official client. It is the wrong choice if you need the official client's guarantees around account security and official support, since it is a third party app talking to the Twitch API with your own credentials, and it is the wrong choice if you want to contribute features, because the AGPL-3.0 licence means a modified build has to be shared. Before building it, register an application in the Twitch developer console for a client id and secret, copy .env.example to .env, and read the MobX code generation note, since changes inside MobX stores are not applied if you skip it.
Frequently asked questions
Why does Frosty exist as a separate Twitch app?
Because the official Twitch mobile app does not support emotes from 7TV, BetterTTV and FrankerFaceZ, so only emote text names are rendered rather than their actual image or GIF, which makes the chat unreadable in many channels. Frosty is a third party client for people who read chat in emote-heavy channels.
How do I set up Frosty for development?
Install Flutter, clone the repository, register an application in the Twitch dev console to get a client id and secret, copy .env.example to .env and fill in the values, run flutter pub get, then run the app on an emulator or device. The included VS Code launch configurations read the .env file automatically, and dart run scripts/get_twitch_token.dart optionally gets a user auth token.
What state management does Frosty use and what is the gotcha?
MobX, and the gotcha is code generation. The documentation warns that if you do not refer to the code generation documentation, your changes within MobX stores may not be applied, so the build has to run the generator or the edits to a store silently have no effect.
What licence is Frosty released under?
AGPL-3.0-or-later, with the LICENSE file at the repository root. That matters for anyone distributing a modified build, since the corresponding source has to be offered to the users of that build.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tommyxchow-frosty)Was this useful?