A faithful clone of the Google Gemini mobile app, built almost entirely
from the flutter_ai family of
packages. It exists to dogfood those packages — to prove you can build a
real, polished AI app on them with minimal custom code — and doubles as a
worked example of how to wire them together.
- Streaming chat with Markdown rendering and a model picker (Gemini 2.5 Flash / Pro), light + dark themes.
- Signature gradient background that blooms while a response is generating, and an animated, programmatically-drawn Gemini "spark" logo.
- Chat history drawer — create / switch / delete threads, transcript restored on reopen.
- Composer attachments — pick from gallery or camera and send images.
- Per-message actions (copy · feedback · regenerate · read-aloud) and follow-up suggestion chips.
- Live voice mode — on-device speech-to-text in, text-to-speech out, driven
by the package's
AiLiveController.
Nearly all behavior comes from published pub.dev packages — the app is mostly glue and Gemini-specific styling:
| Package | Used for |
|---|---|
flutter_ai_elements |
AiChat, AiPromptInput, AiModelSelector, AiSuggestions, AiLiveSession/AiLiveController, theming via AiThemeExtension |
flutter_ai_client |
UseChatController, ChatThreadStore persistence |
flutter_ai_provider_gemini |
the Gemini backend |
Platform plugins the packages intentionally don't bundle: image_picker
(attachments), speech_to_text + flutter_tts (live voice).
You need your own Gemini API key. The
key is passed at run time via --dart-define and is never stored in source.
flutter pub get
flutter run --dart-define=GEMINI_API_KEY=<your-key>Or copy the helper script and drop your key in (it's gitignored):
cp run-local.sh.example run-local.sh
# edit run-local.sh to add your key, then:
./run-local.sh -d <device>flutter testtest/thread_flow_test.dart is a deterministic thread-lifecycle test against a
fake provider; test/capture_test.dart --update-goldens regenerates the
screenshots in test/shots/.
BSD 3-Clause — see LICENSE.


