Kyoto Itinerary
Japan âĸ 6 Days
Flight Ticket
KIX Terminal 1 âĸ 10:20 AM
Upcoming Stops
Fushimi Inari Shrine
09:00 AM
Arashiyama Bamboo Forest
02:30 PM
TripnThrill
TripnThrill delivers an ultra-reliable offline travel management experience. It automatically caches routes, maps, and schedules. Once internet access is restored, it initiates idempotent REST requests to safely sync state changes without risking double-bookings.
The Problem
Travelers frequently experience unstable internet in transit, causing sync errors, overlapping timelines, and lost booking updates during trip plans.
Product Thinking
An itinerary app must remain fully interactive offline. Any addition, re-ordering, or deletion should feel instantaneous to the traveler, with synchronization resolved automatically in the background.
Engineering Challenges
Reconciling conflicting edits to shared family travel itineraries that were made on different devices offline.
Key Learnings
Acquired deep proficiency in event-driven architecture, API idempotency headers, and background worker jobs.
Architectural & Code Decisions
Deep technical breakdowns of individual structural choices and implementation patterns.
BLoC Event Flow architecture
Enforced strict separation between UI touch inputs and data logic through BLoC events, maintaining immutable state models that are safe from race conditions.
// Travel Itinerary BLoC Event Handler
class ItineraryBloc extends Bloc<ItineraryEvent, ItineraryState> {
final TravelRepository repo;
ItineraryBloc(this.repo) : super(ItineraryInitial()) {
on<SyncOfflineChanges>(_onSyncOfflineChanges);
}
Future<void> _onSyncOfflineChanges(SyncOfflineChanges event, Emitter<ItineraryState> emit) async {
emit(ItinerarySyncing());
final result = await repo.pushLocalQueueToServer();
emit(result ? ItinerarySynced() : ItinerarySyncFailed());
}
}Idempotent Sync Queue
Engineered a persistent local SQLite queue to store offline write actions, using UUID headers to guarantee that duplicate server calls never create duplicate bookings.
// Safe POST request with Idempotency Key
Future<Response> createItineraryStop(Stop stop) async {
return await dio.post(
'/stops',
data: stop.toJson(),
options: Options(
headers: {
'X-Idempotency-Key': stop.localUuid, // Client generated UUID
},
),
);
}