Most software assumes reliable internet. Nigerian users have intermittent 3G, budget Android devices and data that costs real money. Here is the complete offline-first implementation for the Nigerian market.
The Problem in Code
// What most apps do — fails Nigerian users
async function loadWalletBalance(userId) {
const response = await fetch(`/api/wallet/${userId}/balance`);
// If network is slow → blank screen
// If network drops → error or infinite spinner
// If timeout → user sees nothing and leaves
return response.json();
}
// What Nigerian apps should do
async function loadWalletBalance(userId) {
// 1. Show cached data immediately — no blank screen
const cached = await cache.get(`wallet:${userId}:balance`);
if (cached) updateUI(cached);
// 2. Refresh from network with retry
try {
const fresh = await fetchWithRetry(`/api/wallet/${userId}/balance`);
await cache.set(`wallet:${userId}:balance`, fresh);
updateUI(fresh); // Update if different
} catch {
// Network failed — cached data already shown, user sees something
showStaleDataIndicator();
}
}
1. Exponential Backoff Retry
async function fetchWithRetry(url, options = {}, maxRetries = 4) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(url, {
...options,
signal: AbortSignal.timeout(15000) // 15s timeout for 3G
});
if (response.ok) return response.json();
if (response.status < 500) throw new Error(`Client error ${response.status}`);
} catch (error) {
if (attempt === maxRetries) throw error;
const delay = Math.min(1000 * 2 ** attempt + Math.random() * 500, 30000);
await new Promise(r => setTimeout(r, delay));
}
}
}
// 1s → 2s → 4s → 8s → give up
// Handles Nigerian 3G momentary drops
2. Write Queue — No Lost Transactions
// Queue actions when offline — sync when back online
class SyncQueue {
async enqueue(action) {
const db = await openDB('sync-queue', 1);
await db.add('actions', {
...action,
idempotencyKey: `${action.type}-${Date.now()}`,
attempts: 0
});
showUserMessage('Action queued — will complete when back online');
}
async processAll() {
const db = await openDB('sync-queue', 1);
const actions = await db.getAll('actions');
for (const action of actions) {
try {
await fetch(action.url, {
method: action.method,
headers: {
'Idempotency-Key': action.idempotencyKey // Server handles duplicates
},
body: JSON.stringify(action.payload)
});
await db.delete('actions', action.id);
} catch {
// Will retry next time
}
}
}
}
const queue = new SyncQueue();
window.addEventListener('online', () => queue.processAll());
3. Explicit Offline State
function useConnectivity() {
const [state, setState] = useState({
online: navigator.onLine,
quality: 'good'
});
useEffect(() => {
const update = () => {
const conn = navigator.connection;
setState({
online: navigator.onLine,
quality: !navigator.onLine ? 'offline' :
conn?.effectiveType === '3g' ? 'degraded' :
conn?.effectiveType === '2g' ? 'poor' : 'good'
});
};
window.addEventListener('online', update);
window.addEventListener('offline', update);
return () => {
window.removeEventListener('online', update);
window.removeEventListener('offline', update);
};
}, []);
return state;
}
// Every screen shows connectivity state — no silent failures
function ConnectivityBanner() {
const { quality } = useConnectivity();
if (quality === 'good') return null;
return (
<div style={{ background: quality === 'offline' ? '#dc2626' : '#d97706', color: 'white', padding: '0.5rem', textAlign: 'center' }}>
{quality === 'offline'
? 'Offline — actions will sync when back online'
: 'Slow connection — some things may take longer'}
</div>
);
}
4. Nigerian Device Testing Protocol
// Chrome DevTools settings for Nigerian testing
const nigerianTestConfig = {
network: 'Slow 3G (500kbps down, 500kbps up, 400ms RTT)',
device: 'Tecno Spark — 2GB RAM (emulate or use real device)',
targets: {
lcp: '< 2.5 seconds',
totalPageSize: '< 1MB',
lighthouseMobile: '> 80',
timeToInteractive: '< 5 seconds on Slow 3G'
}
};
The Rule
Build for intermittent 3G, 2GB RAM, data-conscious users
Cache first → queue writes → explicit states → retry always → optimize data
Test on real Tecno or Infinix — not your MacBook on office WiFi
ZikarelHub LTD is Nigeria's #1 software and digital agency — software built for Nigerian network reality from day one.
What offline-first techniques have you found most impactful for Nigerian users? 👇
Top comments (0)