


Reflection is our AI-powered journaling app designed to help users gain deeper insights into their thoughts and experiences. When we set out to build Reflection, we faced a compelling challenge: how could we transform the traditional journaling experience by making AI interactions both insightful and seamless? Our users wanted to gain deeper understanding from their journal entries without sacrificing privacy or performance.
Our solution: Integrate Google Gemini using Vertex AI in Firebase and Flutter and to create a secure journaling experience that delivers meaningful personalized insights with millisecond response times.
We started by creating an AI-enhanced editor where users can write entries and receive thoughtful questions, guidance, or feedback to help them explore their thoughts more deeply.

After exploring several approaches, we found that Vertex AI in Firebase provided the ideal combination of performance, security, and ease of integration for our Flutter app.
[User Device: Flutter App]
|
v
[Firebase App Check] <---+
| |
v |
[Firebase Remote Config] |
| |
v |
[Depth Service] |
| |
v |
[Vertex AI in Firebase]--+
|
v
[AI Response to User]Our current architecture leverages Flutter and Firebase's ecosystem:
• Flutter App: Multi-platform UI built with Flutter
• Firebase App Check: Security layer ensuring only legitimate clients access our AI
• Firebase Remote Config: Dynamic management of prompts and AI settings
• Vertex AI in Firebase: Secure, server-side AI processing with Gemini models
• Depth Service: Core service managing AI interactions and context
Security was a top priority. App Check ensures that only verified clients can access our Vertex AI resources.
1. Add Firebase dependencies
dependencies:
firebase_app_check: latest_version2. Initialize Firebase and App Check
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: firebaseOptions());
await setFirebaseAppCheck();
runApp(MyApp());
}3. Configure App Check for different environments
Future setFirebaseAppCheck() async {
try {
if (kDebugMode) {
await FirebaseAppCheck.instance.activate(
webProvider: ReCaptchaV3Provider('Your_Recaptcha_Key'),
androidProvider: AndroidProvider.debug,
appleProvider: AppleProvider.debug,
);
_log.d('Activated FirebaseAppCheck in debug mode');
return;
}
await FirebaseAppCheck.instance.activate(
webProvider: ReCaptchaV3Provider('Your_Recaptcha_Key'),
androidProvider: AndroidProvider.playIntegrity,
appleProvider: AppleProvider.appAttest,
);
_log.i('FirebaseAppCheck activated');
} catch (e, s) {
_log.e('Error activating FirebaseAppCheck', error: e, stackTrace: s);
}
}We initially encountered an issue where App Check showed 0% verified requests. After consulting with Firebase support, we discovered a critical step was missing: connecting App Check to the Vertex AI model instance.
// The correct way to initialize Vertex AI with App Check
final model = FirebaseVertexAI.instanceFor(appCheck: FirebaseAppCheck.instance)
.generativeModel(model: 'YOUR_MODEL');This small but crucial detail was the key to making our security layer work properly. You can find more details in this Firebase user voice thread.
We expanded our AI capabilities into search to support natural language search, allowing users to ask questions about past entries in conversational language. For example, users can ask "Where did I go on vacation last summer?" or “What are my self-limiting beliefs?” and get relevant insights and source entries from their journal history.

We use Firebase Remote Config to adjust AI behavior without app updates. This allows us to:
• Switch between AI models (Gemini 1.5 Pro, Gemini 2.0 Flash, etc.)
• Update system prompts and templates
• Adjust temperature and other generation parameters
Firebase Remote Config dashboard for AI settings
Our configuration structure:
{
"ai_config": {
"provider": "gemini",
"model": "gemini-2.0-flash",
"temperature": 0.7,
"maxTokens": 999999,
"maxInputSize": 2000000,
"minInputSize": 10,
"safetySettings": {}
},
"ai_system_prompt": "You are a helpful journaling sidekick.",
"ai_entry_prompt_template": "...",
"ai_journal_search_prompt_template": "...",
"ai_today_page_personalized_prompt_template": "..."
}class GeminiService {
final _log = getLogger('GeminiService');
late final GenerativeModel _model;
void initializeGemini(AIConfig config) {
try {
_model = FirebaseVertexAI.instanceFor(appCheck: FirebaseAppCheck.instance).generativeModel(
model: config.model,
generationConfig: getGenerationConfig(config),
safetySettings: getSafetySettings(config),
);
_log.i('Gemini service initialized successfully');
} catch (e, s) {
_log.e('Failed to initialize Gemini: Error: $e, StackTrace: $s');
}
}
}To achieve our fast response times, we implemented several optimization strategies:
// Example of streaming implementation
Future<void> streamResponse(String prompt) async {
final content = [Content.text(prompt)];
try {
final stream = _model.generateContentStream(content);
await for (final response in stream) {
// Process and display each chunk as it arrives
final text = response.text;
if (text != null) {
_updateMarkdownUI(text);
}
}
} catch (e) {
_log.e('Error streaming response: $e');
rethrow;
}
}For developers looking to implement similar functionality, here's a simplified guide:
1. Set up Firebase in your Flutter project
▪ Install the FlutterFire CLI:
dart pub global activate flutterfire_cli▪ Configure Firebase:
flutterfire configure2. Add the necessary dependencies
In the terminal, run:
flutter pub add firebase_core firebase_app_check firebase_remote_config firebase_vertex_aidependencies:
firebase_core: latest_version
firebase_app_check: latest_version
firebase_remote_config: latest_version
firebase_vertex_ai: latest_version3. Enable Vertex AI in Firebase Console
▪ Navigate to the Firebase Console
▪ Select your project
▪ Go to Product Categories > AI > Vertex AI in Firebase
▪ Enable the service and select your preferred models
4. Implement App Check
▪ Follow our implementation example above
▪ Don't forget to connect App Check to your Vertex AI instance!
5. Create your AI service layer
▪ Implement a service class similar to our GeminiService
▪ Use dependency injection for easier testing and maintenance
Here is a quick video showing the new AI implementation in app:
Experience Reflection’s new AI implementation on our Flutter-powered, fully native apps live today on iOS, Android, MacOS, and Web.
Our journey with Vertex AI in Firebase taught us several valuable lessons:
The integration of Vertex AI in Firebase has transformed our user experience. Our users don't know or care that we moved our AI integration from server-side to client, implemented response caching, or managed prompts with Remote Config. What they do care about is speed, quality of responses, and data security. With this latest release, users have been loving the changes - we’ve heard it directly from our users and are also seeing it in the user adoption numbers.

Integrating Vertex AI in Firebase with Flutter has been transformative for Reflection. The combination of Flutter's multi-platform capabilities and Firebase's secure, scalable AI infrastructure has allowed us to deliver a truly modern journaling experience.
We're grateful to the Firebase and Flutter teams for creating tools that enable small development teams like ours to build sophisticated AI-powered applications. As these technologies continue to evolve, we're excited to push the boundaries of what's possible in personal journaling and self-reflection.
While today's experience revolves around text, our next big release will expand beyond that. First voice based journaling, and beyond that live conversational experience using Gemini’s (newly announced!) Live API. We are excited to share our journey working with it once we finish building!
Try Reflection today and experience the power of Flutter, Firebase and Vertex AI — we can’t wait to hear what you think!
Written by Isaac Adariku, Lead Flutter Developer at Reflection.