Version: 1.1.0 Major changes: - Implemented complete Flutter app structure with all core features - Added comprehensive UI screens for auth, countdown, goals, profile, settings, and social features - Integrated Supabase backend with authentication and data repositories - Added offline support with Hive caching and local storage - Implemented comprehensive routing with go_router - Added location services with Google Maps integration - Implemented notifications and home widget support - Added voice recording capabilities and AI chat features - Created comprehensive test suite and documentation - Added Android and iOS platform configurations - Implemented achievements system and social features - Added calendar integration and bucket list functionality This represents a complete Phase 1 milestone with 3,775 additions across 31 files.
13 KiB
LifeTimer - Developer Documentation
Table of Contents
- Project Overview
- Getting Started
- Architecture
- Project Structure
- Development Setup
- Key Components
- State Management
- API Integration
- Testing
- Deployment
- Contributing
Project Overview
LifeTimer is a Flutter-based mobile application that helps users achieve their goals through a focused 1356-day countdown challenge. The app uses Supabase for backend services including authentication, database, storage, and real-time features.
Tech Stack
- Framework: Flutter 3.10+
- Language: Dart 3.0+
- Backend: Supabase (PostgreSQL, Auth, Storage, Realtime)
- State Management: Riverpod
- Navigation: go_router
- Authentication: Email, Google, Apple
- Database: PostgreSQL via Supabase
- Storage: Supabase Storage
- Analytics: Supabase Analytics
- Maps: Google Maps, OpenStreetMap
- Images: Unsplash, Pexels APIs
Getting Started
Prerequisites
- Flutter SDK 3.10 or higher
- Dart SDK 3.0 or higher
- Android Studio or VS Code
- Xcode (for iOS development, macOS only)
- Supabase account
- Google Cloud Console account (for Google Maps)
- Unsplash API key
- Pexels API key
Installation
-
Clone the repository
git clone https://github.com/your-org/lifetimer.git cd lifetimer -
Install dependencies
flutter pub get -
Set up environment variables
cp .env.example .env # Edit .env with your credentials -
Run the app
flutter run
Architecture
LifeTimer follows a Clean Architecture pattern with clear separation of concerns:
Layers
-
Presentation Layer (
lib/features/*/presentation/)- Screens and widgets
- UI components
- User interactions
-
Application Layer (
lib/features/*/application/)- Controllers and view models
- State management
- Business logic
-
Domain Layer (
lib/features/*/domain/)- Entities and value objects
- Business rules
- Use cases
-
Data Layer (
lib/data/)- Models and DTOs
- Repositories
- API clients
- Data sources
Key Principles
- Single Responsibility: Each component has one clear purpose
- Dependency Inversion: Depend on abstractions, not concretions
- Open/Closed: Open for extension, closed for modification
- Interface Segregation: Small, focused interfaces
Project Structure
lib/
├── main.dart # App entry point
├── bootstrap/ # Initialization
│ ├── bootstrap.dart # Bootstrap function
│ ├── supabase_client.dart # Supabase client setup
│ └── env.dart # Environment configuration
├── core/ # Cross-cutting concerns
│ ├── theme/ # App theming
│ ├── routing/ # Navigation
│ ├── widgets/ # Reusable widgets
│ ├── errors/ # Error handling
│ ├── utils/ # Utilities
│ └── services/ # Core services
├── data/ # Data layer
│ ├── models/ # Data models
│ ├── repositories/ # Data repositories
│ ├── services/ # Data services
│ └── providers/ # Dependency providers
└── features/ # Feature modules
├── auth/ # Authentication
├── onboarding/ # Onboarding
├── goals/ # Goals management
├── countdown/ # Countdown feature
├── social/ # Social features
├── profile/ # User profile
├── settings/ # Settings
├── analytics/ # Analytics & insights
└── achievements/ # Achievements system
Development Setup
Environment Configuration
Create a .env file in the project root:
# Supabase
SUPABASE_URL=your_supabase_url
SUPABASE_ANON_KEY=your_supabase_anon_key
# Google Maps (optional)
GOOGLE_MAPS_API_KEY=your_google_maps_key
# Image APIs
UNSPLASH_ACCESS_KEY=your_unsplash_key
PEXELS_API_KEY=your_pexels_key
Supabase Setup
-
Create a Supabase project
- Go to https://supabase.com
- Create a new project
- Get your project URL and anon key
-
Run database migrations
# Apply migrations from supabase/migrations/ -
Configure authentication
- Enable Email auth
- Enable Google OAuth
- Enable Apple OAuth (iOS)
-
Set up storage
- Create storage buckets
- Configure RLS policies
Code Generation
Run code generation for Riverpod providers:
flutter pub run build_runner build --delete-conflicting-outputs
Key Components
Authentication
Location: lib/features/auth/
Components:
AuthGate: Routes based on auth stateSignInScreen: Email/password sign inSignUpScreen: Email/password sign upAuthController: Manages auth state
Usage:
final authController = ref.watch(authControllerProvider);
final user = authController.currentUser;
Goals Management
Location: lib/features/goals/
Components:
GoalsListScreen: Lists all goalsGoalEditScreen: Create/edit goalsGoalDetailScreen: View goal detailsGoalsController: Manages goals state
Usage:
final goalsController = ref.watch(goalsControllerProvider);
final goals = goalsController.goals;
Countdown
Location: lib/features/countdown/
Components:
HomeCountdownScreen: Main countdown displayCountdownController: Manages countdown state
Usage:
final countdownController = ref.watch(countdownControllerProvider);
final remaining = countdownController.remainingTime;
Social Features
Location: lib/features/social/
Components:
SocialFeedScreen: Activity feedLeaderboardsScreen: RankingsPublicProfileScreen: User profilesSocialController: Manages social state
State Management
LifeTimer uses Riverpod for state management.
Providers
StateNotifierProvider (for complex state):
final goalsControllerProvider = StateNotifierProvider<GoalsController, GoalsState>((ref) {
final repository = ref.watch(goalsRepositoryProvider);
final authController = ref.watch(authControllerProvider);
return GoalsController(repository, authController);
});
Provider (for services):
final goalsRepositoryProvider = Provider<GoalsRepository>((ref) {
final client = ref.watch(supabaseClientProvider);
return GoalsRepository(client);
});
Watching State
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.watch(goalsControllerProvider);
return state.isLoading
? LoadingIndicator()
: GoalsList(goals: state.goals);
}
Reading State (without rebuilding)
@override
Widget build(BuildContext context, WidgetRef ref) {
final controller = ref.read(goalsControllerProvider.notifier);
return ElevatedButton(
onPressed: () => controller.loadGoals(),
child: Text('Load Goals'),
);
}
API Integration
Supabase Client
Location: lib/bootstrap/supabase_client.dart
Usage:
import 'package:supabase_flutter/supabase_flutter.dart';
final client = Supabase.instance.client;
// Query data
final response = await client
.from('goals')
.select()
.eq('owner_id', userId);
// Insert data
await client.from('goals').insert(goal.toJson());
// Update data
await client.from('goals').update({'progress': 50}).eq('id', goalId);
Repository Pattern
Example:
class GoalsRepository {
final SupabaseClient _client;
GoalsRepository(this._client);
Future<List<Goal>> getGoals(String userId) async {
final response = await _client
.from('goals')
.select()
.eq('owner_id', userId)
.order('created_at', ascending: false);
return (response as List).map((json) => Goal.fromJson(json)).toList();
}
}
Testing
Unit Tests
Location: test/
Example:
test('should calculate remaining days correctly', () {
final start = DateTime(2026, 1, 1);
final end = DateTime(2029, 9, 17); // 1356 days later
final now = DateTime(2026, 1, 15);
final remaining = end.difference(now).inDays;
expect(remaining, equals(1341));
});
Widget Tests
Example:
testWidgets('should display countdown', (WidgetTester tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
countdownControllerProvider.overrideWith((ref) => mockController),
],
child: MaterialApp(home: HomeCountdownScreen()),
),
);
expect(find.text('Your Journey'), findsOneWidget);
});
Running Tests
# Run all tests
flutter test
# Run with coverage
flutter test --coverage
# Run specific test file
flutter test test/features/countdown/countdown_controller_test.dart
Deployment
iOS Deployment
-
Configure signing
- Open
ios/Runner.xcworkspace - Select your team and bundle identifier
- Configure signing certificates
- Open
-
Build for release
flutter build ios --release -
Upload to App Store Connect
- Use Xcode or Transporter
- Follow App Store submission process
Android Deployment
-
Configure signing
- Create keystore
- Configure
android/key.properties - Update
android/app/build.gradle
-
Build app bundle
flutter build appbundle --release -
Upload to Play Console
- Upload
build/app/outputs/bundle/release/app-release.aab - Follow Play Store submission process
- Upload
Contributing
Code Style
Follow Flutter/Dart style guidelines:
- Use
dart formatto format code - Use
flutter analyzeto check for issues - Follow effective Dart guidelines
Commit Messages
Use conventional commits:
feat: add goal completion celebration
fix: resolve countdown timer not updating
docs: update README with new features
test: add unit tests for goal repository
Pull Request Process
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Update documentation
- Submit a pull request
- Address review feedback
Branch Naming
feature/- New featuresfix/- Bug fixesdocs/- Documentationtest/- Testsrefactor/- Code refactoring
Common Tasks
Adding a New Feature
- Create feature directory:
lib/features/your-feature/ - Add presentation layer:
presentation/your_screen.dart - Add application layer:
application/your_controller.dart - Add repository if needed:
lib/data/repositories/your_repository.dart - Add route:
lib/core/routing/app_router.dart - Write tests:
test/features/your-feature/ - Update documentation
Adding a New Model
- Create model:
lib/data/models/your_model.dart - Add JSON serialization
- Add to repository
- Write tests
- Update documentation
Adding a New Route
- Add route definition in
app_router.dart - Add route to navigation helpers
- Update navigation documentation
- Test navigation flow
Troubleshooting
Build Issues
Problem: Build fails with dependency errors Solution:
flutter clean
flutter pub get
flutter pub upgrade
Problem: iOS build fails Solution:
cd ios
pod install
cd ..
flutter clean
flutter build ios
Runtime Issues
Problem: App crashes on startup Solution:
- Check environment variables
- Verify Supabase configuration
- Check logs in Flutter DevTools
Problem: State not updating Solution:
- Ensure you're using
ref.watch()for state - Check that providers are properly configured
- Verify state mutations are correct
Resources
Documentation
Tools
Community
License
This project is licensed under the MIT License.
Support
For development support:
- GitHub Issues: https://github.com/your-org/lifetimer/issues
- Email: dev@lifetimer.app
- Discord: https://discord.gg/lifetimer
Version: 1.0.0 Last Updated: January 3, 2026