diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..7fb22a6 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,21 @@ +{ + "name": "Tia - Baby Tracking", + "short_name": "Tia", + "description": "Your baby tracking companion", + "start_url": "/", + "display": "standalone", + "background_color": "#fdf2f2", + "theme_color": "#fb7185", + "icons": [ + { + "src": "/icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} \ No newline at end of file diff --git a/public/sw.js b/public/sw.js new file mode 100644 index 0000000..7c79894 --- /dev/null +++ b/public/sw.js @@ -0,0 +1,49 @@ +/// + +declare const self: ServiceWorkerGlobalType; + +const CACHE_NAME = "tia-v1"; +const STATIC_ASSETS = [ + "/", + "/manifest.json", +]; + +self.addEventListener("install", (event) => { + event.waitUntil( + caches.open(CACHE_NAME).then((cache) => cache.addAll(STATIC_ASSETS)) + ); + self.skipWaiting(); +}); + +self.addEventListener("activate", (event) => { + event.waitUntil( + caches.keys().then((keys) => + Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))) + ) + ); + self.clients.claim(); +}); + +self.addEventListener("fetch", (event) => { + // Skip non-GET requests + if (event.request.method !== "GET") return; + + // Skip API requests + if (event.request.url.includes("/api/")) return; + + event.respondWith( + caches.match(event.request).then((cached) => { + const networked = fetch(event.request) + .then((response) => { + const clone = response.clone(); + caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone)); + return response; + }) + .catch(() => cached); + + return cached || networked; + }) + ); +}); + +export {}; \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 976eb90..825896c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -13,8 +13,13 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Tia - Baby Tracking", + description: "Your baby tracking companion", + manifest: "/manifest.json", + icons: [ + { url: "/icon-192.png", sizes: "192x192", type: "image/png" }, + { url: "/icon-512.png", sizes: "512x512", type: "image/png" }, + ], }; export default function RootLayout({ diff --git a/src/app/page.tsx b/src/app/page.tsx index 7f0d20c..1254d96 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -200,6 +200,12 @@ export default function HomePage() { // Process queue when coming online const handleOnline = () => processOfflineQueue(); window.addEventListener("online", handleOnline); + + // Register service worker + if ("serviceWorker" in navigator) { + navigator.serviceWorker.register("/sw.js").catch(console.error); + } + return () => window.removeEventListener("online", handleOnline); }, []);