From 108a4618331b7298f60592c3073e8e0f633998f7 Mon Sep 17 00:00:00 2001 From: Eros Taborelli Date: Tue, 18 Nov 2025 15:07:12 +0100 Subject: [PATCH] feat(pwa): Make framed installable offline --- .github/workflows/version-bump.yml | 64 ---------------------------- README.md | 2 +- index.html | 14 ++++-- package.json | 2 +- public/favicon.ico | Bin 0 -> 1150 bytes public/icons/maskable_icon_x128.png | Bin 0 -> 1457 bytes public/icons/maskable_icon_x192.png | Bin 0 -> 2342 bytes public/icons/maskable_icon_x384.png | Bin 0 -> 5353 bytes public/icons/maskable_icon_x48.png | Bin 0 -> 747 bytes public/icons/maskable_icon_x512.png | Bin 0 -> 7034 bytes public/icons/maskable_icon_x72.png | Bin 0 -> 911 bytes public/icons/maskable_icon_x96.png | Bin 0 -> 1231 bytes public/manifest.json | 56 ++++++++++++++++++++++++ 13 files changed, 69 insertions(+), 69 deletions(-) delete mode 100644 .github/workflows/version-bump.yml create mode 100644 public/favicon.ico create mode 100644 public/icons/maskable_icon_x128.png create mode 100644 public/icons/maskable_icon_x192.png create mode 100644 public/icons/maskable_icon_x384.png create mode 100644 public/icons/maskable_icon_x48.png create mode 100644 public/icons/maskable_icon_x512.png create mode 100644 public/icons/maskable_icon_x72.png create mode 100644 public/icons/maskable_icon_x96.png create mode 100644 public/manifest.json diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml deleted file mode 100644 index 2373323..0000000 --- a/.github/workflows/version-bump.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: Version Bump - -on: - workflow_run: - workflows: ["Build and Deploy to GitHub Pages"] - types: - - completed - -permissions: - contents: write - pull-requests: write - -jobs: - version-bump: - runs-on: ubuntu-latest - # Only run if the previous workflow succeeded - if: ${{ github.event.workflow_run.conclusion == 'success' }} - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - - - name: Configure Git - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - - name: Create version bump branch - run: | - BRANCH_NAME="version-bump-$(date +%Y%m%d-%H%M%S)" - git checkout -b $BRANCH_NAME - echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV - - - name: Bump version - run: npm version minor --no-git-tag-version - - - name: Commit version bump - run: | - git add package.json package-lock.json - NEW_VERSION=$(node -p "require('./package.json').version") - git commit -m "chore: bump version to $NEW_VERSION" - echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV - - - name: Push changes - run: git push origin $BRANCH_NAME - - - name: Create Pull Request - env: - GH_TOKEN: ${{ github.token }} - run: | - gh pr create \ - --title "chore: bump version to $NEW_VERSION" \ - --body "Automated version bump to \`$NEW_VERSION\` after successful deployment. - - This PR was automatically created by the version-bump workflow." \ - --base main \ - --head $BRANCH_NAME diff --git a/README.md b/README.md index b5c805a..8801bfa 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ A Vue.js application for creating beautiful layouts of two pictures with customi - Configurable frame width and outer border size - Drag-and-drop image upload - High-resolution image export +- PWA support - installable on mobile and desktop devices ## Tech Stack @@ -80,7 +81,6 @@ This project uses GitHub Actions for continuous integration and deployment: - **CI**: Runs linter, tests, and build on all non-main branches and pull requests - **Build and Deploy**: Automatically builds and deploys to GitHub Pages on every tag -- **Version Bump**: Creates a PR with a minor version bump after successful deployment ## AI Disclaimer AI tools have been used to contribute to this project. diff --git a/index.html b/index.html index 8101ceb..f2652e6 100644 --- a/index.html +++ b/index.html @@ -8,11 +8,19 @@ Framed - - + + + + + + + + + +
diff --git a/package.json b/package.json index 19b822f..5e0a840 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "erost-framed", - "version": "1.0.0", + "version": "1.1.0", "description": "Canvas-based picture framing application", "type": "module", "scripts": { diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b96266e415cce08835ce6193a19fd8ab86e78e38 GIT binary patch literal 1150 zcmZQzU<5(|0R|wcz>vYhz#zuJz@P!dKp~(AL>x#lFaYJyL7=1ge`;cXd(;1Zb|zRc zNDiM}0S;#W%d?aJPwi>@Kc%}B1%t$@^D_wQUodm(|8wWh|37{DGzva+$+&WEcIeeyFV@TAAqpl$BB#&tl`dNQwh=&JQYZwQ}H(`KX8_~#A zBLFQi0$LhJ)@owRKV809>t9|QJeGyM44{oN=`KF8$W&g}c|$MaJ@! zVON9WCp7z}s+i@7Z2d`_W^aCysF<>mUw&x8Sm&d0fqVOSe4KFYs!xI zCoikr5ngQcg=tXr%&DaZ7f2+-JY^)BA)n*2z zBR460-q!Zn8R@#H;ZeBNSnkV!XC;r_>0qDaRhbUu%*-FsAZV$`kA$#tOm`a~thv^! zKi|1^p~?pv0sVa&U}Y>xMeMC39{--nT-uUZHU6RjEhYJ{@S`In^i>Q~UOtxf5w)(B`Q!Rg+)`sewo6cGbYfb57E0gg|xW90vzI72)2B`DEJKF%2pb|ee5 zEPE_9Hx>KNr_#6g{QZD}(J&G#HYQ7GLyc_pEd`!?fXg6OK1@MY!lH(nBAvJC#y#-# zlDIjip=21oG`-NYxvsc4YX`(%dG%7YU{-gV&4QHmjah}|i{taC_ej_2#pJ;!qGn0g zmDKk-+BDYI0N8x_k-zVXjK!enmhGwi-INS2&vwqLkkwRk*&Kc*Sv+UzcFr8S7fS51 zprm(`qZYz{us!J#)?D$p+XM%-PGcEcU~KR8P8x`(m>e>4?4CpPIt*MmzBGiR#b@5$ zO@PpZ9^<3X6Rw+o4QQ`(8V_J@oc>Cwi-lJObFKMui;~v|-3zl#q`ud#I&F~s(I;1r spW0^2jx4~mz3cs+{RKz^dLo?$IpleTebDFI*RQ=xCc~31bqx~y4O%iu9smFU literal 0 HcmV?d00001 diff --git a/public/icons/maskable_icon_x192.png b/public/icons/maskable_icon_x192.png new file mode 100644 index 0000000000000000000000000000000000000000..f651d193e9aa2e1b48767186fcef9c012424ce7b GIT binary patch literal 2342 zcmd^>`CF4$7RT@V@)8n(A%G(oXbC%xC|cVNTC>nDkws&NMwN3L+r;PG9DSnLnUE%`-ood+u`X`QGO_pXWUH zmX{}0c@JR^06>}MMq!{{ylYqtIxvPXLoT~IEbrUiR=fWM$~EP%dc z0%SJ?H3Dh?$nhZ{hk9stj}QOnRLqzA?|e7V|q^QK$}UrkNlRcXCc^T>pwIY;$^#3#MO8`jk|(A#Usz!-RxN`}TG9$3fP zFtvDsV{hWk=zlBp<`oNvt_>zqZh4pGO1c$PuxSQ;IH{F~%dh((B=BIG5gU}ee-MWR zs-zk9HCJwA9*>J0HNSw*4~11)HjEzeEXg<0IBp1@$QWKMP$jdKaB|sLBKf{x(n_BV z_N!s^&`meyK&UH#EDV$=dTfy0Up|xp;BVYCZ&CoHSLRWLYISCr<8J|&;$9eF31hQ# zgNSMnax?d+Fc{74(ndCbvG@bw*Spc&e@O7x;cGV*V1C8@oS$?8{F-u(OD?p`@@M_n zuiTbj$}*2hZ9d;8v`;vz?O`v7DN`7NU&j_ry_<7yPq5J9RCt%Ar_0w*oUDgWb*p|z zT^Xa#ifVEw$ODCH>DB1gM_=-|WxV7q2Z!Sh9;2SmN2}DMjM?0$)NaGjsv(-r*p9iw z>hyqYjZhc(Ckq|MMFw9hYCRxBhFYN_36UG0;y@WDWvuAP3setE5<{cJ^t6s*xGCVdPI(okDr{I zt8TQtIyV2L?yabMW`16jHN{-7k2DdalZCb?Tet~55#>tRx-q*unVPP_} zNE5 z{A#9^F&o&byTT|VBk$dgYEh zp4bd> zy?+-XThyKYCj%I1EUev%9vEavu9k{ z_o7;-dOS1FK;j9r$hmUq@z8Lo5FtzsFQ*?XOm1)% z3&Fsso|ts!s~w>O>)HBu3mdobaHr(bLT?>SKP*Z2p8-I+8hh?RYHDgsLV|rGt~mT) zN5YbS_g4SlVBW^~s3H+}8&IiKW^%IQ(sf-w(a)0b-ux^2;wLr*g(Jm-Z!Sg4GqUU; zk%rr6wu*izKY9K9eX%f>f0rwNNRGz@C{*X-~r{!Cs8h^I?wc>J*YYtQ~OYz3}R)bA!vg-?VjrQ8b@T?MeP%y z-OIGh>ChB{C;uPIIxPKpHnO#%;$FfW%a-Go;f(G3xZFQ86G2eIVCUwA$!k?~I-N-( zoJ*QnGMkat%zU2X(bCjZ;Op!AYjtC=b1qz6Z6I5A`spat1oV+I^L&_?HJgR zbdoZ^4)3j6SzEIeR8pCr-U>-kEbnPwAXSR`=%{^kXlHuMzwzCEUMOU+ir8q`l=%03w;x+&F_0b(FAYfXD`f+%xT_5Mr*S zoX$jhiSmobL3seqzjLFFghGkAIA~4>P?xJq5CJ7B)gmQW qNBfdc+Lh9s4y>bZos zC7O1j`ve3do58RXPdvdIuHzZdNJR8%Fk}H}U%AG_5JzAXqsaC1WoN()b`}iiI6cGz zOrM5e8KF$aRRolik0NtM{}w)t|K`XqxjV7z&$s-Xv^2U&YjN%)s&&Z0V2mB#j)m`g zdw*nMA^y!aqjHBy>85uIQc=ZZxDjY9w6(G6X^}`A8+GWRv{YL=KJI|)q--EI&3=N{ z{&uA1#8D(EHvn$6u6B}`nVH=Vz7wl_w}C(N+iABtNT-eJ z@*gst4+<`c+N4-=WRQOx`}__6DRHAbR{5xn)@|mVF*c~jf+H74WF?#@g-uQiZE1(h zXJlegfqzL&u(;tW6!~*GLf^3`E-&o}rE^r!$R8~#PJ7U}a6rBn;X6@TCKh-+o+Q=^ z)PGpTUU7RVjHz1M+}GPO;;EK72{P1&oeV!o%J?L+4s&<;&9#G4Q;Z$!wxBp!_C!sV z1<|a~jwZpqcClVe7`d7We`KV|M{5kI?G$MmktQFb_3(*RVP z(10Iy+|`Hwe2(`pZ-zET+lJi>QBw|9%gWi|S=p~P5GWZL4T^eNn42KM*wi@`j``8P zxoDf(;$c@;kaB7u?@Pj2@2!6JnNj1sA{Wv4Kr=}#%Px`Rk>J)1T$wiCNct$(L^LfK z3cXyhdnPgf;mXJVh&R~#_kc@* z#kDH|m#P4ln29R^?4kk8zEABw4q(Rxu%kcyNdvpD7*O>4C{qpW=3AnBtxOgH*!^D{ zeT(FJ9?Bh7Ptl7|g#N>R?KSzn!v6j%jcLh(?yoySnA2%6W=yuF5^Q8$)xo3U-l#XK z*W45erSn%`>*v?DQnC^6C8y5mwr(UVZna52ru&=SF;@wdqDfIfN@}WePW!W|e}|#? z@T_59wOm|O>m{ZhnEiqypBLM@RHgGJ;oJIodM}OY6i?e;k!TqXlr#EyVKYkN59yOrILt`+KG`<#I*&KYfHBK3w;+{hFyS{@UTIBzBN7=UMMgRoSp! zYGUFo>M`c>7euzn*h$)?VI??ShfaOhG_F-q5W)0gifvP4BDTJ})Yi{J@6}&U$5oji z?$aH)LGa6#ms}-Ou=Q3?9Fk?%ApS?w@aUWXRcMdQV76I z?CZ<4Li@VnMEm_;RJ7j>N3LlZ6E1(tBB{ct(-G<8{hpr}OI8GP_+j5j?_@b#OO$BV zDta;dqzvNmc-=YX)DJ^7{A&*CEGBLK2dVV7Tk1qdK3>Uy65o-rfb>5C(#I$20Mg@fP~`Es z?6m+)1~v@n!IKr5@Ua{W^7?{_15T+!5ncRI90(tYx|Zm2XZkS^KIV+h`E*WFf7KJ^ z<@|@;BPIqsYnb8}v!Z&Als-}Sn+!*UY9<=G2PY?OA_IOcT{ zOP&%R|J=-#^1RqR^Df_cd1wH+KBTswpdjVr>xvtgMpHVChb60)Ryxs(^X1|D)6*}zshqT3OAwclzX4ztX0e>C)A31Mg_He=vaTzZ6T>ksME@*l6KLJjF z7ueTp-t{uA3?oYA1)JdD*@OqUvgk&$zz|3&&XRt4=Awd#eoLeKl|Kfu<5Dkop zP&Tp4COw%dP${Q}L{n3Nzt`1;%zmQP>OEuYBYbXb+G@ok^*xH@*CPsbrQqTySHXU> z18!aa;6~G#dPR&nkEXgYJJQhT4+Z``(kuJZ@Ct=*!B4N( zHJn1|d+YcGpSsxW$sGTZw)nKwBxAZ+K}VC-C@C2ao{an5x+0eqR_j?T8VhHfd|-zK z9A1SnCY08)0kQMF39tp0YYE_f0xbMoH%}ABR>7Ej%LP}#trNGC0DDBc`{s=PeSNy8JThp_#b%9ua0V8_6$FFZ;Tl=_5#as44_!gE zE>OtE=V!q?lHdqrWo;6gB0F2&*5QUU<&ngaSX{| zeLKtBTiH?I`2WvdXT0RJ4(@20zV~gV{S7&B|9LDQ-)#RRBM=i7Qs#QM-LpXPq|clG zCmf`BBTRcY7D}m2K38H}7ixQXt``%7adE}%q^f@}KZ~2#ne1))QEz|b`#-}X2CMzI z-c+y#SV)WI*Vu+LoIW?_yX1-dBwvxsCRaOjr*Iw?a1_wlv+qTdL_%6vuLa-6y<0mq z`V`DFcOP=q@HUQ#y`N+>vqMpYK{D#B*|)O&i*DaFV9RYkV(VN`ZhmC@UgnsXe@-H< zN}^m0PbRKc6|B1-((NkalU*YrC*MSBRqn^zCmi^Ko;a7)2{RZ? ze|u51LAL+;`%uY>zcX%&?LFU+rF~GMKzhQg*pz9hWgacI>zHTR1|+(%IyA2hjS%GM!lhIDIbgMcb#hZJ>!%~nB;_`uV20}lD5nWPIuT}c1s|p_3Ki@;N@Gd z?p@>Fyiv1t%k8&8Q!S&E9rni6&wQBf*2%ad*K@gMTH5!oh1JI`KJl}|FfeXH&@>a>^vF2-{eLat8Oi^yE$~<_ z(Qw6N$`P%=F6-P^%O?cudugm@@M1aNxdIrG?_K^C9@-xE<4o#`GhX{j-mzA3+HN4!R+pA(Kw>SF z5N_xPSf%LHEdncKhOO;PE$A%PfP{qB`jw&)yM=CnL`pyeQ7}LZN$ANryR$R8GEv_z;EHR01(x$0?NAt{?@`D06Z-LcyJ`Vf76ox{x1o%y#G9V7YZF` z-i0rXWuzqip_I5Yyy>%#|G4Vn%?~@pm#FtP?+QJdbl`7-r>m+ym!z6gg|Acbg@z-C zQ%{@w9}5>G(bo?J^u9xlU!bOwlRfc&pLwD1Zd$t7QZb@$p07%5*wuVa7A>i8)h*Ku z%K?J)4;YFsc)s-^JX>BvgROj$63|SsmIKcePo_SGmXSs&8mSd4Y2Y6{e960nWr4%b zJ90)1Nm`8`hcrNmlt2J1Xr!On&Vo?gz6ddrPFO?!r87{#@#+fTf;%kGVS zWj{6%fXvc_YZfi#izQ3;SM5`Kfod+%V|g$lYOOClh6R5rcHD2tGq@Iq&$g~{L~u2x zuaH6cB7!(|F)S;|>lzhK5cJ+M{L1t?1}qG=K90;~*E1kIT7=BfY@sM)SovnY*K)ds zqS*7cmyl(rsyQ(Da@`4R^bro!=n}Re!3#7E%BQcdL^_#=Xb@aqjVw2Ykz{_|mc}Y% zW(r9%qjRxH@Zj%RFnv1hIqY9L3sPiZcx%fA0&dGfK_Jpe2MB!5_)f+bX5MW0ubi=} z?H$ztst=4Nx%-OE-?BV2k#N%x&RR`@t{G8fclZ3*otUL3uZnd7AnAQlTx$DMU5vr? zAgB5JyARfp)YhnbKeo7YfvWLq!wdAiG$1Va0H@<5%vz`4a0|-XjW8eio6|6^?IVcT zinnKSP};ACNI^D6V5I5dz_FgB#YhB;LMVXf3q~m%o6CZ27VQ#77d`|eZd`yc;8-*R zP86Bl7%Hkbu#;83gLH0#xO+o-%Y#KH8RdQ*-1wzNW3@zG+Nsy)#!s)*yiF+-is);J z%dRAG$oyIexNC1$_uQ|Qj_4A~=ElsEwOQ7K!i2Z%x8`nt)~=rAHLpL#SnI%QbLcu` zaFg&w`EGxMZ~FCxilSGGt#RMr4NZx%0oHQ}>bato*^atydT$ zo0=av2dQhYpdob~n_sDsyXC;V4#YB&q%D zpb)cVB0-poA{8m)84Hez%LydlRwM(Qch1*hdpbF= zA##C40?auqu>Wu%B-pD~<8ugZm+ypN0Qo`=W~kPeLq88FEH33^)G`>9X!3s(F0P*JdQnl^ITF=6P+>(l$e1}@2TTm6qp!+eXWNWNULSlA`;767V^@V-Ii zhwWyeSZjYRzRIGwBJ6kQ1_rE3njgg=5Xc{?ygO{VbK{fiA)}y1J&Zq$ zaBL<~NtsKcqH!ni8m!tsZFGdH3AeJd6S{x2t4U^nh z89f98E?w@9izIn!ES;s=tkv0{%q?FR~xcdOq{nqa^RvkLL{8yVR4b zemyblb#pFmS*Cub{`r?rSF^4De(F83VUkZ{#dF?vLEEYy4Q&?%x0bFbyvpY2kbiIA z;>+tjCqKSt8N48?Wcik;wJ+aPJ4H_0IXCnFE`{)u$#-lmKW=h<(|G4i@pUziNiCO5 za#=f8rx#h5Dc^q2qwf%7V)Js{YvZkfjy7S(nfb!C{6r!bJ}fhE_{M&H>8*zhI}huW zv~T(PR-xfX$)gN|1t*_O+s*W_j>lh&pJ~N9Df#~bd|WHqHtk`bu!vKEL6gZ#N|Z&x z)xmRd6T=b?jm!{%1`$TpUap{qJtk*%Y(DP0X4S;2L8n6_pKrbV%%R40&Gpw8ORP+5 z!`H6eaR2@8k6YZ|&OffWY{txRf%0$LZtI?XUL2)2eeIVeJI@- zID5JVhU~YiGAWvCcl>~&+E!N{1x6)j22VjjW{-vw0uDhgM;L?@j94a!2pTr9bnq~$ zxVjKfvKQz=^E+jS&wL6_{jXHX_-dE7RH2Np`K8*j->+IfNF+*B{bXXORxrP*(e>iT z55Mei)2sytoP%$PbUdG)Yxd>g<#efj_pf|;Z~whH?r%Qrx5v)J&-X++RK>dEzr6X$ zoj<=O|59AK^yl-pXET57E}k{deC^@rbH`uLwG>!?@3_m}m0JEipK%7_+4oUiH79R} lF8$?wPiw*I%$$|1{}@VF^`^~{Ep!EC22WQ%mvv4FO#n1+fWH6$ literal 0 HcmV?d00001 diff --git a/public/icons/maskable_icon_x96.png b/public/icons/maskable_icon_x96.png new file mode 100644 index 0000000000000000000000000000000000000000..f6e24eeeb82e5c54b8015cb365ba7e62b9393aad GIT binary patch literal 1231 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGojKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(;}uz(rC1}R)=9Ph`#z+&m?;uuoF z_;yZgzL29x8^1_KW6*|No~YSZw1pq<|8PwD|3>k9KbU>4%(~K_k<7|`#VhIZr>Apr zx1Vd-a+&vx_3BDb4r}Y%#bxu-Z?b+X;Zia(_P0|K)Nng>ddqYcFU`)k-`1JTx}7XcI(rVkIFkQ=bU@%As6EuX)4)0Y=^_)ZUY@jld4nqRS*bpzO+wM1zKLu|SrBB5>vU?epr2VRfv{oaZbYP<^@cX7S7!5H+%N%Wo{<+ zqL;KB-nY!{ck>L*Fstp(J)35tgI>=)JwJFjN-Z9AASVfUjLTh^=BrBB>G*lDwZ z;cSLp`7(>|(@U)8w)W3UWxWtQVV=-w(coEqzm7MYp4-m7<3zUJ(FcvcQeOT$aziza zxh9S2d$2>ofqfrD9w>|Kn9sz-{H=94gZ#n+e?;`5klTJRfPvt*Nq z*z;vcN*o$0!7f>~8F6w^GeXy2pIqtt|MjC7);N=^{?XCVn>IGiSNf#((8~Qng-xUQ zbEo@^lTU`6JLk(|MYeRv-F*{CznglDt~swXKl}%>r!eC$5$}V_WAUA zzM*FMchTr2+@cGZ&qjxC;g-MuNZgRzL=g8^%*5uUrEE@%vcaF9)3=_R-#Ax6{mzbm gCr{Y0x?cOnZo+*k(t6Tf2T)<+>FVdQ&MBb@00#~N`2YX_ literal 0 HcmV?d00001 diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..9962870 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,56 @@ +{ + "name": "Framed", + "short_name": "Framed", + "description": "Create stunning layouts of two pictures with customizable backgrounds, borders, and orientations", + "start_url": "/", + "display": "standalone", + "background_color": "#1f2937", + "theme_color": "#1f2937", + "orientation": "any", + "icons": [ + { + "purpose": "maskable", + "sizes": "48x48", + "src": "/icons/maskable_icon_x48.png", + "type": "image/png" + }, + { + "purpose": "maskable", + "sizes": "72x72", + "src": "/icons/maskable_icon_x72.png", + "type": "image/png" + }, + { + "purpose": "maskable", + "sizes": "96x96", + "src": "/icons/maskable_icon_x96.png", + "type": "image/png" + }, + { + "purpose": "maskable", + "sizes": "128x128", + "src": "/icons/maskable_icon_x128.png", + "type": "image/png" + }, + { + "purpose": "maskable", + "sizes": "192x192", + "src": "/icons/maskable_icon_x192.png", + "type": "image/png" + }, + { + "purpose": "maskable", + "sizes": "384x384", + "src": "/icons/maskable_icon_x384.png", + "type": "image/png" + }, + { + "purpose": "maskable", + "sizes": "512x512", + "src": "/icons/maskable_icon_x512.png", + "type": "image/png" + } +], + "categories": ["photo", "graphics", "utilities"], + "screenshots": [] +}