fix(front): 루트 /favicon.ico 를 discovery 배포에 넣는다

미리보기 카드와 일부 브라우저는 <link rel="icon"> 을 보지 않고 /favicon.ico 를
그대로 요청한다. vercel.json 의 SPA 리라이트가 모든 경로를 index.html 로 보내서
아이콘 자리에 HTML(text/html 2,589B)이 도착했고, 공유 카드에 회색 링크 아이콘이 나왔다.

public/ 은 infinith-demo 배포와 공용이라 파일명을 discovery- 로 나눠 두었으므로,
빌드 때 이 배포의 아이콘만 루트 이름으로 복사한다. infinith-demo 빌드는 그대로다.

검증: discovery 빌드에 favicon.ico(16·32·48)·favicon-32·192·apple-touch-icon 생성,
기본 빌드에는 생기지 않음. tsc 0 에러.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Haewon Kam 2026-09-16 09:27:10 +09:00
parent 216b2c4217
commit d1c846b6aa

View File

@ -1,5 +1,6 @@
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import fs from 'fs';
import path from 'path';
import {defineConfig, loadEnv} from 'vite';
import { supabaseSync } from './plugins/vite-plugin-supabase-sync';
@ -54,6 +55,26 @@ export default defineConfig(({mode}) => {
return {
plugins: [
react(),
{
// 루트 /favicon.ico. 미리보기 카드와 일부 브라우저는 <link rel="icon"> 을 보지 않고 루트를 그대로 요청한다.
// vercel.json 의 SPA 리라이트가 모든 경로를 index.html 로 보내므로, 파일이 없으면 HTML 이 아이콘 자리에 온다.
// public/ 은 infinith-demo 배포와 공용이라 파일명을 나눠 두었고, 빌드 때 이 배포의 것만 루트 이름으로 복사한다.
name: 'infinith-root-favicon',
apply: 'build' as const,
writeBundle(options: {dir?: string}) {
if (!isDiscovery) return;
const out = options.dir ?? 'dist';
for (const [from, to] of [
['discovery-favicon.ico', 'favicon.ico'],
['discovery-favicon-32.png', 'favicon-32.png'],
['discovery-favicon-192.png', 'favicon-192.png'],
['discovery-apple-touch-icon.png', 'apple-touch-icon.png'],
]) {
const src = path.resolve(out, from);
if (fs.existsSync(src)) fs.copyFileSync(src, path.resolve(out, to));
}
},
},
{
name: 'infinith-head',
transformIndexHtml(html: string) {