Files
homepage/src/routes/[recipeLang=recipeLang]/+page.ts
Alexander Bocken 9ff30b28cd feat: add PWA offline support for recipe pages
- Add service worker with caching for build assets, static files, images, and pages
- Add IndexedDB storage for recipes (brief and full data)
- Add offline-db API endpoint for bulk recipe download
- Add offline sync button component in header
- Add offline-shell page for direct navigation fallback
- Pre-cache __data.json for client-side navigation
- Add +page.ts universal load functions with IndexedDB fallback
- Add PWA manifest and icons for installability
- Update recipe page to handle missing data gracefully
2026-01-28 21:38:33 +01:00

51 lines
1.4 KiB
TypeScript

import { browser } from '$app/environment';
import { isOffline, canUseOfflineData } from '$lib/offline/helpers';
import { getAllBriefRecipes, getBriefRecipesBySeason, isOfflineDataAvailable } from '$lib/offline/db';
import { rand_array } from '$lib/js/randomize';
export async function load({ data }) {
// On the server, just pass through the server data unchanged
if (!browser) {
return {
...data,
isOffline: false
};
}
// On the client, check if we need to load from IndexedDB
// This happens when:
// 1. We're offline (navigator.onLine is false)
// 2. Service worker returned offline flag
// 3. Server data is missing (e.g., client-side navigation while offline)
const shouldUseOfflineData = (isOffline() || data?.isOffline || !data?.all_brief?.length) && canUseOfflineData();
if (shouldUseOfflineData) {
try {
const hasOfflineData = await isOfflineDataAvailable();
if (hasOfflineData) {
const currentMonth = new Date().getMonth() + 1;
const [allBrief, seasonRecipes] = await Promise.all([
getAllBriefRecipes(),
getBriefRecipesBySeason(currentMonth)
]);
return {
...data,
all_brief: rand_array(allBrief),
season: rand_array(seasonRecipes),
isOffline: true
};
}
} catch (error) {
console.error('Failed to load offline data:', error);
}
}
// Return server data as-is
return {
...data,
isOffline: false
};
}