WhimAway Engineering Docs

Confluence

Internal technical documentation covering architecture decisions, runtime data flow, and development workflows for the WhimAway Android app and backend.

Last updated: March 25, 2026

Overview

WhimAway is an AI-assisted, local-first Android task manager that supports image, voice, and manual task creation.

The UI emits typed actions to a central ViewModel, updates a single UI state model, persists tasks to Room, and syncs changes in the background to Firebase.

  • Photo capture → AI suggests title, details, due date, and subtasks
  • Voice recording → AI transcribes and structures task content
  • Written mode → manual task entry with consistent domain flow

Local writes happen first for responsiveness and resilience. Sync, media upload, and remote reconciliation run asynchronously through WorkManager and sync coordination.

Architecture

Action-driven, layered architecture with local-first persistence and async sync orchestration.

High-level system graph
LayerPrimary Responsibility
PresentationRender state and emit strongly typed actions
State OrchestrationRoute actions, execute use cases, coordinate async work
DomainExpose business operations for create, update, observe, and toggle
DataLocal CRUD, soft delete, sync enqueue, media coordination
SyncRealtime merge plus periodic/one-shot reconciliation to Firebase
AIImage/audio parsing via backend and structured extraction
RemindersDue-date notification scheduling with quick actions

Data Flow

All UI interactions are action-dispatched, persisted locally, then synchronized remotely.

End-to-end CRUD and sync lifecycle
  • Task observation pipeline: Room Flow → ViewModel mapping → UI state emission
  • Realtime merge path: Firestore listener → sync coordinator merge → Room upsert
  • AI parse path: action → coordinator → backend endpoint → structured suggestion state

Task Creation Flows

Three entry modes share a common confirmation and persistence path.

Capture / Voice / Written creation paths
  • Photo flow falls back to editable defaults if parsing fails.
  • Voice recording auto-stops at 60s and keeps manual confirmation controls.
  • Written flow bypasses AI and still follows the same repository and sync path.

Tech Stack

Android-first stack with Firebase services and a FastAPI AI backend.

CategoryTools
AndroidKotlin, Jetpack Compose, Material 3
StateStateFlow, action-driven UI updates
Local StorageRoom
Background JobsWorkManager
BackendFastAPI (Python)
AIOpenAI APIs (backend-only usage)
CloudFirebase Auth, Firestore, Firebase Storage
NetworkingRetrofit + OkHttp
ReliabilityFirebase Crashlytics

Core Architecture Concepts

The app is centered around typed intents, deterministic state, and local-first consistency.

HomeAction as the intent contract

UI layers emit strongly typed actions only. HomeViewModel.onAction() is the single router for behavior.

HomeUiState as single source of truth

MutableStateFlow<HomeUiState> is the only mutable UI state container. Compose screens render by collecting this state stream.

Repository as integration boundary

TaskRepositoryImpl writes locally first, schedules reminders, and delegates sync/upload logic while exposing a stable domain API.

Core action pipelinetext
HomeScreen interaction
→ HomeAction
→ HomeViewModel.onAction()
→ Use Case
→ TaskRepositoryImpl
→ Room write + reminder scheduling
→ Sync enqueue

Notifications

Due-date notifications are WorkManager-backed and include quick actions for completion and snooze.

  • Notification channel is created at app startup and worker execution time.
  • Reminders are scheduled only for active tasks with dueAt timestamps.
  • ReminderWorker publishes high-priority notifications with action intents.
  • Mark Done action updates repository state and enqueues sync.
  • Snooze action shifts due date (10 minutes) and reschedules reminder.
  • Android 13+ notification permission is checked before display.

Project Structure

Codebase is split into Android app modules and backend service with clear layer boundaries.

Repository treetext
app/
  src/main/java/dev/saipranith/toflowai/
    ui/
      screens/
      components/
    domain/
      model/
      repository/
      usecase/
    data/
      datasource/
      repository/
      remote/
      sync/
      reminder/
backend/
  main.py
  requirements.txt

Run Locally

Android app and backend can run independently during development.

Android app

Snippetbash
# Open project in Android Studio
# Ensure app/google-services.json exists
./gradlew.bat :app:assembleDebug

Backend

Snippetbash
cd backend
# create .env with OPENAI_API_KEY=...
pip install -r requirements.txt
uvicorn main:app --reload