Add DESIGN.md (look-and-feel SSOT) + rewrite HANDOFF as next-session entry point
- docs/DESIGN.md: exact color tokens, Impact typography, component catalog, assets, Do/Dont, pending 06.09 design changes - HANDOFF.md: accurate current state (single-match v2), correct file map, 4 SSOT read-order, confirmed decisions, prioritized next-session tasks (multi-match A / detail B / firebase C) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>main
parent
e43cc08429
commit
0a96babc98
123
HANDOFF.md
123
HANDOFF.md
|
|
@ -1,83 +1,72 @@
|
|||
# TriplePick Web — HANDOFF (다음 세션용)
|
||||
# TriplePick Web — HANDOFF (다음 세션 진입점)
|
||||
|
||||
최종 업데이트: 2026-06-08 KST
|
||||
작성: 프론트엔드 R1(mock) 완료 시점
|
||||
최종 갱신: 2026-06-09 KST
|
||||
> 새 세션은 이전 대화 기억이 없다. **이 문서 → 아래 4개 SSOT 순서로 읽고 시작**하면 그대로 구현 가능.
|
||||
|
||||
> 이 문서는 **새 세션에서 이어받기** 위한 것. 새 세션은 이전 대화 기억이 없으니 여기 + 아래 기획 문서만 보고 작업한다.
|
||||
## 📌 새 세션 시작 시 읽을 순서
|
||||
1. **이 파일** (현재 상태·파일맵·실행)
|
||||
2. `docs/DESIGN.md` — **룩앤필/디자인 시스템 SSOT** (컬러·폰트·컴포넌트·자산·Do/Don't)
|
||||
3. `../Worldcup 2026/000. Plan/Task — 랜딩·디자인·프론트엔드 업데이트 (06.09 회의).md` — **할 일 전체(우선순위·금요일 스코프)**
|
||||
4. `docs/BACKEND.md` — 백엔드(Firestore·함수·채점·Resend·투표창)
|
||||
5. (참고) `../Worldcup 2026/000. Plan/Landing 기능정의서 — TriplePick 2026.md` / `Landing PRD — TriplePick 2026.md`
|
||||
|
||||
## 0. 이 프로젝트가 뭔가
|
||||
2026 월드컵 **TriplePick** AI 승부예측 랜딩. 한국 vs 체코 단일 경기 R1.
|
||||
사용자가 GPT·Claude·Gemini 예측을 보고 자기 픽을 제출 → 같은 선택 AI 확인 → 공유 → 100만원 챌린지.
|
||||
## 0. 프로젝트
|
||||
TriplePick = "AI(GPT·Claude·Gemini) vs 너" 글로벌 축구 승부예측 랜딩. (※ "월드컵" 명칭 법적 사용불가)
|
||||
픽 제출 → 같은 AI 확인 → 공유 → 포인트/100만원 챌린지. 모바일 우선.
|
||||
|
||||
기획 SSOT (상위 폴더):
|
||||
- `../Worldcup 2026/000. Plan/Landing PRD — TriplePick 2026.md`
|
||||
- `../Worldcup 2026/000. Plan/Landing 기능정의서 — TriplePick 2026.md`
|
||||
- 디자인: `../Worldcup 2026/000. Plan/002. Landing Visuals/TriplePick2026 Profile image/`
|
||||
## 1. 현재 상태 (DONE)
|
||||
- Next.js 16 + React 19 + Tailwind v4 (App Router, TS). `npm run build` 통과.
|
||||
- **단일 경기(한국 vs 체코) v2** 구현 — 디자인 002/003 + 사용자 디렉션 반영(Impact, 민트 #85FCA8, 틸그린 GPT, 클래식 축구공, 화이트 시트, 쿨톤 상금).
|
||||
- 인터랙션: 픽 → (닉네임)이메일 → 제출 → 결과(같은 AI) → Crowd 증가 (전부 **mock**, 백엔드 미연결).
|
||||
- 배포: https://triplepick-web.vercel.app (`/` = 현재, `/before` = v1 기록용).
|
||||
- git: `fa68169` init → `5ba653c` /before → `1b9dbd2` Backend Pack → (투표창) 커밋들.
|
||||
|
||||
## 1. 현재 상태 (DONE — 프론트 R1, mock 데이터)
|
||||
- Next.js 16 + React 19 + Tailwind v4 (App Router, TS)
|
||||
- 모바일 우선, 다크 그린 스코어보드 톤 (디자인 002/003 정합)
|
||||
- 구현 섹션: TopBar(카운트다운·참여수·CTA) / Hero / MatchCard / AIPredictions(3모델 confidence바) / Experience(픽·제출·결과·공유·Crowd) / PrizeChallenge / Footer(법무 4고지)
|
||||
- 인터랙션 검증 완료: 픽 선택 → 닉네임 → 제출 → 결과(같은 AI 계산) → Crowd 실시간 증가
|
||||
- `npm run build` 통과
|
||||
|
||||
## 2. 실행 방법
|
||||
## 2. 실행
|
||||
```bash
|
||||
cd /Users/haewonkam/Claude/AIO2O/triplepick-web
|
||||
npm install # 최초 1회
|
||||
npm run dev -- --port 3737
|
||||
# http://localhost:3737
|
||||
npm install
|
||||
npm run dev -- --port 3737 # http://localhost:3737
|
||||
```
|
||||
|
||||
## 3. 파일 맵
|
||||
## 3. 파일 맵 (현행)
|
||||
```
|
||||
app/layout.tsx 메타데이터·OG·SEO (ko)
|
||||
app/page.tsx Hero → MatchupHUD → Arena → Footer
|
||||
app/globals.css 테마 토큰, .sheet(레이어드 화이트), .bracket(HUD), .btn-mint, .gold-*
|
||||
lib/types.ts 도메인 타입 (Firestore 변환기에 재사용)
|
||||
lib/mockData.ts ⚠️ MOCK — Firebase 연결 시 여기부터 교체
|
||||
lib/format.ts 라벨/시간/퍼센트 포맷
|
||||
components/Hero.tsx 헤더 + 후킹 (다크)
|
||||
components/MatchupHUD.tsx Match01→Final + 코너브래킷 + 녹색글로우 VS (003 대결 강조)
|
||||
components/Arena.tsx ⚠️ 레이어드 화이트 시트(AI예측+픽+결과) + 골드 상금 + Crowd (client) — submit이 mock
|
||||
components/Footer.tsx 고지 (003 fine print + 법무)
|
||||
app/layout.tsx 메타·OG·SEO(ko)
|
||||
app/page.tsx Hero → MatchupHUD → Arena → Footer (단일 경기)
|
||||
app/before/page.tsx /before (v1 기록용, 자체완결)
|
||||
app/globals.css 디자인 토큰 (DESIGN.md와 1:1)
|
||||
lib/types.ts 도메인 타입 (opensAt/lockAt 포함)
|
||||
lib/schedule.ts Group A 6경기 일정(KST) SSOT — opensAt=킥오프-48h, lockAt=킥오프
|
||||
lib/mockData.ts ⚠️ MOCK AI예측/Crowd + DEMO_FORCE_OPEN 플래그
|
||||
lib/format.ts 시간·라벨 포맷
|
||||
lib/firebase.ts 클라 초기화 스켈레톤(env)
|
||||
components/Hero.tsx · MatchupHUD.tsx · Arena.tsx(핵심) · BallIcon.tsx · Footer.tsx
|
||||
public/icons/ ball.png(투명) profile.png gpt/claude/gemini kor.png
|
||||
firestore.rules · firestore.indexes.json · firebase.json · .env.example · scripts/seed.mjs
|
||||
docs/DESIGN.md · docs/BACKEND.md
|
||||
```
|
||||
|
||||
> 디자인 정합: 002(레이어드 화이트 백그라운드) + 003(매칭 대결 강조·Match01→Final·골드 ₩1,000,000·Crowd 가로바). 버튼 민트 #85FCA8(--mint). 모델 컬러 GPT #19c37d / Claude #e8814a / Gemini #5b8cff.
|
||||
> 참고: 002/003에 없는 sticky 카운트다운 TopBar는 디자인 충실성을 위해 제거함(PRD의 카운트다운/마감 로직은 Firebase 단계에서 헤더 또는 픽 옆에 재도입 가능). 세그먼트 기본 선택 없음(픽 강제) — 목업은 한국 승 선택 상태로 표시되어 있으니 기본값 원하면 Arena의 useState(outcome) 기본값 지정.
|
||||
## 4. 확정 결정 (구현에 반영됨/반영할 것)
|
||||
- **투표창**: 오픈 = 킥오프 D-2(-48h, `opensAt`) / 마감 = **킥오프 정각**(`lockAt`, 경기 전까지). `DEMO_FORCE_OPEN=true`로 데모는 항상 열림 → **운영 시 false**.
|
||||
- **AI 예측**: 매일 KST 0시 1회 생성, 그날 고정(immutable), 남은 경기만. (현재 mock)
|
||||
- **결과 메일**: 경기 3시간 후, **맞춘 사람만** + 다음경기/100만원 링크 (Resend).
|
||||
- **Firebase**: 사용자가 새 프로젝트 직접 생성 → config 6키·서비스계정·Resend키 제공 대기.
|
||||
- **상금 약관(포인트 배점 수치)**: 미정 → 팀 결정 후 dev. R2.
|
||||
|
||||
## 4. 다음 세션 할 일 — Firebase 연결 (NEW 프로젝트)
|
||||
## 5. 다음 세션 할 일 (우선순위)
|
||||
### 🔴 A. 멀티 경기 구조 (06.09 회의 최대 변경)
|
||||
- 단일 `/` → **전체 일정 대시보드** + `/match/[matchId]` 상세 + (차기)`/leaderboard`
|
||||
- `lib/schedule.ts` 6경기를 소스로 대시보드/동적 상세 렌더
|
||||
### 🔴 B. 경기 상세 변경 (금요일 핵심)
|
||||
- 확률 라벨 "승리 예측 팀 승리 확률"로, 닉네임 제거(이메일만), 서브타이틀 삭제, 투표 카운트다운 복원, 예측하기→결과보기 전환, 경기별 공유
|
||||
### 🟠 C. Firebase 연결 (BACKEND.md 그대로)
|
||||
- `npm i firebase`(설치됨) → `.env.local` 6키 → `mockData` 읽기 → Firestore, `Arena.confirmSubmit` mock → `submitPrediction` 콜러블
|
||||
- `firebase deploy --only firestore:rules,firestore:indexes` → `node scripts/seed.mjs` → functions 생성/구현
|
||||
### 🟡 D. 폴리시
|
||||
- Pretendard 웹폰트, OG 동적 공유카드(@vercel/og), 카카오 공유 SDK, 접근성
|
||||
|
||||
### 사용자(나)에게 요청할 것 ⬇ (새 세션이 물어볼 항목)
|
||||
1. **새 Firebase 프로젝트 생성** 후: `projectId`, 웹앱 config 6키
|
||||
(apiKey, authDomain, projectId, storageBucket, messagingSenderId, appId)
|
||||
2. Firestore 사용 설정(Native 모드), 리전 선택(asia-northeast3 서울 권장)
|
||||
3. (선택) 결과 알림 이메일 발송용 키(Resend/SendGrid)
|
||||
4. 도메인 결정(triplepick.ai 등) — 미정이면 Firebase Hosting 기본 도메인
|
||||
|
||||
### 연결 작업 순서
|
||||
1. `npm i firebase` + `lib/firebase.ts`(초기화, env에서 config 로드)
|
||||
2. `.env.local`에 NEXT_PUBLIC_FIREBASE_* 6키
|
||||
3. `lib/mockData.ts` → `lib/data.ts`로 교체: `getMatch / getAIPredictions / getCrowdStats` Firestore 읽기
|
||||
4. `components/Experience.tsx`의 `confirmSubmit` mock → `submitPrediction`(Firestore write + 트랜잭션 crowd 증분)으로 교체
|
||||
5. Firestore 보안 규칙 작성(기능정의서 §7): 쓰기 검증(마감·outcome·score·nickname), device_id 중복 방지
|
||||
6. 시드: matches/ai_predictions 문서 입력(현재 mockData 값 사용)
|
||||
7. Cloud Functions: `onResultSet → scoreAll`(채점), `subscribeResult`, OG `generateShareCard`
|
||||
8. GA4 이벤트 연결(기능정의서 §6), UTM 보존
|
||||
9. `firebase init hosting` + `next build` 배포
|
||||
|
||||
### 데이터 모델·API·채점·인수조건
|
||||
→ `기능정의서 §3~§8` 그대로 구현. 타입은 `lib/types.ts`에 이미 정의됨.
|
||||
|
||||
## 5. 남은 폴리시/TODO (R1 마감 전)
|
||||
- [ ] 결과 카드 문구 "선택입니다.나머지" 사이 공백 추가(Experience.tsx)
|
||||
- [ ] 공유 카드 OG 동적 이미지(@vercel/og) — 현재 텍스트 공유만
|
||||
- [ ] 카카오 공유 SDK 연동(국내 1순위)
|
||||
- [ ] 폰트: Pretendard 웹폰트 로드(현재 시스템 폴백)
|
||||
- [ ] 국기 이모지 → 에셋 이미지(선택)
|
||||
- [ ] 마감(lockAt) 지난 상태 QA, device_id 중복 제출 QA
|
||||
- [ ] 접근성(터치 타깃·대비) 점검
|
||||
> 금요일(체코전) 스코프 = **랜딩 + 투표만**. 리더보드·응원가·영상·댓글·AI적중률·공유포인트 = **차기**.
|
||||
|
||||
## 6. 주의
|
||||
- `lib/mockData.ts`의 AI 예측은 **플레이스홀더**. 발행 전 실제 GPT/Claude/Gemini JSON으로 교체.
|
||||
- 경로에 공백 없음(`triplepick-web`) — 툴링 안전. 상위 캠페인 폴더는 `Worldcup 2026`(공백 있음)이라 앱을 분리 배치함.
|
||||
- 룩앤필은 **`docs/DESIGN.md` 토큰을 따른다**(임의 변경 금지). 변경 시 DESIGN.md부터 갱신.
|
||||
- mockData AI예측은 플레이스홀더 → 실제 모델 출력으로 교체.
|
||||
- 경로 공백 없음(`triplepick-web`). 상위 캠페인 폴더(`Worldcup 2026`)는 공백 있어 앱 분리 배치.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
# TriplePick — Look & Feel / Design System (SSOT)
|
||||
|
||||
최종 갱신: 2026-06-09 KST
|
||||
출처: 구현된 `app/globals.css` + 컴포넌트 + 사용자 디렉션(02/03 목업 + 첨부 레퍼런스 반복 확정)
|
||||
원칙: **이 문서가 룩앤필의 단일 기준(SSOT).** 새 컴포넌트·페이지는 여기 토큰·패턴을 그대로 따른다.
|
||||
|
||||
> 디자인 진화 기록(Before/After): `/before`(v1 다크토큰) vs `/`(현재). 임의 변경 금지 — 토큰을 바꾸면 여기부터 갱신.
|
||||
|
||||
---
|
||||
|
||||
## 1. 브랜드 에센스
|
||||
- 이름: **TriplePick / Triple Pick 2026** · 핸들 `@triplepick_ai` · 운영 AIO2O
|
||||
- 컨셉: "AI 셋(GPT·Claude·Gemini) vs 너" — 대결·스코어보드·e스포츠 픽밴 에너지
|
||||
- 톤: 다크 차콜 베이스 + **민트/틸그린 액센트**, 프리미엄 스포츠 브로드캐스트
|
||||
- ⚠️ 금지: **"월드컵" 명칭(법적)** → "글로벌 축구" 프레이밍 / **골드 촌스러운 톤 금지**(쿨 민트·틸) / **단색 초록 일변도 금지**
|
||||
|
||||
---
|
||||
|
||||
## 2. 컬러 토큰 (globals.css `:root` — 정확값)
|
||||
|
||||
| 역할 | 변수 | HEX | 용도 |
|
||||
|---|---|---|---|
|
||||
| 베이스 | `--bg` | `#14171C` | 차콜 다크 배경 |
|
||||
| 베이스2 | `--bg2` | `#1B1F26` | 카드/입력 배경 |
|
||||
| 카드 | `--card` | `#20262F` | 다크 카드 |
|
||||
| **CTA 민트** | `--mint` | `#85FCA8` | 메인 버튼(밝은 민트그린) |
|
||||
| 민트 텍스트 | `--mint-ink` | `#0A2417` | 민트 버튼 위 글자 |
|
||||
| 액센트/글로우 | `--green` | `#3EE08A` | VS 글로우·보더·언더라인 |
|
||||
| **레이어 시트** | `--sheet` | `#F2F3EF` | 화이트 레이어드 시트(AI예측·픽) |
|
||||
| 시트 카드 | `--sheet-card` | `#FFFFFF` | 시트 위 카드 |
|
||||
| 잉크 | `--ink` | `#14171C` | 화이트 위 텍스트 |
|
||||
| 잉크 뮤트 | `--ink-muted` | `#79808C` | 보조 텍스트 |
|
||||
| 다크 라인 | `--line-d` | `#2B313C` | 다크 보더 |
|
||||
| 라이트 라인 | `--line-l` | `#E3E5DF` | 시트 보더 |
|
||||
|
||||
**모델 컬러(고정):** GPT `--gpt #15A99B`(틸그린) · Claude `--claude #E8814A`(오렌지) · Gemini `--gemini #5B8CFF`(블루)
|
||||
**상금 카드(쿨톤, 골드 폐기):** 보더 `--gold-border #5EF0B4` · 배경 `--gold-bg #0E1F1B`(딥틸) · 버튼 그라데 `#85FCA8 → #15A99B`(`.gold-btn`)
|
||||
|
||||
> 배경: `radial-gradient(120% 50% at 50% -5%, #20302A, var(--bg))` — 상단 미세 그린 글로우.
|
||||
|
||||
---
|
||||
|
||||
## 3. 타이포그래피
|
||||
- **타이틀 = Impact** (`.font-impact`: Impact, Haettenschweiler, "Arial Narrow Bold"). 예: `TRIPLE PICK 2026` 44px, 섹션 헤딩 32–40px
|
||||
- 본문 = Pretendard / 시스템 산세리프 (한글). (Pretendard 웹폰트 로드는 TODO)
|
||||
- 스케일: **사용자 지시로 2× 상향**. AI 스코어 28px · 모델명 20px · 매치 타이틀 22px · 헤딩 22px · 세그먼트 16px · 스테퍼 32px · CTA 20px
|
||||
- 후킹 헤드라인: **한 줄 강제**(`whitespace-nowrap`, 19px) + 양옆 `⫽` 그린
|
||||
|
||||
---
|
||||
|
||||
## 4. 레이아웃
|
||||
- **모바일 우선**, `.shell` max-width **460px**, 좌우 패딩 16
|
||||
- 구조 = **다크 히어로(상) + 레이어드 화이트 시트(하)** 하이브리드
|
||||
- 다크: Hero · MatchupHUD(대결)
|
||||
- 화이트 시트(`.sheet`, radius 22, 그림자): AI 예측 + 당신의 선택
|
||||
- 다크: 상금(쿨톤) · Crowd · Footer
|
||||
- 카드 radius 12–22, 터치 타깃 ≥ 44px
|
||||
|
||||
---
|
||||
|
||||
## 5. 컴포넌트 카탈로그 (현재 구현 = 기준)
|
||||
|
||||
- **Hero** (`Hero.tsx`): `TRIPLE PICK 2026`(Impact, 2026 그린) → `AI Prediction Arena`(그린) → 서브카피 **알약**(반투명, 가시성↑) → 후킹 한 줄(⫽ 그린)
|
||||
- **MatchupHUD** (`MatchupHUD.tsx`): `Match 01 → Final` 진행 바 → **녹색 글로우 보더 카드**(box-shadow green) → **프로필 로고 아이콘**(`/icons/profile.png`) + 팀명 + 일시(그린 볼드) + 경기장 → 국기(실제 KOR png + CZE 인라인 SVG) + **라이트닝 그린 VS**(Impact, textShadow glow)
|
||||
- **AI 예측 카드** (`Arena.tsx`, 화이트 시트 내): 실제 모델 아이콘(`/icons/gpt.png·claude.jpg·gemini.jpeg`) + 모델명 + 스코어(28px) + 확률% + **모델색 confidence 바** + 근거 한 줄
|
||||
- **세그먼트(당신의 선택)**: 3분할, 선택 시 `--mint` 배경 + 잉크 텍스트
|
||||
- **스코어 스테퍼**: −/+ 버튼 + 큰 숫자(32px)
|
||||
- **CTA(`.btn-mint`)**: `#85FCA8` + 글로우 그림자
|
||||
- **상금 카드(`.gold-card`/`.gold-btn`)**: 딥틸 배경 + 민트 보더 + 민트→틸 그라데 버튼 (쿨톤)
|
||||
- **Crowd Pick**: 가로 세그먼트 단일 바(국기 + %)
|
||||
- **Footer**: fine print + 법무 4고지 + `© 2026 TriplePick · 운영 AIO2O · @triplepick_ai`
|
||||
|
||||
---
|
||||
|
||||
## 6. 아이콘·이미지 자산 (`public/icons/`)
|
||||
- `ball.png` — **클래식 흑백 축구공(투명 PNG)**. ⚠️ 흰 배경/체커보드 구워넣기 금지(마젠타 키잉으로 투명 처리한 자산)
|
||||
- `profile.png` — TriplePick 브랜드 로고(매치카드 아이콘)
|
||||
- `gpt.png` / `claude.jpg` / `gemini.jpeg` — 실제 브랜드 아이콘(레터박스 금지)
|
||||
- `kor.png` — 한국 국기. 체코는 인라인 SVG(백·적 + 청 삼각)
|
||||
- 글로우는 `drop-shadow(... rgba(62,224,138,.))` 그린으로만
|
||||
|
||||
---
|
||||
|
||||
## 7. Do / Don't
|
||||
- ✅ 실제 모델 아이콘 · 클래식 축구공(투명) · 라이트닝 그린 VS · 화이트 시트 + 다크 하이브리드 · 민트 CTA
|
||||
- ✅ 3색(틸그린/오렌지/블루)으로 모델 구분, 글로우는 그린
|
||||
- ❌ "월드컵" 표현 / 골드 톤 / 단색 초록 일변도 / 레터박스 가짜 아이콘 / 이모지 축구공 / 임의 다크 단색(=v1 회귀)
|
||||
- ❌ 한글을 이미지로 굽기(가독성↓) — 텍스트 레이어로
|
||||
|
||||
---
|
||||
|
||||
## 8. 06.09 회의로 반영해야 할 디자인 변경 (대기)
|
||||
> 상세: `../../Worldcup 2026/000. Plan/Task — 랜딩·디자인·프론트엔드 업데이트 (06.09 회의).md`
|
||||
- [ ] 확률 라벨 `Confidence` → **"OO 승리 확률 XX%"**(이긴 팀 기준) + 승리팀 국기
|
||||
- [ ] confidence 바 축소/삭제 검토, **근거(메인 리즌) 강조**, 모델 텍스트 짧고 재미있게
|
||||
- [ ] **닉네임 필드 제거 → 이메일만**
|
||||
- [ ] 서브타이틀 `Korea Republic vs Czechia · Matchday Prediction` **삭제(중복)**
|
||||
- [ ] **"투표 종료까지" 카운트다운** 상세 페이지에 복원
|
||||
- [ ] 멀티 경기: 대시보드 + 경기 상세 + (차기)리더보드 — 동일 토큰으로 확장
|
||||
- [ ] 예측하기 → (경기 후) **결과 보기** 버튼 + 최종 스코어 표시
|
||||
Loading…
Reference in New Issue