Skip to content

A modern, over-engineered Weather Companion built with Kotlin Multiplatform (Android, iOS, Desktop). Features Clean Architecture, adaptive UI, background notifications, and custom Compose canvas graphs. Powered by Open-Meteo & Nominatim.

License

Notifications You must be signed in to change notification settings

Robert-P-M/Stormbreaker_KMP

Repository files navigation

⚡ Stormbreaker

Kotlin Compose Multiplatform Platforms Architecture License

The "Over-Engineered" Multiplatform Weather Companion.

Der "Over-Engineered" Multiplatform Wetter-Begleiter.

Stormbreaker Tablet Split View


🇬🇧 English

Click here for German / Hier klicken für Deutsch

⚡ Project Overview

Stormbreaker is not just another weather app. It is a showcase of modern Kotlin Multiplatform (KMP) development, pushing the boundaries of code sharing between Android, iOS, and Desktop (JVM).

Built with a strict Clean Architecture, it intentionally leans into "over-engineering" to demonstrate scalability, testability, and the separation of concerns using SOLID, KISS (ironically applied to individual modules), and DRY principles. It leverages Open-Meteo for weather data and Nominatim for geocoding. While favorite locations and user settings are persisted locally for quick access, forecast data is fetched live to ensure maximum accuracy.


📱🖥️ Multiplatform Capabilities

Stormbreaker shares ~90% of its code across platforms, including UI, ViewModels, UseCases, and Data Layers. Platform-specific code is isolated to hardware interactions.

Platform Tech Key Implementation Details
Android Jetpack Compose Uses WorkManager for reliable background updates. Custom BroadcastReceiver handling for alarms and boot events.
iOS Compose Multiplatform Implements native BGTaskScheduler for background fetches. Native CLLocationManager via Kotlin/Native interop.
Desktop (JVM) Compose for Desktop Window management, System Tray integration, and Swing-based interoperability where needed.

✨ Features

Forecast Overview Hourly & Air Quality
Forecast Overview Split Hourly Details Split
14-Day Forecast (Light/Dark Split) Deep Metrics (Light/Dark Split)

🎥 Short Demo (Android)

screen_recording_readme.mp4

  • Smart Forecast System: Combines Open-Meteo weather data with reverse geocoding from Nominatim to provide precise, location-aware forecasts.
  • Adaptive UI: Fully responsive layouts that adapt to mobile, tablet, and desktop window sizes using ListDetailPaneScaffold.

Tablet Details Split View


  • Advanced Metrics:
    • Air Quality: Detailed graphs for PM10, PM2.5, NO2, Ozone, and more.
    • Pollen Breakdown: Specific tracking for Alder, Birch, Grass, Mugwort, Olive, and Ragweed.
    • Sun Curve: Custom Canvas-based visualization of sunrise/sunset and current sun position.
  • Resilient Notifications:
    • Android: Robust alarm scheduling handling BOOT_COMPLETED and SCHEDULE_EXACT_ALARM.
    • iOS: Local notifications triggered via background fetch.
    • Desktop: System tray notifications.
  • Custom Graphing Engine: A bespoke, Bezier-curve based charting solution built entirely in Compose Canvas (no external charting libraries).

🚀 Tech Stack & Architecture

This project follows a strict Multi-Module Clean Architecture.

  • Language: Kotlin 2.0+ (K2 Compiler enabled)
  • UI Framework: Jetpack Compose & Compose Multiplatform
  • Dependency Injection: Koin (utilizing highly granular module definitions).
  • Network: Ktor with Content Negotiation.
  • Database: Room Multiplatform (SQLite) for persisting user favorites and settings.
  • Settings: DataStore Preferences for persistent user configuration.
  • Async: Kotlin Coroutines & Flow.
  • Date/Time: kotlinx-datetime.

The "Over-Engineering" Philosophy

Why simple when you can make it robust?

  • Granular Mappers: Every layer transition (DTO -> Domain -> UI) has dedicated mappers.
  • Interactors: ViewModels do not talk to Repositories directly; they go through Interactors/UseCases to ensure business logic is decoupled.
  • Convention Plugins: Custom Gradle logic defined in build-logic to standardize module configuration.

🛠️ Deep Dive: Implementation Details

🔐 Permission Handling

