firebase_ai gives a typed Gemini client with Firebase Auth and App Check already in the path. This article turns that observation into a small implementation model you can test, measure, and keep boring when the app grows. The problem in one sentence Client-side Gemini calls with App Check, Auth, and Server Prompt Templates. The useful question is not whether the API or pattern looks elegant in isolation. It is where state lives, which boundary owns failure, and how a user recovers when the happy path disappears. A practical model Server Prompt Templates keep system prompts and tool definitions out of the binary. Start with one explicit owner for the behavior. Keep widgets responsible for rendering and user intent; keep IO, persistence, permissions, and retries behind a small interface. That gives you a seam for a fake in tests and a place to record the facts that matter in production. For a Flutter app, the boundary usually looks like this: The widget emits an intent such as ...