Skip to content

Development Setup

This guide covers the development workflow, tools, and best practices for working with Lumo.

  1. Start Development Server

    Terminal window
    # Hot reload during development
    flutter run --hot
    # Debug mode with verbose logging
    flutter run --debug --verbose
  2. Code Generation (when needed)

    Terminal window
    # Generate code for Riverpod providers and other code generation
    dart run build_runner build
    # Watch for changes and regenerate automatically
    dart run build_runner watch
  3. Testing

    Terminal window
    # Run unit tests
    flutter test
    # Run widget tests
    flutter test test/widget_test.dart
    # Run integration tests
    flutter test integration_test/

Essential extensions for Lumo development:

.vscode/extensions.json
{
"recommendations": [
"dart-code.flutter",
"dart-code.dart-code",
"ms-vscode.vscode-json",
"bradlc.vscode-tailwindcss",
"esbenp.prettier-vscode",
"ms-vscode.vscode-typescript-next"
]
}
.vscode/settings.json
{
"dart.flutterSdkPath": "",
"dart.lineLength": 100,
"dart.closingLabels": true,
"dart.previewFlutterUiGuides": true,
"dart.previewFlutterUiGuidesCustomTracking": true,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true
},
"files.associations": {
"*.dart": "dart"
}
}
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug App",
"request": "launch",
"type": "dart",
"program": "lib/main.dart",
"args": ["--flavor", "development"]
},
{
"name": "Profile App",
"request": "launch",
"type": "dart",
"flutterMode": "profile",
"program": "lib/main.dart"
},
{
"name": "Release App",
"request": "launch",
"type": "dart",
"flutterMode": "release",
"program": "lib/main.dart"
}
]
}
analysis_options.yaml
include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
- "**/*.g.dart"
- "**/*.freezed.dart"
strong-mode:
implicit-casts: false
implicit-dynamic: false
linter:
rules:
# Dart Style Guide
- always_declare_return_types
- always_put_control_body_on_new_line
- avoid_empty_else
- avoid_relative_lib_imports
- avoid_unnecessary_containers
- prefer_const_constructors
- prefer_const_declarations
- prefer_final_fields
- prefer_final_locals
- use_key_in_widget_constructors
# Security
- avoid_print
- avoid_web_libraries_in_flutter
# Performance
- avoid_function_literals_in_foreach_calls
- prefer_collection_literals
- unnecessary_lambdas
Terminal window
# Format all Dart code
dart format .
# Check formatting without applying changes
dart format --set-exit-if-changed .
# Format specific files
dart format lib/features/otp/

Follow this import order:

// 1. Dart core libraries
import 'dart:async';
import 'dart:convert';
// 2. Flutter libraries
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// 3. Third-party packages
import 'package:riverpod/riverpod.dart';
import 'package:realm/realm.dart';
// 4. App imports (absolute)
import 'package:lumo/core/constants/app_constants.dart';
import 'package:lumo/features/otp/domain/entities/otp_entry.dart';
// 5. Relative imports (if absolutely necessary)
import '../widgets/custom_button.dart';
Terminal window
# Project management
flutter create . # Initialize Flutter project
flutter pub get # Get dependencies
flutter pub upgrade # Upgrade dependencies
flutter pub deps # Show dependency tree
# Development
flutter run # Run app
flutter run --hot # Run with hot reload
flutter run --profile # Run in profile mode
flutter run -d <device-id> # Run on specific device
# Building
flutter build apk --debug # Debug APK
flutter build appbundle --release # Release App Bundle
flutter build ios --release # iOS release build
# Testing
flutter test # Run tests
flutter test --coverage # Run tests with coverage
flutter drive # Run integration tests
# Analysis
flutter analyze # Analyze code
flutter doctor # Check Flutter installation

Create helpful scripts in scripts/ directory:

scripts/dev.sh
#!/bin/bash
echo "Starting Lumo development..."
flutter pub get
dart run build_runner build
flutter run --hot
scripts/test.sh
#!/bin/bash
echo "Running Lumo tests..."
flutter test --coverage
flutter test integration_test/
scripts/build-debug.sh
#!/bin/bash
echo "Building debug version..."
flutter clean
flutter pub get
dart run build_runner build
flutter build apk --debug

