Expert guidance for building a Flutter expense tracker with ML-powered categorization using Supabase and pgvector embeddings
Expert guidance for developing and maintaining a Flutter expense tracker application with ML-powered transaction categorization.
This Flutter application follows **Clean Architecture** with three distinct layers:
Each feature module follows this pattern:
```
feature_name/
├── data/ # Models, datasources, repository implementations
├── domain/ # Entities, use cases, repository interfaces
└── presentation/ # BLoC/Cubit, pages, widgets
```
When setting up the development environment:
1. Ensure `.env.example` exists with template:
```bash
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key-here
```
2. Create `.env` from example:
```bash
cp .env.example .env
```
3. Add actual Supabase credentials to `.env`
4. Run initial setup:
```bash
flutter pub get
flutter run
```
When creating a new feature module:
1. **Create folder structure**:
```
lib/features/new_feature/
├── data/
│ ├── datasources/
│ ├── models/
│ └── repositories/
├── domain/
│ ├── entities/
│ ├── repositories/
│ └── usecases/
└── presentation/
├── bloc/
├── pages/
└── widgets/
```
2. **Follow layer dependencies**:
- Presentation depends on domain only
- Domain has no dependencies (pure business logic)
- Data depends on domain (implements interfaces)
3. **Register dependencies** in `lib/config/injection.dart` using GetIt
4. **Add navigation routes** in `lib/config/routes/`
**Use Cubit when**:
**Use BLoC when**:
**Example Cubit**:
```dart
class SimpleCubit extends Cubit<SimpleState> {
SimpleCubit() : super(SimpleInitial());
void updateValue(String value) {
emit(SimpleLoaded(value));
}
}
```
**Example BLoC**:
```dart
class ComplexBloc extends Bloc<ComplexEvent, ComplexState> {
ComplexBloc() : super(ComplexInitial()) {
on<LoadData>(_onLoadData);
on<UpdateData>(_onUpdateData);
}
Future<void> _onLoadData(LoadData event, Emitter<ComplexState> emit) async {
// Complex logic here
}
}
```
**Database Operations**:
```dart
// Query with joins
final response = await supabase
.from('transactions')
.select('*, categories(*)')
.order('date', ascending: false);
// Insert with pgvector embedding
await supabase.from('transaction_embeddings').insert({
'transaction_id': id,
'embedding': embedding, // 384-dimensional array
});
// Similarity search using PostgreSQL function
final similar = await supabase.rpc('find_similar_transactions', params: {
'query_embedding': embedding,
'match_threshold': 0.7,
'match_count': 5,
});
```
**Caching Strategy**:
**Always refer to DESIGN_SYSTEM.md** for detailed specifications. Key principles:
**Typography**:
**Layout**:
**Color Palette**:
**Transaction List Pattern**:
```dart
// Merchant name (16px, white)
// Category (100px fixed width, 14px, gray)
// Amount with IN/OUT badge (16px, Roboto Mono tabular)
// Date separator with subtle divider
```
Run tests frequently during development:
```bash
flutter test
flutter test test/features/transactions/transactions_test.dart
flutter test --coverage
flutter analyze
dart format .
```
```bash
flutter run
flutter build apk --release
flutter build appbundle --release
```
1. **Never create authentication** - app works locally without user accounts
2. **Transaction type is derived from amount sign** - positive = income, negative = expense
3. **Categories in DB have name only** - no icon/color fields
4. **No code generation** - all models and dependencies are manual
5. **Currency is always INR (₹)** - use en_IN locale
6. **Dark mode only** - don't add light theme support
7. **Maintain fixed-width layouts** - prevents UI shifting in transaction lists
8. **Use cached categories** - avoid unnecessary DB calls in streams
1. **Category Loading**:
- Preload at app startup
- Use cached data for real-time operations
- Synchronous category lookups
2. **Stream Efficiency**:
- Minimize database queries
- Use cached reference data
- Debounce user input where appropriate
3. **ML Operations**:
- Batch embedding generation
- Cache similarity results
- Use confidence thresholds to avoid unnecessary categorization
**Always update documentation when**:
Update these files:
1. **Homepage shows current month only** - not "latest" or "recent" transactions
2. **Personalized greetings** - dynamic messages based on time/context, no account numbers
3. **Top 3 categories** - based on transaction count, not amount
4. **Progressive disclosure** - show essential information first, details on demand
5. **Minimal interactions** - no decorative animations, focus on data density
6. **Debit-optimized** - most transactions are expenses, design accordingly
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/expense-tracker-flutter-development/raw