This file provides comprehensive guidance for agentic coding agents working on the Planova Flutter project.
Planova is a Flutter-based personal productivity app that manages todos, agenda, journal, and notes using structured Markdown files. The app follows a clean architecture pattern with Provider state management and supports cross-platform deployment (Android, iOS, Web, Desktop).
flutter pub get # Install dependencies
flutter clean # Clean build cache
flutter pub deps # Show dependency treeflutter analyze # Run static analysis (uses flutter_lints)
flutter format . # Format all Dart files
dart fix --apply # Apply automated fixesflutter test # Run all tests
flutter test test/widget_test.dart # Run single test file
flutter test --name "test_name" # Run tests by name pattern
flutter test --coverage # Run tests with coverage
flutter test --reporter=expanded # Verbose test outputflutter run # Run in debug mode
flutter run --release # Run in release mode
flutter build apk # Build Android APK
flutter build ios # Build iOS app
flutter build web # Build for web
flutter build windows # Build for Windows
flutter build macos # Build for macOS
flutter build linux # Build for LinuxOrganize imports in this specific order:
- Third-party packages (alphabetical)
- Flutter SDK packages (alphabetical)
- Local project imports (alphabetical)
import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:planova/constants/app_constants.dart';
import 'package:planova/models/daily_file.dart';
import 'package:planova/providers/daily_file_provider.dart';
import 'package:planova/utils/logger.dart';- Classes/Enums: PascalCase (
DailyFile,CalendarEvent,LogLevel) - Variables/Methods: camelCase (
selectedDate,loadDailyFiles()) - Files/Directories: snake_case (
daily_file.dart,utils/logger.dart) - Constants:
static constwith descriptive names (widgetUpdateInterval) - Private members: Prefix with underscore (
_dailyFiles,_loadData())
lib/
├── constants/ # App-wide constants and messages
├── models/ # Data models and entities
├── providers/ # State management (Provider pattern)
├── repositories/ # Data access layer
├── screens/ # UI screens/pages
├── services/ # Business logic and external services
├── themes/ # App theming and colors
├── utils/ # Utility classes and helpers
├── widgets/ # Reusable UI components
└── main.dart # App entry point
Use the custom exception hierarchy for consistent error handling:
// Create specific exceptions
throw FileOperationException(
'Failed to save daily file',
filePath: filePath,
details: 'Permission denied or file locked',
originalError: e,
);
// Handle exceptions gracefully
try {
await _saveDailyFile(content);
} catch (e) {
Log.e('Save operation failed', error: e);
rethrow; // Re-throw to let caller handle
}Use structured logging with the Log class:
// Basic logging
Log.d('Debug message'); // Debug
Log.i('Info message'); // Info
Log.w('Warning message'); // Warning
Log.e('Error message', error: e); // Error
// Method tracing
Log.entry('methodName', params: {'id': id});
Log.exit('methodName', result: result);
// Performance logging
Log.performance('databaseQuery', duration);
// Exception logging
Log.exception(customException);
// With context and emojis (following existing pattern)
Log.i('📅 DailyFileProvider: Loading daily files...');
Log.e('❌ StorageService: Failed to initialize', error: e);Follow Provider pattern conventions:
class DailyFileProvider extends ChangeNotifier {
// Private fields
List<DailyFile> _dailyFiles = [];
String _selectedDate = '';
// Public getters (immutable)
List<DailyFile> get dailyFiles => List.unmodifiable(_dailyFiles);
String get selectedDate => _selectedDate;
// Public methods with proper error handling
Future<void> loadDailyFiles() async {
try {
_dailyFiles = await _repository.loadAll();
notifyListeners();
} catch (e) {
Log.e('Failed to load daily files', error: e);
rethrow;
}
}
// Proper disposal
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
}Create immutable models with proper copyWith methods:
class DailyFile {
final String path;
final String date;
final String content;
const DailyFile({
required this.path,
required this.date,
required this.content,
});
DailyFile copyWith({
String? path,
String? date,
String? content,
}) {
return DailyFile(
path: path ?? this.path,
date: date ?? this.date,
content: content ?? this.content,
);
}
// Computed properties with getters
DateTime get dateTime => _parseDate(date);
String get formattedDate => _formatDate(date);
}Follow established testing conventions:
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:planova/services/widget_service.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
setUp(() {
SharedPreferences.setMockInitialValues({});
});
group('WidgetService', () {
test('should update widget with daily file', () async {
// Arrange
final dailyFile = DailyFile(/* ... */);
// Act
await WidgetService.updateWithDailyFile(dailyFile);
// Assert
expect(find.byType(/* ... */), findsOneWidget);
});
});
}- File extension:
.mdfor Markdown files - Date format:
yyyyMMdd(e.g.,20241228) - Directory names from
AppConstants:orgDirName,dailiesDirName,notesDirName
- Use keys from
AppConstantsclass - Don't prefix with
flutter.(handled automatically) - Examples:
themeModeKey,storagePathKey,widgetThemeKey
- Use
AppConstants.defaultDailyTemplatefor new daily files - Follow existing Markdown structure with
##headers
- Before committing: Always run
flutter analyzeand fix any issues - New features: Write tests before or alongside implementation
- Code review: Ensure import order, naming conventions, and error handling
- Performance: Use Log.performance() for tracking operation times
- Consistency: Follow existing patterns and use centralized constants
- Android: Handle permissions properly, check directory access
- iOS: Follow Apple design guidelines for UI components
- Web: Ensure responsive design and proper file handling
- Desktop: Consider window management and platform-specific shortcuts
Remember: This codebase emphasizes structured logging, proper error handling, and clean architecture patterns. Always prioritize maintainability and consistency when making changes.