Understanding Offline Mode and Caching
How LobbyFlight works offline and how data caching ensures continuous display
Understanding Offline Mode and Caching
LobbyFlight is designed for 24/7 operation in hotel lobbies. The intelligent caching system ensures that your display continues to show flight information even during network interruptions.
How Offline Mode Works
Service Worker Architecture
LobbyFlight uses a Service Worker - a JavaScript technology that runs in the background and manages caching.
Benefits:
What Gets Cached?
| Content | Storage Duration | Update Frequency |
| --------- | ------------------ | ------------------ |
| App files (HTML, CSS, JS) | Until update | At app release |
|---|---|---|
| Flight data | 6 hours | Based on tierutes |
| Weather data | 2 hours | Every 30 minutes |
| Logo and images | Unlimited | On change |
| Configuration | 24 hours | On change |
Offline Behavior
When Internet is Lost
- Service Worker intercepts requests
- Cached data is delivered
- User notices nothing
- Orange status bar appears: "Offline mode"
- Cached flight data continues to display
- Last update time is shown
- Warning appears: "Data may be outdated"
- Display continues to work
- Users are informed
- Cached data marked as stale
- Clear indication shown
- System continues to attempt reconnection
Automatic Reconnection
The system continuously tries to restore the connection:
// Reconnection logic
function tryReconnect() {
fetch('/api/health')
.then(() => {
showNotification('Connection restored')
refreshData()
})
.catch(() => {
attempts++
const delay = attempts < 30 ? 1000 :
attempts < 60 ? 5000 : 30000
setTimeout(tryReconnect, delay)
})
}Cache Management
Automatic Cleanup
Service Worker performs automatic cleanup:
On app update:
Code:
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames
.filter(name => name !== CURRENT_CACHE)
.map(name => caches.delete(name))
)
})
)
})Manual Cache Clearing
Method 1: Via Browser DevTools
Method 2: Via JavaScript Console
// Clear all caches
caches.keys().then(names => {
names.forEach(name => caches.delete(name))
})
// Re-register Service Worker
navigator.serviceWorker.getRegistration().then(reg => {
reg.unregister()
window.location.reload()
})Method 3: Hard Refresh
Method 4: Message API
// Send cache-clear message to Service Worker
navigator.serviceWorker.controller.postMessage({
type: 'CLEAR_CACHE',
cache: 'all' // or 'api', 'assets', 'runtime'
})Cache Size Management
Browser Limits:
LobbyFlight typical usage:
Automatic Eviction:
Browser automatically deletes old caches when:
Troubleshooting Offline Issues
Problem: Old Data Displayed
Symptoms:
Diagnosis:
Solutions:
Problem: Offline Mode Despite Internet
Symptoms:
Diagnosis:
Solutions:
Problem: Service Worker Not Loading
Symptoms:
Diagnosis:
// Run in Console
navigator.serviceWorker.getRegistrations().then(regs => {
console.log('Registered SWs:', regs)
})Solutions:
Problem: Cache Growing Too Large
Symptoms:
Diagnosis:
// Check cache size
navigator.storage.estimate().then(estimate => {
console.log(`Used: ${estimate.usage / 1024 / 1024}MB`)
console.log(`Quota: ${estimate.quota / 1024 / 1024}MB`)
})Solutions:
Best Practices for Offline Operation
Optimal Configuration
For stable network:
For unstable network:
Preparation for Offline
Before deployment:
Regular maintenance:
Monitoring
What to monitor:
Alert thresholds:
Advanced Configuration
Custom Offline Page
You can design a custom offline page:
HTML Template (/public/custom-offline.html):
<!DOCTYPE html>
<html>
<head>
<title>Offline - [Hotel Name]</title>
<style>
/* Your custom styling */
</style>
</head>
<body>
<div class="container">
<img src="/logo.png" alt="Hotel Logo">
<h1>Currently no connection</h1>
<p>Showing cached flight data...</p>
<div id="last-update"></div>
</div>
<script>
// Custom reconnect logic
</script>
</body>
</html>Customizing Cache Strategies
For special requirements:
// Longer cache time for images
if (request.destination === 'image') {
return caches.match(request) || fetch(request).then(response => {
cache.put(request, response.clone())
return response
})
}
// No cache for specific APIs
if (request.url.includes('/realtime/')) {
return fetch(request) // Always fresh
}Offline Analytics
Tracking offline events:
// On offline
navigator.sendBeacon('/api/analytics', JSON.stringify({
event: 'offline_start',
timestamp: new Date().toISOString(),
cached_items: await countCachedItems()
}))
// On reconnect
navigator.sendBeacon('/api/analytics', JSON.stringify({
event: 'offline_end',
duration: offlineDuration,
cache_hits: cacheHitCount
}))