
PhotoTrek on iPhone, Android & Web: Cross-Platform App Architecture with Flutter
Part 6 of the PhotoTrek Series: Building a unified mobile & web client in Flutter 3.44 and Dart 3.12 with pure Dart solar physics and native Apple Maps navigation.
Native iOS (iPhone/iPad), Android, and Web PWA support with pure Dart solar physics and 2-Opt VRP optimization.
The Multi-Device Reality of Expeditions and Classrooms
In modern field logistics and school field trips, teachers, students, chaperones, and photographers carry a diverse matrix of devices:
- 🍏 iPhones & iPads: Chaperones and educators carrying iOS devices.
- 🤖 Android Phones & Tablets: School bus cockpit navigation and driver tablets.
- 💻 Chromebooks & MacBooks: Students running mission control in Chrome classrooms.
To deliver an identical, high-performance experience across all ecosystems without rewriting core math, we created PhotoTrek Flutter—a unified cross-platform client written in Dart 3.12+ and Flutter 3.44+.
🏗️ Cross-Platform Architecture: One Codebase, All Platforms
┌─────────────────────────────────────────────────────────────┐
│ FLUTTER PRESENTATION LAYER │
│ (MapScreen • BucketList • RouteSolver • SolarHUD • BusTrip)│
├─────────────────────────────────────────────────────────────┤
│ DOMAIN LOGIC (PURE DART) │
│ • SunCalcEngine: Solar Azimuth & Golden Hour Trigonometry │
│ • VrpOptimizer: 2-Opt & Nearest-Neighbor Routing Algorithm │
│ • SchoolBusVrpOptimizer: Bell Margins & Micro-Grant Models │
├─────────────────────────────────────────────────────────────┤
│ NATIVE COMPILATION TARGETS │
│ 🍏 iOS / iPadOS 🤖 Android 🌐 Web (WASM) 💻 Desktop │
└─────────────────────────────────────────────────────────────┘
⚡ Pure Dart Astronomical Physics (SunCalcEngine.dart)
By implementing our solar astronomical algorithms in pure Dart, sun position calculations execute natively at 60 FPS on any iPhone or iPad without needing platform bridges:
// lib/domain/solar/sun_calc_engine.dart
static SunPosition calculatePosition(DateTime date, double lat, double lng) {
final double dayOfYear = _getDayOfYear(date).toDouble();
final double hourOfDay = date.hour + date.minute / 60.0;
final double b = (360.0 / 365.0) * (dayOfYear - 81.0) * rad;
final double solarDeclination = 23.45 * math.sin(b) * rad;
final double solarHourAngle = (tst / 4.0 - 180.0) * rad;
final double elevationRad = math.asin(
math.sin(lat * rad) * math.sin(solarDeclination) +
math.cos(lat * rad) * math.cos(solarDeclination) * math.cos(solarHourAngle)
);
return SunPosition(
azimuthDegrees: (azimuthDeg + 360.0) % 360.0,
elevationDegrees: elevationRad * deg,
phase: elevationRad * deg >= -4.0 && elevationRad * deg <= 6.0 ? "Golden Hour" : "Daylight",
);
}
🚀 Running on iPhone, iPad, and Web
- Clone the Repository:
git clone https://github.com/philgear/phototrek-journey-flutter.git - Run on iOS Simulator / iPhone:
flutter run -d ios - Run on Web (Instant Chromebook PWA):
flutter run -d chrome - Execute Verified Unit Tests:
flutter test
📄 Open Source Ecosystem
Both the Flutter Cross-Platform Repository and the Android Studio Native Repository are fully open-source under the Apache 2.0 License!