From 3750cd2cc686c31fe08000fce490dc6107e33909 Mon Sep 17 00:00:00 2001 From: emil Date: Sun, 10 May 2026 21:06:19 +0300 Subject: [PATCH] feat: add PWA support with offline caching - Generate 192x192, 512x512 and Apple touch icons from favicon.svg - Add web app manifest (manifest.json) - Add service worker with network-first for HTML, cache-first for assets - Register SW in BaseLayout - Add theme-color meta and apple-touch-icon link --- public/apple-touch-icon.png | Bin 0 -> 3299 bytes public/icon-192.png | Bin 0 -> 3629 bytes public/icon-512.png | Bin 0 -> 10821 bytes public/manifest.json | 24 ++++++++++++++++ public/sw.js | 52 +++++++++++++++++++++++++++++++++++ src/layouts/BaseLayout.astro | 8 ++++++ 6 files changed, 84 insertions(+) create mode 100644 public/apple-touch-icon.png create mode 100644 public/icon-192.png create mode 100644 public/icon-512.png create mode 100644 public/manifest.json create mode 100644 public/sw.js diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7b1ceaaaf3307d6c370e250d40f2a524f6483dfd GIT binary patch literal 3299 zcmai1c~p{H_Xb12#94C|8bHlT%2IPi^QxG`HI?eSN#X7R5>Ha0j+Y1kfV9%y00MHJssRA7Os8`g�&0r|zVA zc4OER&nPH9 z_j=?>n_0e0xOjkR*>~vu@rMr$mL5);#P!u2>n&iGPsh-}b3!I1q;Zk( z4>-bC=NR6KXMlN(RS_VN0@Sps{CP8}=Ag0wEtR6?-uRprXItDmJo?oWM4kF6#xL?k zHI6w4U%P?7p^yXj(r;W$dwf(`pt_NmU&Q58Znyng)lHbGIVjMW`;h4}uV0XLr&TRY z)%lKhzjJox)9{w`%_-$yK<~5ag_1kXR-$5R(Rg}XyWNR}@5R@?ez1}w|&@pWIP)Zuq3pKH*8EFb5Mqcel`_WDcDR9EJEO z<#T8{PCMB=3`SIv@Psz@2DTj_F`LIdsuHdrTd#hjTGS56{x%2P-6`yeMFnb5JaG2UHg2Z(#!%t;amN8W1 z@{~FNYtuwGguRgCIAQz&dJn=sV84;?MuK7#+cGq_32Ve@Z6N&!)H1X2@^L;(0id3* zNCHONwzA(I2G9V=0VYtY_OD0>fF2Ob5pEa1n)>@ad+J>od}t7ytCSR{Oq6ItNydV6 zb)l!nEHL!;IVlMlV>kJLS9juU;s=yK8n>Py7*|(8|HDLgw#K?~Ox>+gHoT7`SrBBg zajv2^#W&u7)q~Yfw9zf{6ZtN_IN5l-d}CALG&3Une(N)l%rv`*W=B^Fo%*e55KXw~ z;6WHLHeIT^Jo14{c}WX{5+%5;TW9>$BAZ3N0h&~|UvD@3{G|TRt&93!N%c#vt`#`=<*}Ot)tY`%$ynp*S!vq&>oht&Yy=7 zaJVe(svDnfv47;Mnlqys!>iY7JirLX$&|Ni;o@AmrfL)2c(~7(TYj#?2Y7zPFdMpG z&L-8^Ukx8E++i5|L`78ArUZ&^ty+2a0zhV{-C5#Dw8rTDhLvwKd4tBNZQrJULRJPd z7h&vK2bOG*-{NCef6dnIu02TAV{CfRbpcE5gN1`=epbunpyg|YRBGZ-=v~2=o{{Lj zwJ804@*K6`cc=+i&xo+z-!yn@#MWQ)<}`C&jFAGA2vgz`hC-Ld4p?=raPnDU4J*A* zEB8Xj+Vr#;$yJep0@q%|HEB>u+!yyg-0?r3XOtInE$-3Wh8CDD4~ z-+MhP6fQG_!Z@z2&CP#z2YmRY%&rsD>!vp^`D6Z*^&<{+>#k&8t~#U)R%1rj>ky{{%!yoTNLek4()5zSjXgSWor-lcPv@5EWW;sB31 zixfM^KK?RwtllSjl_ObW0{-t>ZWVmN%Is4;WVv7^#Ef~d;oqfu=XQ|M97;S_C3F>L}P+XWR?Ev|GmX zUpmN`OSlK;lts0-RQN<#lppPNDjaf+9unu)DbM*WN5iDYr&HnUh21YJAtboLbu|g? zzj`14xHxa>Fkalzl`NuAGf%-{Qv-O424M{vv?34JWfQ^$?X0xj4ThGic^=> zRF%-i(EM*xn}VDMKCLb}Od4ihJ%piaKetHEP4>5)dD_|T5Wk^g@D(8Oy{!>g^=pW= z@&~slaZ)liuv0 z{}OC^!D(vYtr0*u39VfSIc9zM^PvI*mN^LF7x*%ynBnQ2e79X>1e)w(bBS^g%kp(^Cao=*qoito z%z^+BRF~n*#hlh*whhj@*uFSbtg$TBI6PvOVu}!>c>lh$4Qs(6zUX0N;G@&dJ97Is z%k6a=a7eE`5qLss>Tz5%&Xpy* zsIvd?p!;|ajM)%=W~g?}!_z+IQsgxF*bqY%gDf!R(l#E*Essq{oxi!%G-rxe&SW^h z!-L*SA_doczN@dl>@&tw zb@309TMW&zi|i&{JI?E?3a(?K4XjT7uEBk-Q<)I>Szl{91e(nSzs^Vqo@4fk#dw=j zY0QuL8F--S=OZZ|9g|(ug_-(S+cx%!H?&1U_V_GC&D&QNF8bpNjv|-Zta@Q1@WQsv j3b~8-gg1G&VHYC0YT@O1c(hXd*8*^|cRg2Sdo}JqJZ($O literal 0 HcmV?d00001 diff --git a/public/icon-192.png b/public/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..82622ce65a128f0ff2ad17d9f9ff906a5e833c07 GIT binary patch literal 3629 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 Uk-?P^^?$&*(>4}WX6_090|1@Rg#Z8m literal 0 HcmV?d00001 diff --git a/public/icon-512.png b/public/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..2e07c690039c3744240f78055479479cb69af64d GIT binary patch literal 10821 zcmd^lc_7r^_xH6`QdE>m5h+`xQmHJXM3%B7q>)h+$`&DFW?EI&WJ%TXn5^SWodXJT}8`O@`E5kkxL^^TlC zh!_6lMN1aJ*YwpN^YA6;u4mpm);3e?y<8zG;@4i&sy-KEgjac~8CAvDxlVxtmKi4^Qh-c;c zTUuW;ytWFiTeWJ5w6yA~B`bJuwSNt1m&Kll9nr;8Fm+g~|3!Y@&{9I3&c+ z#KsoQzB;LgPqUGtzw`SUkgv^roLTTaWHL#$l5jq!utL!%>nHJ!`KVwzE4xIV`X-$f2;lki%(T>zENeISfH~>sr@g33Z1yp|s_&*=W2)vp?|u?_#c4bxoM3N!sZO8;!}#YV zI{V%rPE?nf+zc>eA-iR(Hu>=lo!WoilkTO z#PxBSXhZS%nTwG_f>fQ2n*Ni8Db#*J-!p%5M>jLMp{Xq4LDDv4Vq2ukxcsay?B&Vq zLk%=`O3I6&dtPqPd@q6nulAr*_DR|m^oB8WzHIw;l3g=k4M$<>ICzwuxoFpiw}DwIoB!W^?FV9 z;_?wW+JvZ|uWUHiZR8gtec)K2>&cK=q0hMIh%7%ZWpdK1TyIQOR&H0WK51i3lmTfc z54tC>`rgJ%D!P+&*W}J}32x}PR-(I|;DpF#q}4T-T=ZBYhyhgn=eUwj^sW2(EA8947?S0l1HX{|;nWh&cT65!0n!$v;4J!Hg zXk1;qSNTO#IXiT^Sm*R?vSjECn44V=DZ}nASA38iv}|Yh2M4Y(yK*do17x*^v`zhS z0g=zCv??z-TA51M zSmoM__j*iV@SzhN{gUUex*M2;dk>dq!!gTKjps`dl9y-_ca^IZT_nKibjwZJ#N|OK zGS+l7@wJ@(SWv27`5R7v?)w7`LBfcKfB2CA9Hc23IYe<@qaUIV#E8RY`3& zz2twyFKL^-^Ur{GM|$?O3?H%;Il|b!vA{H{Q(0&=W&P$)Z{y0u#Ssc{@1C8~^-9=O z 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 literal 0 HcmV?d00001 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} +