diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..7b1ceaa Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/icon-192.png b/public/icon-192.png new file mode 100644 index 0000000..82622ce Binary files /dev/null and b/public/icon-192.png differ diff --git a/public/icon-512.png b/public/icon-512.png new file mode 100644 index 0000000..2e07c69 Binary files /dev/null and b/public/icon-512.png differ diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..a85da6a --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,24 @@ +{ + "name": "Randify — Random Value Generators", + "short_name": "Randify", + "description": "Simple tools for raffles, games, and everything that needs randomness.", + "start_url": "/", + "display": "standalone", + "background_color": "#09090b", + "theme_color": "#534AB7", + "orientation": "portrait-primary", + "scope": "/", + "lang": "en", + "icons": [ + { + "src": "/icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/public/sw.js b/public/sw.js new file mode 100644 index 0000000..f71d5ee --- /dev/null +++ b/public/sw.js @@ -0,0 +1,52 @@ +const CACHE_NAME = 'randify-v1'; + +self.addEventListener('install', (event) => { + self.skipWaiting(); +}); + +self.addEventListener('activate', (event) => { + event.waitUntil(self.clients.claim()); +}); + +self.addEventListener('fetch', (event) => { + const { request } = event; + const isNavigate = request.mode === 'navigate'; + const isSameOrigin = new URL(request.url).origin === self.location.origin; + + if (!isSameOrigin) { + return; + } + + if (isNavigate) { + // Network-first for HTML pages: fresh content when online, + // fallback to cache when offline. + event.respondWith( + fetch(request) + .then((response) => { + if (response && response.status === 200) { + const clone = response.clone(); + caches.open(CACHE_NAME).then((cache) => cache.put(request, clone)); + } + return response; + }) + .catch(() => caches.match(request)) + ); + } else { + // Cache-first for static assets (JS, CSS, SVG, fonts, etc.) + event.respondWith( + caches.match(request).then((cached) => { + if (cached) { + return cached; + } + return fetch(request).then((response) => { + if (!response || response.status !== 200 || response.type !== 'basic') { + return response; + } + const clone = response.clone(); + caches.open(CACHE_NAME).then((cache) => cache.put(request, clone)); + return response; + }); + }) + ); + } +}); diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index f7cde42..1349385 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -36,8 +36,16 @@ const ruUrl = `https://randify.pro${getRelativeLocaleUrl("ru", pathWithoutLocale + + + {title} +