Generative AI can be integrated into Flutter applications for chat, summarization, classification, content generation, document processing, and intelligent assistants.
A production application should avoid putting sensitive API credentials directly in the mobile application.
A safer architecture is:
Flutter App
|
| HTTPS
v
Backend API
|
v
Gemini API
|
v
AI Response
Embedding a production AI API key directly in an APK makes it possible for attackers to extract the key.
Instead:
Flutter -> FastAPI/Node/Laravel -> Gemini
The backend can implement:
A simple chat screen can contain:
final controller = TextEditingController();
TextField(
controller: controller,
decoration: const InputDecoration(
hintText: 'Ask something...',
),
)
Send the message through a repository:
class AiRepository {
Future<String> generate(String prompt) async {
// Call your backend here.
throw UnimplementedError();
}
}
A scalable Flutter AI application can use:
Presentation
|
BLoC / Cubit
|
AI Repository
|
API Client
|
Backend
|
Gemini
This makes it possible to replace Gemini later without rewriting the UI.
Install dependencies:
pip install fastapi uvicorn google-genai
Example:
import os
from fastapi import FastAPI
from pydantic import BaseModel
from google import genai
app = FastAPI()
client = genai.Client(
api_key=os.environ["GEMINI_API_KEY"]
)
class ChatRequest(BaseModel):
message: str
@app.post("/chat")
async def chat(request: ChatRequest):
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=request.message,
)
return {"response": response.text}
Keep the API key in an environment variable:
export GEMINI_API_KEY="your-key"
Never commit it to Git.
Using the http
package:
import 'dart:convert';
import 'package:http/http.dart' as http;
class AiApi {
final String baseUrl;
AiApi(this.baseUrl);
Future<String> chat(String message) async {
final response = await http.post(
Uri.parse('$baseUrl/chat'),
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode({
'message': message,
}),
);
if (response.statusCode != 200) {
throw Exception('AI request failed');
}
final data = jsonDecode(response.body);
return data['response'] as String;
}
}
AI requests are asynchronous, so explicitly represent:
Idle
↓
↓
Success
or
↓
Failure
With BLoC:
sealed class AiState {}
class AiInitial extends AiState {}
class Ai extends AiState {}
class AiSuccess extends AiState {
final String response;
AiSuccess(this.response);
}
class AiFailure extends AiState {
final String message;
AiFailure(this.message);
}
Instead of:
Explain this.
Use structured instructions:
You are an assistant for a Flutter developer.
Task:
Explain the following Dart error.
Requirements:
1. Identify the root cause.
2. Provide corrected code.
3. Keep the explanation concise.
Error:
{{error}}
Structured prompts make application behavior more predictable.
For chat applications, streaming can improve perceived responsiveness:
User message
|
v
Backend
|
+---- token
+---- token
+---- token
+---- token
|
Flutter renders progressively
Consider Server-Sent Events or WebSockets depending on your backend architecture.
Never expose:
Add:
Flutter is an excellent client platform for AI applications, but a maintainable architecture separates the UI from the AI provider. A backend gives you control over security, prompts, model selection, cost, and business logic.
SDK Flutter: https://github.com/v-modal/vmodal_sdk_flutter
SDK Android: https://github.com/v-modal/vmodal_sdk_android
Discord: https://discord.gg/K72z28KUx