Vitu uses Hive, a lightweight NoSQL database for Flutter, to store all user data locally. Data is stored as key-value pairs with values serialized as Dart Maps.
Hive is not a relational database. There are no tables, foreign keys, or SQL queries. All relationships are managed through naming conventions.
Box get _usersBox => Hive.box('users');Box get _userSettingsBox => Hive.box('user_settings');Box get _dailyExerciseBox => Hive.box('daily_exercise');Box get _hydrationLogsBox => Hive.box('hydration_logs');Box get _hydrationSummaryBox => Hive.box('daily_hydration_summary');
class User { final String nombre; final String apellido; final String genero; final int edad; final double altura; // cm final double peso; // kg final String correo; final String contrasena; // simple local final String? brightness; // 'light' | 'dark' final int? seedColor; // ARGB int final String? fontFamily; // null | 'serif' u otras final bool? followLocation;}
class UserSettings { final String userId; final String? brightness; final int? seedColor; final String? fontFamily; final bool? followLocation; final double? metaHydratationMl;}
{userId}_{YYYY-MM-DD} - Sleep data for the night ending on this date
Sleep dates use the date the user woke up, not when they went to bed. A sleep session from 11 PM on March 3 to 7 AM on March 4 is stored under 2026-03-03.
// Get current logged-in user's emailString? getCurrentUserEmail() { final v = _usersBox.get('currentUserEmail'); if (v is String && v.isNotEmpty) return v; return null;}// Get user by emailUser? getUserByEmail(String correo) { final raw = _usersBox.get('user:$correo'); if (raw is Map) return User.fromMap(raw); return null;}// Get current user objectUser? getCurrentUser() { final email = getCurrentUserEmail(); if (email == null) return null; return getUserByEmail(email);}// Save user and set as currentFuture<void> saveCurrentUser(User u) async { await _usersBox.put('user:${u.correo}', u.toMap()); await _usersBox.put('currentUserEmail', u.correo);}// Verify login credentialsbool verifyLogin(String correo, String contrasena) { final u = getUserByEmail(correo.trim().toLowerCase()); if (u == null) return false; return u.contrasena == contrasena;}
final weekly = <double>[];final now = DateTime.now();for (int i = 6; i >= 0; i--) { final d = now.subtract(Duration(days: i)); final key = '${u.correo}_${_dateKey(d)}'; final r = _hydrationSummaryBox.get(key); double t = 0.0; if (r is Map) { t = (r['total_ml'] is double) ? r['total_ml'] : double.tryParse('${r['total_ml'] ?? 0}') ?? 0.0; } final p = ((t / (_goal * 1000.0)) * 100.0).clamp(0.0, 100.0); weekly.add(p);}setState(() { _weeklyPercent = weekly;});
Hive does not have built-in migration support. Schema changes require manual handling.
To add a new field:
// Old schema{'userId': '[email protected]', 'steps': 5000}// New schema (after code update){'userId': '[email protected]', 'steps': 5000, 'distance_km': 0.0}// Reading with fallbackfinal distance = (raw['distance_km'] is double) ? raw['distance_km'] : 0.0; // Default for old data