A custom abstraction layer (AppPermissionService) handles permission logic across platforms:

  • Android: Wraps ActivityResultContracts and handles Rationale UI logic.
  • iOS: Interacts with UNUserNotificationCenter and CLLocationManager authorization status.
  • JVM: Graceful fallbacks (permissions assumed granted or no-op).

📡 API Integration & Fusion

The app combines two distinct APIs:

  1. Nominatim (OSM): For resolving coordinates to human-readable names.
  2. Open-Meteo: For raw weather data.
  • Logic: The MergeFavoriteForecastsUseCase orchestrates these streams, handling bounding box calculations to map generic API results to user-saved favorites efficiently.

🔔 Notification System

  • Android: Implements a double-receiver pattern (DailyForecastRebootReceiver & DailyForecastIntentReceiver) to ensure notifications survive reboots and are delivered exactly on time using AlarmManager.
  • iOS: Uses Kotlin/Native interop to register background tasks that fetch data and trigger local notifications.

🏗️ Setup & Build

Requirements

  • Android Studio Koala or newer / IntelliJ IDEA 2024+
  • JDK 21
  • Xcode 15+ (for iOS target)

Build Steps

  1. Clone: git clone https://github.com/Robert-P-M/Stormbreaker.git
  2. Sync: Let Gradle sync the convention plugins and catalogs.
  3. Run:
    • Select composeApp configuration for Android.
    • Select iosApp for iOS Simulator.
    • Run desktopRun Gradle task for the JVM app.


🇩🇪 Deutsch

Hier klicken für Englisch / Click here for English

⚡ Projektübersicht

Stormbreaker ist nicht nur eine weitere Wetter-App. Es ist eine Demonstration moderner Kotlin Multiplatform (KMP) Entwicklung, welche die Grenzen des Code-Sharings zwischen Android, iOS und Desktop (JVM) ausreizt.

Entwickelt mit einer strikten Clean Architecture, lehnt sich das Projekt bewusst in Richtung "Over-Engineering", um Skalierbarkeit, Testbarkeit und die Trennung von Zuständigkeiten mittels SOLID, KISS (ironisch auf Modulebene angewandt) und DRY Prinzipien zu demonstrieren. Es nutzt Open-Meteo für Wetterdaten und Nominatim für Geocoding. Während favorisierte Orte und Benutzereinstellungen lokal gespeichert werden, um schnellen Zugriff zu ermöglichen, werden Wetterdaten live abgerufen, um höchste Genauigkeit zu garantieren.


📱🖥️ Multiplatform Fähigkeiten

Stormbreaker teilt ~90% des Codes über alle Plattformen hinweg, einschließlich UI, ViewModels, UseCases und Data Layer. Plattformspezifischer Code beschränkt sich auf Hardware-Interaktionen.

Plattform Technologie Wichtige Implementierungsdetails
Android Jetpack Compose Nutzt WorkManager für zuverlässige Hintergrund-Updates. Eigene BroadcastReceiver für Alarme und Boot-Events.
iOS Compose Multiplatform Implementiert nativen BGTaskScheduler für Hintergrundaktualisierungen. Nativer CLLocationManager via Kotlin/Native Interop.
Desktop (JVM) Compose for Desktop Fenstermanagement, System Tray Integration und Swing-basierte Interoperabilität wo nötig.

✨ Funktionen

Vorhersage Übersicht Stündliche Details & AQI
Forecast Overview Split Hourly Details Split
14-Tage Vorschau (Light/Dark Split) Detaillierte Metriken (Light/Dark Split)

🎥 Kurzes Video (Android)

screen_recording_readme.mp4

  • Intelligentes Vorhersagesystem: Kombiniert Open-Meteo Wetterdaten mit Reverse Geocoding von Nominatim für präzise, standortbezogene Vorhersagen.
  • Adaptive UI: Vollständig responsive Layouts, die sich mittels ListDetailPaneScaffold an Smartphone-, Tablet- und Desktop-Fenster anpassen.