Use Flutter Inspector for UI debugging:

  1. Run app in debug mode
  2. Open Flutter Inspector in VS Code or browser
  3. Select widgets to inspect layout and properties
// Use proper logging instead of print statements
import 'package:flutter/foundation.dart';
// Debug logging (removed in release builds)
if (kDebugMode) {
debugPrint('Debug information: $data');
}
// Development assertions
assert(() {
// Validation code that only runs in debug mode
if (someCondition) {
throw FlutterError('Invalid state in development');
}
return true;
}());
// Conditional logging
void log(String message) {
if (kDebugMode) {
debugPrint('[${DateTime.now()}] $message');
}
}
Terminal window
# Profile app performance
flutter run --profile
# Enable performance overlay
flutter run --profile --trace-skia
  • Widget tree modifications
  • Method implementations
  • Variable assignments
  • Adding/removing imports
  • Adding/removing classes
  • Changing class hierarchy
  • Modifying main() function
  • Adding/removing static fields
  • Changing generic type declarations
// Preserve state during hot reload
class _MyWidgetState extends State<MyWidget> {
String _data = '';
@override
void reassemble() {
super.reassemble();
// Code here runs on every hot reload
// Useful for development-only logic
}
}
lib/core/config/dev_config.dart
class DevConfig {
static const bool enableLogging = true;
static const bool enableAnalytics = false;
static const String apiBaseUrl = 'https://api-dev.yourapp.com';
static const String firebaseProjectId = 'your-app-dev';
// Debug-specific features
static const bool showPerformanceOverlay = false;
static const bool showDebugBanner = true;
}
// Different behavior for debug/release
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Lumo'),
actions: [
// Only show debug menu in debug mode
if (kDebugMode)
IconButton(
onPressed: _showDebugMenu,
icon: const Icon(Icons.bug_report),
),
],
),
// ... rest of widget
);
}
Terminal window
# Install Realm Studio for database inspection
# Download from: https://realm.io/realm-studio/
# Connect to local database
# File → Open Realm file
# Navigate to app data directory
// Helper for development database operations
class DatabaseDebugHelper {
static void printAllOtpEntries(Realm realm) {
if (kDebugMode) {
final entries = realm.all<OtpEntrySchema>();
for (final entry in entries) {
debugPrint('OTP Entry: ${entry.issuer} - ${entry.account}');
}
}
}
static void clearAllData(Realm realm) {
if (kDebugMode) {
realm.write(() {
realm.deleteAll<OtpEntrySchema>();
});
debugPrint('All OTP entries cleared');
}
}
}
Terminal window
# Main branches
main # Production-ready code
develop # Integration branch for features
# Feature branches
feature/qr-scanner-improvements
feature/backup-encryption
bugfix/auth-flow-issue
# Release branches
release/1.1.0
hotfix/1.0.1
Terminal window
# Conventional commit format
feat: add QR code scanning for account import
fix: resolve biometric authentication issue
docs: update setup guide with Firebase configuration
style: format code according to Dart style guide
refactor: reorganize OTP generation logic
test: add unit tests for OTP validation
chore: update dependencies to latest versions
# Examples
feat(otp): implement HOTP support
fix(auth): handle biometric unavailable state
docs(readme): add installation instructions
.pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: flutter-analyze
name: Flutter Analyze
entry: flutter analyze
language: system
pass_filenames: false
types: [dart]
- id: flutter-test
name: Flutter Test
entry: flutter test
language: system
pass_filenames: false
types: [dart]
- id: dart-format
name: Dart Format
entry: dart format
language: system
types: [dart]
// Monitor widget rebuild frequency
class PerformanceLogger extends StatelessWidget {
final Widget child;
final String name;
const PerformanceLogger({
super.key,
required this.child,
required this.name,
});
@override
Widget build(BuildContext context) {
if (kDebugMode) {
debugPrint('Building $name at ${DateTime.now()}');
}
return child;
}
}
// Usage
PerformanceLogger(
name: 'OtpListPage',
child: OtpListPage(),
)
// Development memory monitoring
void logMemoryUsage() {
if (kDebugMode) {
// This is a simplified example
debugPrint('Memory usage check at ${DateTime.now()}');
}
}

Once your development environment is set up:

  1. Architecture Overview - Understand the codebase structure
  2. State Management - Learn Riverpod patterns
  3. Testing Guide - Write comprehensive tests

Happy coding! 🚀