Skip to content

Project Structure

Understanding the project structure is crucial for effective development and customization. Lumo follows Flutter best practices with a feature-driven architecture.

lumo/
├── lib/ # Main source code
├── android/ # Android-specific code
├── ios/ # iOS-specific code
├── assets/ # Static assets
├── test/ # Tests
├── docs/ # Documentation (this site)
├── pubspec.yaml # Dependencies and project config
└── README.md # Project overview
lib/
├── main.dart # Application entry point
├── core/ # Core utilities and shared code
│ ├── constants/ # App constants and enums
│ ├── exceptions/ # Custom exception classes
│ ├── extensions/ # Dart extensions
│ ├── theme/ # App theming and colors
│ └── utils/ # Utility functions
├── features/ # Feature-based modules
│ ├── authentication/ # User authentication
│ ├── otp/ # OTP generation and management
│ ├── backup/ # Backup and restore
│ ├── settings/ # App settings
│ └── security/ # Security features
├── shared/ # Shared widgets and components
│ ├── widgets/ # Reusable UI components
│ ├── providers/ # Global state providers
│ └── services/ # Shared services
└── app.dart # App configuration and routing

Each feature follows a consistent structure based on Clean Architecture principles:

features/otp/
├── data/ # Data layer
│ ├── datasources/ # Data sources (local/remote)
│ ├── models/ # Data models
│ └── repositories/ # Repository implementations
├── domain/ # Business logic layer
│ ├── entities/ # Domain entities
│ ├── repositories/ # Repository interfaces
│ └── usecases/ # Business use cases
└── presentation/ # Presentation layer
├── pages/ # UI screens/pages
├── widgets/ # Feature-specific widgets
└── providers/ # State management (Riverpod)

Contains shared utilities and foundational code:

  • constants/: App-wide constants

    • app_constants.dart - General app constants
    • storage_keys.dart - Secure storage keys
    • api_endpoints.dart - API endpoints
  • exceptions/: Custom exception handling

    • app_exceptions.dart - Base exception classes
    • otp_exceptions.dart - OTP-specific exceptions
  • theme/: Application theming

    • app_theme.dart - Theme configuration
    • app_colors.dart - Color definitions
    • text_styles.dart - Typography styles
  • utils/: Utility functions

    • crypto_utils.dart - Encryption utilities
    • otp_utils.dart - OTP generation logic
    • validators.dart - Input validation

The main OTP functionality:

Data Layer:

  • datasources/otp_local_datasource.dart - Local storage operations
  • models/otp_entry_model.dart - OTP data models
  • repositories/otp_repository_impl.dart - Repository implementation

Domain Layer:

  • entities/otp_entry.dart - Core OTP entity
  • repositories/otp_repository.dart - Repository interface
  • usecases/generate_otp.dart - OTP generation use case

Presentation Layer:

  • pages/otp_list_page.dart - Main OTP list screen
  • pages/qr_scanner_page.dart - QR code scanner
  • widgets/otp_tile.dart - Individual OTP display widget
  • providers/otp_provider.dart - State management

User authentication and security:

Key Files:

  • pages/auth_gate.dart - Authentication wrapper
  • pages/biometric_setup_page.dart - Biometric configuration
  • providers/auth_provider.dart - Authentication state
  • services/biometric_service.dart - Biometric authentication

Cloud backup and restore functionality:

Key Files:

  • pages/backup_page.dart - Backup management UI
  • services/firebase_backup_service.dart - Firebase integration
  • models/backup_model.dart - Backup data structure

Shared components across features:

Widgets:

  • custom_button.dart - Standardized buttons
  • loading_overlay.dart - Loading indicators
  • error_dialog.dart - Error display widgets

Services:

  • storage_service.dart - Secure storage wrapper
  • navigation_service.dart - Navigation utilities
android/
├── app/
│ ├── src/main/
│ │ ├── AndroidManifest.xml # App permissions and config
│ │ ├── kotlin/ # Native Android code
│ │ └── res/ # Android resources
│ ├── build.gradle.kts # Build configuration
│ └── google-services.json # Firebase config
└── gradle/ # Gradle wrapper

Important Android Files:

  • AndroidManifest.xml - Permissions, app identity
  • build.gradle.kts - Build settings, signing config
  • MainActivity.kt - Main Android activity
ios/
├── Runner/
│ ├── Info.plist # iOS app configuration
│ ├── GoogleService-Info.plist # Firebase config
│ └── Assets.xcassets/ # iOS app icons
├── Runner.xcodeproj/ # Xcode project
└── Podfile # CocoaPods dependencies

Important iOS Files:

  • Info.plist - App configuration, permissions
  • GoogleService-Info.plist - Firebase configuration
  • Podfile - Native iOS dependencies
assets/
├── icons/ # App icons and UI icons
│ ├── issuers/ # Service provider icons
│ └── ui/ # Interface icons
├── images/ # Static images
├── lottie/ # Lottie animations
└── fonts/ # Custom fonts (if any)

Main project configuration:

  • Dependencies and dev dependencies
  • Asset declarations
  • Flutter and Dart SDK constraints
  • App metadata

Code analysis and linting rules

  • android/app/build.gradle.kts - Android build settings
  • ios/Runner.xcodeproj/ - iOS build settings

Lumo uses Riverpod for state management with a specific pattern:

// Provider definition
final otpListProvider = StateNotifierProvider<OtpListNotifier, List<OtpEntry>>(
(ref) => OtpListNotifier(ref.read(otpRepositoryProvider)),
);
// State notifier
class OtpListNotifier extends StateNotifier<List<OtpEntry>> {
// Implementation
}
// UI consumption
class OtpListPage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final otpList = ref.watch(otpListProvider);
// Build UI
}
}

The app uses named routes with a centralized routing system:

// Route definitions in app.dart
class AppRouter {
static const String home = '/';
static const String scanner = '/scanner';
static const String settings = '/settings';
// ... more routes
}

Lumo uses Realm for local data storage:

@RealmModel()
class _OtpEntry {
@PrimaryKey()
late String id;
late String issuer;
late String account;
late String secret;
// ... more fields
}
test/
├── unit/ # Unit tests
├── widget/ # Widget tests
├── integration/ # Integration tests
└── mocks/ # Mock objects
  1. Repository Pattern: Data access abstraction
  2. Provider Pattern: Dependency injection with Riverpod
  3. Clean Architecture: Separation of concerns
  4. Feature-driven: Modular organization by functionality

When rebranding or customizing:

  1. App Identity: android/app/src/main/AndroidManifest.xml, ios/Runner/Info.plist
  2. Colors & Theme: lib/core/theme/
  3. Icons & Assets: assets/ directory
  4. App Name: pubspec.yaml, platform manifests
  5. Package Name: Platform-specific configuration files

Now that you understand the structure:

  1. Rebranding Overview - Start customizing the app
  2. Development Setup - Learn the development workflow
  3. Architecture Deep Dive - Understand the technical details

The modular structure makes Lumo easy to understand, customize, and extend! 🏗️