From f97eede28519193b35bed8d020c90368a86ef4b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henrique=20Ara=C3=BAjo?= Date: Fri, 23 Oct 2026 17:04:36 -0300 Subject: [PATCH] feat: favicon, app icons and web manifest from the logo favicon.ico (16/32/48), favicon.svg, apple-touch-icon (180) and PWA icons (192, 512, maskable 512) rendered from assets/lowlex.svg, linked from app.html so they work before JavaScript runs. The server sends the right types for .ico and .webmanifest. --- internal/server/server.go | 7 +++++++ web/src/app.html | 4 ++++ web/static/apple-touch-icon.png | Bin 0 -> 1039 bytes web/static/favicon.ico | Bin 0 -> 737 bytes web/static/icon-192.png | Bin 0 -> 1093 bytes web/static/icon-512.png | Bin 0 -> 3108 bytes web/static/icon-maskable-512.png | Bin 0 -> 2690 bytes web/static/manifest.webmanifest | 14 ++++++++++++++ 8 files changed, 25 insertions(+) create mode 100644 web/static/apple-touch-icon.png create mode 100644 web/static/favicon.ico create mode 100644 web/static/icon-192.png create mode 100644 web/static/icon-512.png create mode 100644 web/static/icon-maskable-512.png create mode 100644 web/static/manifest.webmanifest diff --git a/internal/server/server.go b/internal/server/server.go index 2ca7ab2..297351f 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -10,6 +10,7 @@ import ( "io" "io/fs" "log" + "mime" "net/http" "path" "runtime/debug" @@ -35,6 +36,12 @@ type Server struct { jobs *jobRunner } +func init() { + // not in Go's built-in table on every platform + mime.AddExtensionType(".webmanifest", "application/manifest+json") + mime.AddExtensionType(".ico", "image/x-icon") +} + func New(db *sql.DB, cfg config.Config, box *secure.Box, ui fs.FS) *Server { s := &Server{db: db, cfg: cfg, box: box, ui: ui, mux: http.NewServeMux(), limiter: newLoginLimiter()} s.routes() diff --git a/web/src/app.html b/web/src/app.html index 410c8bf..2b04b9b 100644 --- a/web/src/app.html +++ b/web/src/app.html @@ -4,6 +4,10 @@ + + + + %sveltekit.head% diff --git a/web/static/apple-touch-icon.png b/web/static/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d0874a34c077be1aaf4b9da220fe966a470ea6e8 GIT binary patch literal 1039 zcmeAS@N?(olHy`uVBq!ia0vp^TR@nD2}o{QKQWbof%%B1i(^Q|oHut3^JGF9j(ub= za%2?pQ0P|RlHw3I;0=jU*y*rhg;02iWuvy1wWz2JLowqn6CHMi3jqrzC{1*l$kZuf zv+>ZZ*1u(&Uw?fwd*=Q1n_~X|wX=W!?#F` zR4C9%9iftdTLm@G%XZF@PqROlw)xTw^ZS++pFUJdE=zl4u`gKf<(D-FE#B3A{`NP2 z{@nZ3QEV%wS{z$7PsY42etkU8M*jW9UlxA*`1JexYXPSgbSzfi+GAyCp1(h^?eLl} z=>@`%pS-x;pmyx!#s%~KJbiUmec9jW9t*J;`>Lg1k_3d4!@jNj*eQ5?-qxCKL+#(! z-yE^9jJo*XNXKHuwZ1)(nci<7e|%p*)eOl0di3x5cXo9Kzc+7jlv%r@{@ziTj~PH{QDiWCz>Y?f#dY*|lxvh^kpmLAS-U&^@u&!6Cj@$c(DBxW{5Dw3GS7lqxc^=qC(QSSI9&A{;g l|F*+^(}3BU4V0gm8Eyu#Ua33Zstpuj@O1TaS?83{1OQd)%g`-$a z){SFszNluM#plIYmnEi7ic)oBVdXF}*^qzw@7=G9lf)g)WdHtW$;)msf4NKCYSk+C zxCyc@+!MC$`D41weqLfJn=NtqgU-p!s0IZM*Ymp>nRXd3 zVV@uJspL$20Wc{4|KGMExfbX&sL$9fq@VE5;bH-b;PV+UvKS1&KD&{ScLB(`3ia6x zZ@xnYJTAPiWVJRXAATM(r#JZH%>vO0N{TFw$?B6&byuD?3!Qh&?^eky^UbMAxhE$G zI5}}}Dyp=2sGC%>-OZoAUVHc7iy!CAU4Q%X!$iS0^)E$Sz2&M`EDLu&?aA6HSLEjE z&GE>mLoH;keu&Pd3-*gv=d201a*WNiv}9%dA^#P}kG*ippS^0@@+R+`9>omXD;M^M z&hYguRQeuJm{oD|w!%Uu|BzovE*>0;iY+Yyz0!~0d!B86ZnAt5*b!SU^%pm^2nabX e5v~Gh0^k{CAy?>cz|Jvf<;NZgI;zD!cn^&rzzx-4~ z8ClusQMDhh-kaOJI-P(1)Ni5U7uFtKyZ%(c0BJeT?Q$TeQ|Eyvh>yGe>Zk;baXUyaAZVB{l7Df zTj;`%Y3Bpas3>gTF!AiFc}fckW$*3YR`V~-j>V+!-HDymMYU&l*DUjLP@ZucXsCwi z;hV37FFZ@L23dFEK~C;V!zYht*H4?pks)k6A821}-_5G_2ED{{+t-Hv(a}4VQ#+xd zZRT227Lx-xYo9+idT{Pw=+`w5-^wtble3$BV6*UTLFqg#jC=6kujJBgl7I%q6xQD8k_B L>gTe~DWM4f3CYZS literal 0 HcmV?d00001 diff --git a/web/static/icon-512.png b/web/static/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..9d14e4211921a8faba3ca7529ead68e178dfe7fd GIT binary patch literal 3108 zcmeH}|2vfF9>+g3CS%CZh$~+*y2_W!c6>P;jH5Bb2q`NkDe^soY*a($WbsJO5ZYvS z^WEs|c2K76BCd$0wWK^5U5T`dl1w9%Fk*~3xBuYmPv^S!+MnL{=eeKf{@mC7`n>Pw zlON#kt*vRK2>{x@KAb=RA{r7wV?)x7JR1SDMtnK!L;T8_QTOB^DdFL~^riYyYwFp& z_qx_U?hGtR@iR8BS|!qw_sg~h9rXF$KXX%|FUQ&|Hilh)=s|kCWt)>`C|T$m8|?Ms zg}QOOWv&5xbI-7JY(cub^6ui6qZ6;cmMBMej@Rb~8)(8mEi|E+1ZLj?T%Z9KKm^@= z03H-zSrI_P9H92k$^X+KT-Q919yOI4L$$(!8jtOT@Ojosz zhku^;kX>&bTYVcGp*$TI*FF&a{CSpa;?WnBk3DN8BbHFpD7P^;`GnLu5CH zGlyQ&nNQN`lFU;{ofp~Jsx6qs?A+Yg=)F+aL>`Y9pq_ilMLCtSbXd6BB+jC+x`v#G z{NfsKrF|Ai79*)4Yw`V|gp1&K>lt0Ry4YHQv)#<#a<2(z3*^O8J;1D-VO0h!S6;ww z0^n>^bo^eEZ}$S`jk6D;ppaoDKn}4Zo9jYk@|18)4_?*dY^4Q=nK(Pc9K`E5yJMG( zb0g_1zwzg((z%N6Rd2|X_fOpZnSF>iAdA=^aU^62GqocS$T8GuZ30m7XKbYzh%dWs zA50~}W{JsQ0uf9uGV0n%P?yc9D?lP()bWrMG3r8*lrieQKvKh~(<8w)3NJuG0XvT= zp_3j&HskC@w2$7hoR_|U+1r!v6al=6p`OquK+j{7K~o|)3d?g0B>nnEKZ;puqOj3> zKQ$kVN6ve5_U&3@-+fhDE!se#7M&-O50`(ASN(uS<<08S^GDXk=*p97RngH ztr?<0H-kpkGDg;nC zC>F0ELD6>rl4!Zio&a*LT($>Eq}&&sW(m&Rfq?xoqvr*f0B0tU;B)neC4>& zES_6)oCtSu=4%qr$}+5okc~4pilKX^OGSYn>=YkK1WbcV&-4MI3TMvvf>7F!p4Ft2 zUTy`P|Lu+v7KOXMT~4t-Lxjerl=&aPPMvDl+$(ebkGqTWhiM7lC2qi=fc~UodH$>H z(_0`u_k_GYNu^a-46H7k>DXPCV^Nk7k2W2HB0mrkxb&Cem7LQKiUArCVq)dBdq~jp z%Z%r*E(LZ}EU~nX%yJ}=ovGms!0n08c-twnJcfQqe=0M zXN}9lkN0pUA|mG5D+b(&8$cI;EBd?PNFKQTh;WXgeOqn5PzCtcXB_@7Qn)6PZfT=l zIYAIjz1IGZLGb*{YM zyVR<`&0J4+u*ZbcssV$@;VHSmQo3#DSZW{^j6B3*+YX*C@{L`{lv#-11~&Evw$jp^ zcw+)KZ%=+|y+N3I4G}hqq+Zh|L3tGQ+G!#bp*d8+|0>IgzX+@aobBiVLVcWFSOctr z(wuFU;~MI-pI%jTYZg`m>ph<==9glB{!4#vLos+LJ4)Mv+#cHsqm$dAtD>f+rn=gO zU>ln}_K>6*Kb8*8Cq#_y!4HFX+ zyZ>>#=+h3nKT-=+SMR}7&v}rqXQ|0?b>iI|up-0<>SJ#n#%XcNSBk-LKa@AOw47Zp zuw|}H&di3k2Cv@hlhvVm1_%2OGRiEty{ad8ZCYLxo^2;E-87`RyR7J zrKQEm>6p@ZYCCJ8Qz1>;6glIziS&EH|Dk)(Iu&a1RjLyI@2$~5eWS@&gA4lV=PQmR Q>7gg!>*dc8c|@N7FA~1ue*gdg literal 0 HcmV?d00001 diff --git a/web/static/icon-maskable-512.png b/web/static/icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..c7855fd128e9bf029e2d5dccfa37cb58286a0b39 GIT binary patch literal 2690 zcmeH}`%_a#6vxlK#wJ9Q3jrUcfm}c+g$MzBK*fXrmP8a$8KsqKd=P6<1f#+f16QE} zr4=mdBqbEak*N+XMN^fR<))$9kq8~p7DOSU1}F$PDpUeVmw%u?JGDQ3_U!EJp8cM4 zc28k^TnvZp$_4UE>xJ_o=g=kj8e<0SUVp?32+O zUFsXpWmwei!h)3s`^b@nZAm@#S3+Q*ehJ8UK>1=&@IT&I3C_3XKABYP-=8sYuhXX@ zd;FDxGdi+0`@q;i+NbHVYTxeK_-)y*iX}aDL07IDGMG8G)@{t{Z{qCT6E!{d;rt&* z?V*Z&KBT7f0+uD%)@2>INnLgTlj#msR?(!IFuWXWrIxb5bo(Lyg{`N1)+TQdZMKkq zECSI^1P>5pS;$RZP|H9dq1Mqtwyg%mdXrT5Ezq|$xuM<|H9MG@?utWEGPiFR4zWsZ zA0vQ}mu0)H>wlyvygRNlh7C*;JwL04F2=~82V>;ZYbniz-#>Quz7?pYDu3a(IN{(i z!tG1OAq=4eB2I=CctA-qHxkHO`~)9}-_559Qt5wnT~V{BD?KEMqT zbDnQ_T9YyClgYkU>9J^4in`IR@5nJQAhc(})#i-Jz%qcCm0_9hm)knp?S``sF!sgZ zX8XZO0%t&`VYt*2=n!QEiGfMH9*0B93L!=X=-25W;#3zCqdfIQ6jWXxHrgE^PovJ% zLd54?`Cbg_r=0AUy)i_N>+^JL&)xLHO2G+lIJfrQM=#zExp>dN!6a@v0rb~eb?8x` zgSF~RuNld#X-Klzo#PKrG2o1G*r;WJFt00L&x1r_5VHLBL<$cy z0zL5#ib{x5uxu45;!NVbB|z_8(^}k7!D;x{H-jn~AF0Wqclom*NjEsqtRDSKkUDjk zp6>{CWJi6@gyGP4l5S&_Z&Kd1;+p$YkIS*{XfPjHt8eceZR*dLY>|PPzqa4DWRmDy zjYI#h!^Sht&>5~L^e8j7D+QKFP?Va)rUIaq8nwm^qc|d~C)$t#O3xmf2g|n|qT8^Lr`WXVs#vqf}g$4ZNagRta&(;&~;n1#CpLc@H>%&ncD22v7 zVnJ3GXKy5G2wB6D%BR)q>>;EaWLXEsUfB92_v>GFMio2oU}5iwJ$$KRaz!N)Ks(4b z7j^fR<;u`bZT#r3fc7^@56+y#^+YEvw2*8DY;EPYTtfb~@LP^KK-1B%f+`+_&Qm$I zdO_Mp7IOXvV4iD|3JY&Yjas)hsekh-^N>{{zGvTK%Db}|-NKLCUnzMo^?*IFSXntIqtC@pQs_onz zR^-V7mE)E;6ftdXrxHc0jo)&Z2X!n9d8H)ZV3-}I%XMF=yQPZwFdU=iB(rv8X(%|$ z0CF|__YpwU`8GE9PERzubCgfYrl$$XRJWoq34>?{RPOLP<70Q>pSI;zX0O}aM5E1S zG(=vT`3d0nojCr+ew43$pLE`i0od)h(LDiml5fqlkh8$YCp=Bax!{IoK)xz2x+YR_ F>>q^MB;o)7 literal 0 HcmV?d00001 diff --git a/web/static/manifest.webmanifest b/web/static/manifest.webmanifest new file mode 100644 index 0000000..e25dc56 --- /dev/null +++ b/web/static/manifest.webmanifest @@ -0,0 +1,14 @@ +{ + "name": "LowLex", + "short_name": "LowLex", + "description": "A light translation server", + "start_url": "/projects", + "display": "standalone", + "background_color": "#171a17", + "theme_color": "#171a17", + "icons": [ + { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" }, + { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }, + { "src": "/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" } + ] +}