1- import { writeFileSync } from "node:fs" ;
1+ import { readFileSync , writeFileSync } from "node:fs" ;
22import { dirname , resolve } from "node:path" ;
33import { fileURLToPath } from "node:url" ;
44import { defineConfig , type PluginOption } from "vite" ;
55import { svelte } from "@sveltejs/vite-plugin-svelte" ;
66
77const here = dirname ( fileURLToPath ( import . meta. url ) ) ;
88
9+ // Single source of truth for the app icon. Wails generates the desktop icons
10+ // from build/appicon.png (exported from this SVG), and the browser favicon is
11+ // derived from the same SVG here — served in dev via middleware, emitted into
12+ // dist/ at build — so the two can never silently drift. There is intentionally
13+ // no committed favicon.svg; edit build/appicon.svg only.
14+ const appIconSvg = resolve ( here , ".." , "build" , "appicon.svg" ) ;
15+
16+ const faviconFromAppIcon = ( ) : PluginOption => ( {
17+ name : "favicon-from-appicon" ,
18+ configureServer ( server ) {
19+ server . middlewares . use ( ( req , res , next ) => {
20+ if ( req . url ?. split ( "?" ) [ 0 ] === "/favicon.svg" ) {
21+ res . setHeader ( "Content-Type" , "image/svg+xml" ) ;
22+ res . end ( readFileSync ( appIconSvg ) ) ;
23+ return ;
24+ }
25+ next ( ) ;
26+ } ) ;
27+ } ,
28+ generateBundle ( ) {
29+ this . emitFile ( {
30+ type : "asset" ,
31+ fileName : "favicon.svg" ,
32+ source : readFileSync ( appIconSvg ) ,
33+ } ) ;
34+ } ,
35+ } ) ;
36+
937// Vite empties `dist/` at the start of every build, which removes the
1038// .gitkeep committed to git. Without that placeholder, `go build` (and CI's
1139// `go vet`) fails on a fresh checkout because `//go:embed all:frontend/dist`
@@ -20,5 +48,5 @@ const ensureDistGitkeep = (): PluginOption => ({
2048} ) ;
2149
2250export default defineConfig ( {
23- plugins : [ svelte ( ) , ensureDistGitkeep ( ) ] ,
51+ plugins : [ svelte ( ) , faviconFromAppIcon ( ) , ensureDistGitkeep ( ) ] ,
2452} ) ;
0 commit comments