Building a Trust-First Babysitting Platform with Flutter
A deep dive into building a production-ready babysitting app with Flutter, covering clean architecture, real-time tracking, payment systems, and property-based testing.
Building a platform where parents entrust their children to caregivers isn't just another CRUD app. It's a system where every line of code carries the weight of child safety, trust verification, and real-time accountability.
The Problem I Set Out to Solve
The childcare industry has a trust problem. Parents struggle to find verified babysitters, and qualified caregivers lack a platform to showcase their credentials. I wanted to build something that would:
- Connect parents with verified babysitters in real-time
- Provide live session tracking with geo-fencing
- Implement a trust scoring system that rewards reliability
- Handle secure payments with transparent commission structures
- Ensure child data protection at every layer
The Tech Stack
| Layer | Technology | Why | |-------|------------|-----| | Frontend | Flutter | Single codebase for iOS and Android | | State Management | BLoC | Predictable state, testable, scales well | | DI | GetIt + Injectable | Clean dependency injection | | Networking | Dio + Socket.io | HTTP + real-time WebSocket | | Security | AES-256 + flutter_secure_storage | Military-grade encryption | | Testing | glados | Property-based testing |
I went with BLoC because it enforces separation of concerns, events and states are explicit, and testing is straightforward.
Architecture: Clean Architecture with Feature Modules
lib/
├── core/ # Shared infrastructure
│ ├── bloc/ # Base BLoC classes
│ ├── di/ # Dependency injection
│ ├── error/ # Failures, exceptions
│ ├── network/ # API client, WebSocket
│ └── storage/ # Secure storage, encryption
├── features/ # Feature modules
│ ├── auth/
│ ├── booking/
│ ├── session/
│ ├── payment/
│ └── trust_score/
└── shared/ # Shared widgets
Each feature is self-contained, testable in isolation, and can be worked on independently.
The Hardest Problems I Solved
1. Child Data Encryption
Child information is the most sensitive data in the system. I needed encryption at rest:
class EncryptionService {
final Key _key;
final IV _iv;
late final Encrypter _encrypter;
EncryptionService(String secretKey)
: _key = Key.fromUtf8(secretKey.padRight(32, '0').substring(0, 32)),
_iv = IV.fromLength(16) {
_encrypter = Encrypter(AES(_key, mode: AESMode.cbc));
}
String encrypt(String plainText) {
return _encrypter.encrypt(plainText, iv: _iv).base64;
}
String decrypt(String encryptedText) {
return _encrypter.decrypt64(encryptedText, iv: _iv);
}
}
I wrote a property-based test to verify round-trip consistency:
Glados<String>().test('encryption round-trip preserves data', (input) {
final encrypted = encryptionService.encrypt(input);
final decrypted = encryptionService.decrypt(encrypted);
expect(decrypted, equals(input));
});
2. Real-Time Session Tracking with Geo-Fencing
Parents need to know where their children are during a session:
- 30-second location updates via WebSocket
- Geo-fence monitoring that alerts parents if the babysitter leaves the designated area
- GPS tampering detection to catch location spoofing
bool isWithinGeoFence(Location current, GeoFence fence) {
final distance = calculateHaversineDistance(
current.latitude, current.longitude,
fence.center.latitude, fence.center.longitude,
);
return distance <= fence.radiusMeters;
}
When a babysitter exits the geo-fence, the system sends an immediate push notification to the parent and logs the event.
3. The Cred Score Algorithm
I built a trust scoring system (0-100) that considers:
| Component | Weight | What It Measures | |-----------|--------|------------------| | Attendance | 25 points | Shows up on time | | Ratings | 35 points | Client satisfaction | | Response Time | 20 points | Booking acceptance speed | | Complaints | 20 points | Fewer complaints = higher score |
The score affects search visibility, commission rates (20% → 15% → 12%), and access to premium jobs.
class CredScoreCalculator {
CredScore calculate(BabysitterMetrics metrics) {
final attendance = _calculateAttendance(metrics.completionRate);
final rating = _calculateRating(metrics.averageRating);
final response = _calculateResponse(metrics.avgResponseMinutes);
final complaints = _calculateComplaints(metrics.complaintRate);
final total = (attendance + rating + response + complaints)
.clamp(0, 100)
.toInt();
return CredScore(score: total, tier: _getTier(total));
}
}
4. Payment Calculation
Payments involve multiple variables:
PaymentEstimate calculate(PaymentRequest request) {
final hours = max(1, (request.durationMinutes / 60).ceil());
final baseAmount = hours * request.hourlyRate;
final surgedAmount = baseAmount * request.surgeMultiplier;
final totalAmount = surgedAmount * request.childMultiplier;
final commissionRate = _getCommissionRate(request.credScore);
final commission = totalAmount * commissionRate;
final babysitterPayout = totalAmount - commission;
return PaymentEstimate(
estimatedTotal: totalAmount,
platformCommission: commission,
babysitterEarnings: babysitterPayout,
);
}
5. Cancellation Fee Logic
| Cancellation Window | Fee | |---------------------|-----| | > 24 hours before | 0% (full refund) | | 2-24 hours before | 25% | | < 2 hours before | 50% |
Property-Based Testing: My Secret Weapon
Traditional unit tests check specific examples. Property-based tests check universal truths:
Glados<String>().test('encryption is reversible', (input) {
expect(decrypt(encrypt(input)), equals(input));
});
The testing library generates hundreds of random inputs, including edge cases like empty strings, Unicode characters, and special characters.
Key Properties I Tested
| Property | What It Validates | |----------|-------------------| | Encryption round-trip | Data integrity | | Cred Score bounds | Score always 0-100 | | Payment calculation | Formula correctness | | Cancellation fees | Correct tier based on timing | | Geo-fence detection | Accurate boundary checking |
Challenges and Solutions
Offline Session Handling
What happens when a babysitter loses connectivity?
Solution: Local state caching with conflict resolution. Server is authoritative for session state, but we preserve local timeline events and flag payment discrepancies for manual review.
Rate Limiting Without Blocking Legitimate Users
Solution: Tiered rate limiting
- 3 failed OTPs → 15-minute lockout
- 5 requests in 10 minutes → CAPTCHA required
- Device-level tracking → Prevents SIM swap attacks
Payment Gateway Failures
Solution: Retry with exponential backoff + queue for later processing if all retries fail.
Performance Optimizations
- WebSocket for location updates - No polling overhead
- Redis for hot data - Active sessions, babysitter locations, surge pricing
- Lazy loading in discovery - Fetch babysitters based on map viewport
Key Takeaways
- Trust is earned through verification layers - Multiple verification steps build confidence
- Real-time features need offline fallbacks - Users lose connectivity, plan for it
- Property-based testing catches what unit tests miss - Random inputs find edge cases
- Clean architecture pays off at scale - Upfront investment saves time later
- Security isn't a feature—it's a foundation - Encrypt sensitive data, validate inputs
The Result
After months of development, I shipped a platform that:
- Verifies babysitters through multi-layer KYC
- Tracks sessions in real-time with geo-fencing
- Calculates payments with transparent commission tiers
- Protects child data with AES-256 encryption
- Maintains trust through an algorithmic Cred Score
The codebase has 30+ property-based tests validating correctness properties across millions of possible inputs.
Have questions about building trust-first platforms? Feel free to reach out!