RainVu is a modern Flutter app for farmers, gardeners, and weather enthusiasts to meticulously log rainfall from multiple custom gauges. It transforms raw data into actionable insights through powerful charts and historical analysis, all while keeping user data private and on-device.
-
π Data Logging & Management:
- Quickly log rainfall entries with amount, date, and associated gauge.
- Add, edit, and manage multiple custom rain gauges.
- View all historical entries in a clean, organized list.
-
π Powerful Analytics & Insights:
- Visualize data with charts for Month-to-Date (MTD) and Year-to-Date (YTD) totals.
- Analyze monthly trends, seasonal patterns, and year-over-year comparisons.
- Dive deep into daily breakdowns for any given month.
-
π Data Portability:
- Export all your data to CSV or JSON formats for backup or external analysis.
- Import data from a previously exported file to restore or merge records.
-
π Secure & Private:
- All rainfall data is stored securely and locally on the user's device using a relational database.
- No cloud account or internet connection is required for core functionality.
This project is built with a modern, scalable Flutter stack emphasizing type-safety, code generation, and a feature-first architecture with distinct environments for development and production.
- Framework: Flutter & Dart
- State Management: Riverpod with
riverpod_generatorfor compile-safe providers. - Routing: GoRouter with
go_router_builderfor type-safe, declarative navigation. - Local Storage:
- Drift (Moor): For reactive, persistent storage of relational data (gauges, entries).
- shared_preferences: For simple key-value storage of user settings.
- Telemetry:
- Firebase Analytics: For anonymized usage metrics.
- Firebase Crashlytics: For crash reporting.
- Data Models:
freezedfor immutable data classes and unions. - UI & Visualization:
fl_chartfor creating beautiful and interactive charts.flutter_animatefor declarative and easy-to-use animations.
json_serializable: For robust JSON serialization/deserialization.intl: For internationalization and date/number formatting.file_picker&url_launcher: For file system and external link interactions.build_runner: To run all code generation tasks.
flutter_lintsandriverpod_lintare used with a strict ruleset inanalysis_options.yamlto maintain code quality and consistency.
The codebase follows a feature-first architecture and uses separate entry points for different build environments (flavors).
lib/
βββ core/
β βββ data/ # Shared data sources (Drift DB, SharedPreferences)
β βββ navigation/ # GoRouter configuration and routes
β βββ ui/ # App-wide UI (themes, navigation shell)
β βββ utils/ # Shared utilities and extensions
β
βββ features/
β βββ [feature_name]/
β β βββ application/ # Business logic & Riverpod providers
β β βββ data/ # Feature-specific repositories
β β βββ domain/ # Models and entities (often with Freezed)
β β βββ presentation/ # UI (screens, widgets)
β βββ ...
β
βββ shared/
β βββ domain/ # Domain models shared across multiple features
β βββ widgets/ # Reusable widgets (buttons, dialogs, etc.)
β
βββ main_common.dart # Shared app initialization logic
βββ main_dev.dart # Entry point for the 'dev' flavor
βββ main_prod.dart # Entry point for the 'prod' flavor
Follow these instructions to set up the project for local development.
- Flutter SDK (version specified in
pubspec.yaml) - An IDE like Android Studio or VS Code
- An Android Emulator or physical device
- An iOS Simulator or physical device (requires macOS with Xcode)
- Firebase CLI installed and
authenticated (
firebase login). - Java Development Kit (JDK) to use
keytool.
-
Clone the repository:
git clone https://github.com/astraen-dev/RainVu.git cd RainVu -
Install dependencies:
flutter pub get
-
Set up Firebase: This project uses Firebase for Analytics and Crashlytics, configured separately for
devandprodenvironments (flavors). To run the app, you must set up your own Firebase projects.- Create two Firebase projects in the Firebase Console:
one for development (e.g.,
my-rainvu-dev) and one for production (e.g.,my-rainvu-prod). - Enable Analytics and Crashlytics in both projects.
- For each project, register an Android and an iOS app, making sure to use the correct
package/bundle IDs:
- Development:
com.astraen.rainvu.dev(for both iOS and Android) - Production:
com.astraen.rainvu(for both iOS and Android)
- Development:
- Run the
flutterfire configurecommands below, replacing the--projectvalue with your own Firebase project IDs. This will generate the necessaryfirebase_options_*.dartfiles and native configuration files.
Configure Development Firebase:
flutterfire configure \ --project=<YOUR_DEV_PROJECT_ID> \ --out=lib/firebase_options_dev.dart \ --ios-bundle-id=com.astraen.rainvu.dev \ --android-package-name=com.astraen.rainvu.dev \ --ios-out=ios/Runner/Firebase/dev/GoogleService-Info.plist \ --android-out=android/app/src/dev/google-services.json
Configure Production Firebase:
flutterfire configure \ --project=<YOUR_PROD_PROJECT_ID> \ --out=lib/firebase_options_prod.dart \ --ios-bundle-id=com.astraen.rainvu \ --android-package-name=com.astraen.rainvu \ --ios-out=ios/Runner/Firebase/prod/GoogleService-Info.plist \ --android-out=android/app/src/prod/google-services.json
- Create two Firebase projects in the Firebase Console:
one for development (e.g.,
-
Set up Android App Signing: To build a release version of the Android app, you need to configure an upload keystore.
-
Generate an Upload Keystore: If you don't have one, create a keystore using the following
keytoolcommand. It will prompt you for passwords and other information. Remember the passwords you choose.keytool -genkey -v -keystore upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
-
Move the Keystore: Place the generated
upload-keystore.jksfile inside theandroid/directory of the project. -
Configure Signing Properties: In the
android/directory, you will find a template file namedkey.properties.example.- Create a copy of this file and rename it to
key.properties. - Open
key.propertiesand fill in the passwords and alias you chose when generating the keystore.
Note: The
key.propertiesfile is already listed in.gitignoreand must never be committed to version control. - Create a copy of this file and rename it to
-
-
Run code generation: This project heavily relies on code generation. Run
build_runnerto generate the necessary files:dart run build_runner build --delete-conflicting-outputs
The app is configured with two environments, called "flavors": dev and prod. You must specify
which flavor you want to run or build.
Ensure an emulator/simulator is running or a device is connected.
-
To run the
devflavor: This version connects to your development Firebase project, has a.devsuffix in its application ID, and displays a "DEBUG" banner.flutter run --flavor dev -t lib/main_dev.dart
-
To run the
prodflavor: This version connects to your production Firebase project and behaves as the release version would.flutter run --flavor prod -t lib/main_prod.dart
- To build an Android App Bundle for production:
After completing the app signing setup, run:
flutter build appbundle --flavor prod -t lib/main_prod.dart
- To build an iOS App for production:
flutter build ipa --flavor prod -t lib/main_prod.dart
If you modify any file that uses code generation (e.g., Riverpod providers, Freezed models, Drift
tables), you must re-run build_runner. For continuous development, use the watch command:
dart run build_runner watch --delete-conflicting-outputsThis will automatically regenerate files whenever you save a change.
The localization workflow involves several steps to keep the app_en.arb file clean and up-to-date.
- Remove unused keys (Optional):
dart pub global run remove_unused_localizations_keys
- Sort keys and generate metadata (Optional):
arb_utils generate-meta lib/l10n/app_en.arb arb_utils sort lib/l10n/app_en.arb
- Generate Dart localization files:
flutter gen-l10n
This project uses dart_pubspec_licenses to generate a list of open-source licenses for display
within the app. After adding or updating packages, run the following command:
dart run dart_pubspec_licenses:generateThis project is licensed under the MIT License. See the LICENSE file for details.