Why Offline-First Matters for Travel Apps
Travel apps have a unique problem: users need them most when they have the worst connectivity. Airports, trains, remote destinations — these are exactly where mobile data is slow, expensive, or nonexistent.
MicroItinerary is an AI-powered travel planner. Users create itineraries, track expenses, and get destination recommendations. All of this needs to work offline — not as a degraded experience, but as the primary mode.
The key mindset shift: don't treat offline as an error state. Treat it as the default, with online as an enhancement.
The Three Layers of Offline Support
Offline-first PWAs require three things working together:
1. Service Worker — intercepts network requests and serves cached responses. This handles static assets (HTML, CSS, JS) and API responses.
2. IndexedDB — a browser-native NoSQL database for structured data. This stores itineraries, expenses, and user preferences locally.
3. Background Sync — queues mutations (create/update/delete) while offline and replays them when connectivity returns.
Each layer solves a different problem. Service workers handle read caching, IndexedDB handles local state, and background sync handles write durability.
Service Worker: Cache-First Strategy
MicroItinerary uses a cache-first strategy for static assets and a network-first strategy for API data:
For API calls, we try the network first and fall back to IndexedDB:
This means the app always shows data — fresh from the server when online, or from the local cache when offline.
IndexedDB: Local-First State Management
IndexedDB is where the real offline magic happens. Every itinerary, expense, and preference is stored locally first, then synced to the server.
We use Dexie.js as a wrapper around IndexedDB for a cleaner API:
The syncQueue table is critical — it stores pending mutations that haven't been sent to the server yet. Each entry records the action (create/update/delete), the payload, and a timestamp for conflict resolution.
Background Sync: Write Durability
When a user creates an expense while offline, it goes into IndexedDB immediately and gets added to the sync queue. When the device comes back online, the service worker replays the queue:
The service worker's sync event fires automatically when connectivity is restored — even if the app is closed. This means expenses added on a plane land in the database when the user arrives.
Key Takeaways
- Treat offline as the default — design your data flow for no connectivity, then add sync
- IndexedDB is your source of truth — the server is just a backup
- Queue all writes — never fire-and-forget network mutations
- Use timestamps for conflict resolution — last-write-wins is simple and usually sufficient
- Test offline regularly — Chrome DevTools' Network panel has an "Offline" checkbox. Use it.