RightNow Technical Deep Dive: Building in Public
As an indie developer building RightNow in public, I want to share the technical journey and decisions behind the app. This isn’t about showing off code - it’s about sharing what I’ve learned and helping others who might be on a similar path.
The Numbers: A Growing Codebase
Let’s start with some stats that show the scale of this project:
- 44,724 lines of Dart code in the app
- 9,798 lines of test code
- 41 test files with 258 tests passing
- 9 major milestones completed
- 6 months of active development
pie title "Code Distribution"
"App Code" : 44724
"Test Code" : 9798
"Config/Scripts" : 5000
Architecture: Why Offline-First?
Early on, I made a crucial decision: offline-first architecture. Here’s why:
graph TD
A[User Action] --> B[Local Update]
B --> C[Instant UI Change]
B --> D[Queue for Sync]
D --> E{Online?}
E -->|Yes| F[Sync to Cloud]
E -->|No| G[Wait & Retry]
G --> E
Benefits I’ve Experienced
- Lightning fast UI - No waiting for network calls
- Works anywhere - Airplane, subway, poor connection
- No loading spinners - Everything feels instant
- Reliability - Network issues don’t break the app
The Trade-offs
- More complex sync logic
- Potential for conflicts (solved with timestamps)
- Larger app size (local database)
- Testing is more involved
State Management Evolution
I went through several iterations before landing on the current architecture:
Version 1: Simple Provider
Widget → Provider → Database
Problem: Too much rebuilding, poor performance
Version 2: Repository Pattern
Widget → Provider → Repository → Database
Better: Separation of concerns, easier testing
Version 3: Current Architecture
graph LR
A[UI Widget] --> B[Riverpod Provider]
B --> C[Repository Interface]
C --> D[Hive Repository]
C --> E[Mock Repository]
D --> F[Local Database]
E --> G[Test Data]
This pattern has been a game-changer for:
- Testing - Swap real/mock repositories easily
- Features - Add new data sources without touching UI
- Debugging - Clear separation of layers
The Testing Journey
Testing wasn’t an afterthought - it evolved with the app:
graph TD
A[Manual Testing Only] --> B[Basic Widget Tests]
B --> C[Repository Tests]
C --> D[Integration Tests]
D --> E[Full Test Suite]
style A fill:#ff6b6b
style B fill:#ffa06b
style C fill:#ffda6b
style D fill:#9fd86b
style E fill:#6bd8a0
Current Test Coverage
- Unit Tests: Repository logic, data models
- Widget Tests: UI components in isolation
- Integration Tests: Full user workflows
- Manual Tests: Real device testing
Testing Lessons Learned
- Start simple - Even basic tests catch bugs
- Mock at boundaries - Repository interfaces are perfect
- Test user journeys - Not just individual functions
- Keep tests fast - Or you won’t run them
Feature Development Process
Here’s how I typically build a new feature:
graph TD
A[User Feedback] --> B[Design in Figma]
B --> C[Create Data Model]
C --> D[Build Repository]
D --> E[Write Tests]
E --> F[Create UI]
F --> G[Connect Provider]
G --> H[Manual Testing]
H --> I[Ship It!]
Real Example: Task Grooming Games
The gamification feature went through this exact process:
- Feedback: “Grooming backlog is boring”
- Design: Swipe-based card games
- Model: GroomingData with score tracking
- Repository: Separate from main task repo
- Tests: Swipe gesture handling
- UI: Custom game widgets
- Provider: Game state management
- Testing: Friends loved it!
- Shipped: In 3 days
Performance Optimizations
Building for mobile taught me about performance the hard way:
Problem 1: Slow List Scrolling
Solution: Implemented virtualization
graph LR
A[1000 Tasks] --> B[Render Only Visible]
B --> C[~20 Widgets]
C --> D[Smooth 60fps]
Problem 2: Expensive Rebuilds
Solution: Selective watching with Riverpod
// Instead of watching entire task list
ref.watch(taskListProvider.select((tasks) => tasks.length))
Problem 3: Memory Leaks
Solution: Proper disposal and lifecycle management
Platform Challenges
Supporting multiple platforms brought unique challenges:
graph TD
A[Flutter App] --> B[Android]
A --> C[iOS]
A --> D[Web]
A --> E[Desktop]
B --> F[Play Store]
C --> G[App Store]
D --> H[Firebase Hosting]
E --> I[Direct Download]
Platform-Specific Issues
- Android: Keyboard handling, back button
- iOS: Safe areas, gesture conflicts
- Web: Browser back button, local storage limits
- Desktop: Window management, file system
Key Technical Decisions
✅ Decisions I’m Happy With
- Flutter - Write once, run everywhere actually works
- Offline-first - Users love the speed
- Hive database - Simple, fast, reliable
- Repository pattern - Made everything testable
- Riverpod - Powerful state management
🤔 Decisions I’d Reconsider
- Not using code generation earlier - Would have saved time
- Custom animation system - Should have used built-in
- Over-engineering early - YAGNI is real
- Delaying tests - Should have started day one
Deployment Pipeline
Getting the app to users efficiently:
graph LR
A[Git Push] --> B[GitHub Actions]
B --> C[Run Tests]
C --> D[Build Apps]
D --> E[Deploy Web]
D --> F[Upload to Stores]
F --> G[Users!]
But when GitHub Actions minutes ran out, I adapted:
:: Local build script
flutter test
flutter build web
firebase deploy
flutter build appbundle
fastlane upload
Lessons for Other Indie Developers
1. Start Shipping Early
Don’t wait for perfection. My first version had 5 features, not 50.
2. Listen to Users
The best features came from user feedback, not my ideas.
3. Automate Everything
Time spent on automation pays back 10x.
4. Test the Critical Path
You don’t need 100% coverage, just test what matters.
5. Document as You Go
This blog post was easier because I kept notes.
What’s Next?
The technical journey continues:
- Real-time sync - WebSocket integration
- Collaborative features - Shared task lists
- AI integration - Smart task suggestions
- Plugin system - Let users extend functionality
Open Source Plans
I’m considering open-sourcing parts of RightNow:
- The task grooming game engine
- The offline-first sync system
- The capacity management algorithm
- Testing utilities I’ve built
Join the Journey
Building in public means sharing the good and the bad. Follow along:
- 📱 Try the app: rightnow01.web.app
- 📖 Learn more: RightNow App Development
- 📝 Blog series: All RightNow posts
Have questions? Want to share your experience? I’d love to hear from you!
| *Previous: Target Audience & Use Cases ← | Next: Introduction to RightNow →* |
| *Learn more: RightNow App Development | Privacy Policy | Delete Account* |