Tablet Details Split View


  • Erweiterte Metriken:
    • Luftqualität: Detaillierte Graphen für PM10, PM2.5, NO2, Ozon und mehr.
    • Pollenflug: Spezifisches Tracking für Erle, Birke, Gräser, Beifuß, Olive und Ambrosia.
    • Sonnenkurve: Eigene Canvas-basierte Visualisierung von Sonnenaufgang/-untergang und aktuellem Sonnenstand.
  • Robuste Benachrichtigungen:
    • Android: Zuverlässiges Alarm-Scheduling (behandelt BOOT_COMPLETED & SCHEDULE_EXACT_ALARM).
    • iOS: Lokale Benachrichtigungen, ausgelöst durch Background Fetch.
    • Desktop: System-Tray Benachrichtigungen.
  • Eigene Graphing-Engine: Eine maßgeschneiderte, auf Bezier-Kurven basierende Charting-Lösung, komplett in Compose Canvas entwickelt (keine externen Libraries).

🚀 Tech-Stack & Architektur

Dieses Projekt folgt einer strikten Multi-Module Clean Architecture.

  • Sprache: Kotlin 2.0+ (K2 Compiler aktiviert)
  • UI Framework: Jetpack Compose & Compose Multiplatform
  • Dependency Injection: Koin (nutzt hoch-granulare Moduldefinitionen).
  • Netzwerk: Ktor mit Content Negotiation.
  • Datenbank: Room Multiplatform (SQLite) zur Speicherung von Favoriten und Einstellungen.
  • Settings: DataStore Preferences für persistente Benutzerkonfiguration.
  • Async: Kotlin Coroutines & Flow.
  • Datum/Zeit: kotlinx-datetime.

Die "Over-Engineering" Philosophie

Warum einfach, wenn es auch robust geht?

  • Granulare Mapper: Jeder Schichtübergang (DTO -> Domain -> UI) besitzt dedizierte Mapper.
  • Interactors: ViewModels sprechen nicht direkt mit Repositories; sie nutzen Interactors/UseCases, um die Geschäftslogik zu entkoppeln.
  • Convention Plugins: Eigene Gradle-Logik in build-logic zur Standardisierung der Modulkonfiguration.

🛠️ Deep Dive: Implementierungsdetails

🔐 Berechtigungssteuerung

Eine eigene Abstraktionsschicht (AppPermissionService) steuert die Logik plattformübergreifend:

  • Android: Kapselt ActivityResultContracts und UI-Logik für Erklärungen (Rationale).
  • iOS: Interagiert mit UNUserNotificationCenter und CLLocationManager Status.
  • JVM: Elegante Fallbacks (Berechtigungen werden als gewährt angenommen oder ignoriert).

📡 API Integration & Fusion

Die App kombiniert zwei verschiedene APIs:

  1. Nominatim (OSM): Zur Auflösung von Koordinaten in lesbare Namen.
  2. Open-Meteo: Für Roh-Wetterdaten.
  • Logik: Der MergeFavoriteForecastsUseCase orchestriert diese Datenströme und behandelt Bounding-Box-Berechnungen, um generische API-Ergebnisse effizient den gespeicherten Favoriten zuzuordnen.

🔔 Benachrichtigungssystem

  • Android: Implementiert ein Double-Receiver-Pattern (DailyForecastRebootReceiver & DailyForecastIntentReceiver), um sicherzustellen, dass Benachrichtigungen Neustarts überleben und mittels AlarmManager pünktlich zugestellt werden.
  • iOS: Nutzt Kotlin/Native Interop, um Background Tasks zu registrieren, die Daten abrufen und lokale Benachrichtigungen auslösen.

🏗️ Setup & Build

Voraussetzungen

  • Android Studio Koala oder neuer / IntelliJ IDEA 2024+
  • JDK 21
  • Xcode 15+ (für iOS Target)

Schritte

  1. Klonen: git clone https://github.com/Robert-P-M/Stormbreaker.git
  2. Sync: Lass Gradle die Plugins und Kataloge synchronisieren.
  3. Starten:
    • Wähle die composeApp Konfiguration für Android.
    • Wähle iosApp für den iOS Simulator.
    • Führe den desktopRun Gradle Task für die JVM App aus.

📄 License

MIT License. See LICENSE for details.

Crafted with ❤️ and too much coffee in Tyrol, Austria.

About

A modern, over-engineered Weather Companion built with Kotlin Multiplatform (Android, iOS, Desktop). Features Clean Architecture, adaptive UI, background notifications, and custom Compose canvas graphs. Powered by Open-Meteo & Nominatim.

Topics

Resources

License

Stars

Watchers

Forks