explaingit

anshikadixit/cheerup

0DartAudience · developerComplexity · 3/5ActiveSetup · moderate

TLDR

Flutter chat app with a FastAPI back end that streams replies token by token from a Claude model on OpenRouter for an empathetic chatbot persona.

Mindmap

mindmap
  root((CheerUp))
    Inputs
      User chat message
      Conversation history
    Outputs
      Streamed tokens
      Saved messages
      SSE events
    Use Cases
      Build an empathetic chatbot
      Learn SSE streaming
      Hide API key behind FastAPI
    Tech Stack
      Flutter
      Dart
      FastAPI
      Python
      OpenRouter

Things people build with this

USE CASE 1

Use as a starter for a Flutter chat app with token-by-token streaming

USE CASE 2

Learn how to bridge Server-Sent Events from FastAPI into Flutter via the Dio HTTP client

USE CASE 3

Front a Claude-on-OpenRouter chatbot with a FastAPI proxy so the API key stays off the device

USE CASE 4

Swap the empathetic persona system prompt for your own character and ship a different chatbot

Tech stack

FlutterDartFastAPIPythonOpenRouter

Getting it running

Difficulty · moderate Time to first run · 30min

Need an OpenRouter API key plus a Python venv for the back end and the correct localhost host depending on emulator or web target.

In plain English

CheerUp is a small AI chat app that pairs a mobile front end with a Python back end. The mobile app is built in Flutter, the back end is a FastAPI service in Python, and the AI itself is a Claude model accessed through OpenRouter. The character of the chatbot is called CheerUp, an empathetic comfort buddy that listens, validates feelings, and gently encourages the user. That persona is set by a system prompt held on the back end. The main thing the README focuses on is how replies stream into the screen one word at a time, the way ChatGPT does. Without streaming, the user would wait five to ten seconds for the AI to finish before seeing anything. The author chose Server-Sent Events, a one-way HTTP push protocol, so each token can appear as soon as it is generated. The README contrasts this with WebSockets, which allow two-way traffic but are heavier to set up, and notes that one-way streaming is enough here. The data flow is laid out step by step. The user types a message, the Flutter ChatProvider calls a ChatService that uses the Dio HTTP library to POST to the FastAPI endpoint at /chat/stream. FastAPI calls OpenRouter with streaming enabled, forwards each token as an SSE event back to Flutter, and the Flutter side appends every token to a buffer that the UI rebuilds in real time. When a final [DONE] event arrives, the assembled text is saved as a Message object in the chat history. The rest of the README is a tour of design choices presented in interview-style notes. FastAPI sits in the middle so the OpenRouter API key never lives inside the mobile app, and so future server-side logic such as rate limiting or auth can be added without touching the client. State uses the Provider package rather than BLoC or Riverpod, the back end retries calls with exponential backoff and jitter, the full conversation history is resent on each request, and Pydantic schemas validate request and response bodies. The README also lists how to run both pieces. The back end is a Python virtual environment with requirements installed from pip, then started with run.py on port 8000. The Flutter app uses different localhost addresses depending on whether it runs on an Android emulator, iOS, or web.

Copy-paste prompts

Prompt 1
Set up the CheerUp FastAPI back end with my OpenRouter key and run it locally on port 8000
Prompt 2
Point the Flutter app at the right localhost address for Android emulator, iOS, and web targets
Prompt 3
Replace the empathetic CheerUp system prompt with a study-coach persona and keep the streaming behavior
Prompt 4
Add per-user rate limiting in the FastAPI layer before the OpenRouter call
Prompt 5
Switch the streaming transport from SSE to WebSockets in this repo and update the Flutter client
Open on GitHub → Explain another repo

Generated 2026-05-22 · Model: sonnet-4-6 · Verify against the repo before relying on details.