디자인: 게임천국 느낌 아이콘, 홈 단순화(큰 버튼 3개 + 탭), 헤더 로그인/계정 메뉴, 로그인 페이지 분리
- 아이콘: 게임패드 + 천사 고리 + 반짝이, scripts/pwa-icons.ts가 favicon.svg와 PNG를 한 디자인에서 생성 - 홈: 방 만들기·코드로 참여(/j)·컴퓨터와 연습 버튼, [게임 고르기 | 지금 열린 방] 탭 - 헤더: 로그인 전 [로그인] → /login, 로그인 뒤 닉네임 → [설정][로그아웃] 메뉴 - /login: 로그인만, /me(설정)는 로그인 안 했으면 /login?next=/me로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,20 +1,44 @@
|
||||
/**
|
||||
* Renders the PWA icons (docs/07 §11) from the favicon design with headless Chrome.
|
||||
* bun scripts/pwa-icons.ts → apps/web/public/icons/*.png
|
||||
* "any" icons keep the favicon's rounded corners; maskable/apple icons are full-bleed
|
||||
* (the OS applies its own mask) with the board inside the 40% safe circle.
|
||||
* Renders the site icon (docs/07 §11) with headless Chrome.
|
||||
* bun scripts/pwa-icons.ts → apps/web/public/favicon.svg + apps/web/public/icons/*.png
|
||||
* One design (아케이드 게임기 + 천사 고리 + 반짝이) is the source of every icon:
|
||||
* "any" icons keep rounded corners; maskable/apple icons are full-bleed
|
||||
* (the OS applies its own mask) with the art shrunk into the safe circle.
|
||||
*/
|
||||
import { chromium } from 'playwright-core';
|
||||
import { mkdirSync, readFileSync } from 'node:fs';
|
||||
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const PUBLIC = join(import.meta.dir, '../apps/web/public');
|
||||
const OUT = join(PUBLIC, 'icons');
|
||||
mkdirSync(OUT, { recursive: true });
|
||||
|
||||
const rounded = readFileSync(join(PUBLIC, 'favicon.svg'), 'utf8');
|
||||
// Same board as the favicon, shrunk to 80% so every stroke stays inside the safe circle.
|
||||
const fullBleed = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" fill="#E3B76B"/><g transform="translate(32 32) scale(0.8) translate(-32 -32)"><path d="M12 22h40M12 32h40M12 42h40M22 12v40M32 12v40M42 12v40" stroke="#7a5a22" stroke-width="2"/><circle cx="32" cy="32" r="8" fill="#1c1e21"/><circle cx="42" cy="22" r="8" fill="#fff" stroke="#1c1e21" stroke-width="2"/></g></svg>`;
|
||||
const INK = '#1e1b4b';
|
||||
const DEFS = `<defs><linearGradient id="bg" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#7c3aed"/><stop offset=".55" stop-color="#db2777"/><stop offset="1" stop-color="#f97316"/></linearGradient></defs>`;
|
||||
const star = (x: number, y: number, r: number, fill: string) =>
|
||||
`<path d="M${x} ${y - r}Q${x} ${y} ${x + r} ${y}Q${x} ${y} ${x} ${y + r}Q${x} ${y} ${x - r} ${y}Q${x} ${y} ${x} ${y - r}z" fill="${fill}"/>`;
|
||||
const ART = [
|
||||
// 천사 고리: "게임천국"
|
||||
`<ellipse cx="32" cy="14.5" rx="11" ry="3.6" fill="none" stroke="#fde047" stroke-width="2.6"/>`,
|
||||
// 게임 패드
|
||||
`<path d="M20 21h24a10 10 0 0 1 9.6 7.2l3.3 11.6a5.6 5.6 0 0 1-9.5 5.3L43 40H21l-4.4 5.1a5.6 5.6 0 0 1-9.5-5.3l3.3-11.6A10 10 0 0 1 20 21z" fill="#fff" stroke="${INK}" stroke-width="2.2" stroke-linejoin="round"/>`,
|
||||
`<path d="M19.6 26.2h2.8v3h3v2.8h-3v3h-2.8v-3h-3v-2.8h3z" fill="${INK}"/>`,
|
||||
`<circle cx="43" cy="26.6" r="2.3" fill="#facc15" stroke="${INK}" stroke-width="1"/>`,
|
||||
`<circle cx="46.8" cy="30.6" r="2.3" fill="#ef4444" stroke="${INK}" stroke-width="1"/>`,
|
||||
`<circle cx="43" cy="34.6" r="2.3" fill="#22c55e" stroke="${INK}" stroke-width="1"/>`,
|
||||
`<circle cx="39.2" cy="30.6" r="2.3" fill="#3b82f6" stroke="${INK}" stroke-width="1"/>`,
|
||||
// 반짝이
|
||||
star(53, 11, 4.6, '#fde047'),
|
||||
star(10.5, 14, 3, '#fff'),
|
||||
star(54, 53, 3, '#fff'),
|
||||
star(11, 54, 2.2, '#fde047'),
|
||||
].join('');
|
||||
|
||||
const rounded = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">${DEFS}<rect width="64" height="64" rx="14" fill="url(#bg)"/>${ART}</svg>\n`;
|
||||
const fullBleed = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">${DEFS}<rect width="64" height="64" fill="url(#bg)"/><g transform="translate(32 32) scale(0.78) translate(-32 -32)">${ART}</g></svg>`;
|
||||
|
||||
writeFileSync(join(PUBLIC, 'favicon.svg'), rounded);
|
||||
console.log('✓ favicon.svg');
|
||||
|
||||
const ICONS: [file: string, size: number, svg: string][] = [
|
||||
['icon-192.png', 192, rounded],
|
||||
|
||||
Reference in New Issue
Block a user