@su-record/vibe 2.8.17 → 2.8.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/vibe-figma/SKILL.md +25 -66
- package/skills/vibe-figma-analyze/SKILL.md +91 -319
- package/skills/vibe-figma-codegen/SKILL.md +112 -782
- package/skills/vibe-figma-consolidate/SKILL.md +53 -90
- package/skills/vibe-figma-frame/SKILL.md +142 -181
- package/skills/vibe-figma-pipeline/SKILL.md +4 -45
- package/skills/vibe-figma-rules/SKILL.md +320 -159
- package/skills/vibe-figma-style/SKILL.md +107 -476
|
@@ -1,28 +1,76 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: vibe-figma-rules
|
|
3
|
-
description: Figma to Code
|
|
3
|
+
description: Figma to Code 공통 규칙 — Model Routing, 스택 감지, 브레이크포인트, 이미지 분류, 컴포넌트 통합
|
|
4
4
|
triggers: []
|
|
5
5
|
tier: standard
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Skill: vibe-figma-rules —
|
|
8
|
+
# Skill: vibe-figma-rules — 공통 규칙 (Single Source of Truth)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
모든 vibe-figma-* 스킬이 참조하는 공통 규칙 정의.
|
|
11
|
+
중복 방지를 위해 **이 파일에만 정의**하고, 다른 스킬에서는 "vibe-figma-rules R-N 참조"로 사용.
|
|
11
12
|
|
|
12
13
|
---
|
|
13
14
|
|
|
14
|
-
##
|
|
15
|
+
## R-0. 설계 철학
|
|
16
|
+
|
|
17
|
+
> **스크린샷 시각 분석이 핵심이다. 레이어 구조/참조 코드는 보조 수단.**
|
|
18
|
+
|
|
19
|
+
실무 Figma 파일의 현실:
|
|
20
|
+
```
|
|
21
|
+
"Frame 633372" ← 의미 없는 자동 이름
|
|
22
|
+
"Frame 633371" ← 중첩된 의미 없는 프레임
|
|
23
|
+
"Frame 633370" ← AI가 구조를 파악할 수 없음
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
레이어명이 "Frame 47", "Group 12"이고, Auto Layout 없이 절대 배치된 프레임이 대부분.
|
|
27
|
+
`get_design_context`가 깔끔한 참조 코드를 돌려주지 못하는 것이 **기본 전제**.
|
|
28
|
+
|
|
29
|
+
이 스킬은 **스토리보드에서 기능/인터랙션/상태를 추출**하고,
|
|
30
|
+
**디자인 프레임 스크린샷에서 스타일/이미지를 시각 분석**하여,
|
|
31
|
+
**원본 디자인 이미지 수준의 완성도**를 달성하는 것이 목적이다.
|
|
32
|
+
|
|
33
|
+
### 핵심 원칙
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
1. 스크린샷이 1차 소스다
|
|
37
|
+
— 모든 시각적 판단(레이아웃, 색상, 간격, 폰트, 이미지 배치)은 스크린샷에서 읽는다
|
|
38
|
+
— get_screenshot으로 섹션별 원본 이미지를 먼저 확보한다
|
|
39
|
+
|
|
40
|
+
2. 참조 코드는 2차 소스다
|
|
41
|
+
— get_design_context의 참조 코드는 이미지 에셋 URL 추출 + 구조 힌트 용도
|
|
42
|
+
— 참조 코드의 레이아웃/스타일 값은 스크린샷과 대조 후에만 신뢰한다
|
|
43
|
+
— 참조 코드가 부정확해도 스크린샷만으로 코드를 생성할 수 있어야 한다
|
|
44
|
+
|
|
45
|
+
3. 레이어 구조에 의존하지 않는다
|
|
46
|
+
— 구조화된 레이어는 보너스, 없어도 결과물 품질은 동일해야 한다
|
|
47
|
+
— "Frame 633372" 같은 무의미한 이름이 와도 스크린샷에서 섹션 경계를 파악한다
|
|
48
|
+
|
|
49
|
+
4. 검증은 항상 시각적 비교로
|
|
50
|
+
— 완료 기준: 원본 스크린샷 vs 생성 코드의 Match Score 95%+, P1=0
|
|
51
|
+
— 코드의 "정확성"이 아니라 "보이는 결과"가 기준이다
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 분석 우선순위
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
[1순위] get_screenshot → 시각 분석 (레이아웃, 색상, 간격, 폰트, 배경 이미지)
|
|
58
|
+
[2순위] get_design_context → 에셋 URL 추출 + 구조 힌트 (스크린샷과 대조 필수)
|
|
59
|
+
[3순위] get_metadata → 프레임 목록 + nodeId 확보 (구조 파악이 아닌 탐색 용도)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## R-1. Model Routing
|
|
15
65
|
|
|
16
66
|
| Step | Claude | GPT (Codex) | 이유 |
|
|
17
67
|
|------|--------|-------------|------|
|
|
18
68
|
| Step A (스토리보드 + 구조) | **Haiku → Sonnet** | — | MCP 추출 → 구조 설계 |
|
|
19
|
-
| Step B (
|
|
20
|
-
| Step B (
|
|
21
|
-
| Step B (
|
|
22
|
-
| Step C (
|
|
23
|
-
| Step
|
|
24
|
-
| Step C (PC 검증) | **Sonnet** | — | 양쪽 뷰포트 비교 |
|
|
25
|
-
| Step D (공통화) | **Sonnet** | — | 리팩토링 + 최종 검증 |
|
|
69
|
+
| Step B (디자인 추출) | **Haiku** | — | MCP + 이미지 다운로드 |
|
|
70
|
+
| Step B (코드 생성) | **Sonnet** | **gpt-5.3-codex-spark** (병렬) | 섹션별 컴포넌트 생성 |
|
|
71
|
+
| Step B (검증) | **Sonnet** | — | 이미지 비교 + auto-fix |
|
|
72
|
+
| Step C (추가 뷰포트) | **Haiku → Sonnet** | — | 반응형 레이어 추가 |
|
|
73
|
+
| Step D (공통화 + 검증) | **Sonnet** | — | 리팩토링 + 최종 검증 |
|
|
26
74
|
| Post (코드 리뷰) | — | **gpt-5.3-codex** | 전체 코드 품질 검증 |
|
|
27
75
|
|
|
28
76
|
### GPT 모델 선택 기준
|
|
@@ -33,227 +81,340 @@ tier: standard
|
|
|
33
81
|
| `gpt-5.3-codex` | `models.gptCodex` | 코드 리뷰, 분석 (정확도 우선) |
|
|
34
82
|
| `gpt-5.3-codex-spark` | `models.gptCodexSpark` | 코드 생성 (속도 우선) |
|
|
35
83
|
|
|
36
|
-
`~/.vibe/config.json`의 `models
|
|
84
|
+
`~/.vibe/config.json`의 `models`에서 오버라이드 가능.
|
|
37
85
|
|
|
38
86
|
---
|
|
39
87
|
|
|
40
|
-
##
|
|
88
|
+
## R-2. 프로젝트 스택 감지
|
|
41
89
|
|
|
42
|
-
###
|
|
90
|
+
### 2-1. Detect Stack
|
|
43
91
|
|
|
44
|
-
Read
|
|
92
|
+
1. Read `.claude/vibe/config.json` → `stacks` 필드
|
|
93
|
+
2. config 없으면 프로젝트 파일에서 감지:
|
|
45
94
|
|
|
46
|
-
|
|
|
47
|
-
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
95
|
+
| 감지 대상 | 파일 패턴 |
|
|
96
|
+
|-----------|----------|
|
|
97
|
+
| React | `package.json` → `react` in deps |
|
|
98
|
+
| Vue | `package.json` → `vue` in deps |
|
|
99
|
+
| Next.js | `next.config.*` |
|
|
100
|
+
| Nuxt | `nuxt.config.*` |
|
|
101
|
+
| Svelte | `svelte.config.*` |
|
|
102
|
+
| Tailwind | `tailwind.config.*` |
|
|
103
|
+
| CSS Modules | `*.module.css` 패턴 |
|
|
104
|
+
| SCSS | `*.scss` 또는 `sass` in deps |
|
|
105
|
+
| CSS-in-JS | `styled-components` / `@emotion` in deps |
|
|
55
106
|
|
|
56
|
-
###
|
|
107
|
+
### 2-2. 디렉토리 감지
|
|
57
108
|
|
|
58
|
-
|
|
109
|
+
| 용도 | Next.js | Nuxt | React | Vue |
|
|
110
|
+
|------|---------|------|-------|-----|
|
|
111
|
+
| 페이지 | `pages/` or `app/` | `pages/` | `src/pages/` or `src/views/` | `src/views/` |
|
|
112
|
+
| 컴포넌트 | `components/` or `src/components/` | `components/` | `src/components/` | `src/components/` |
|
|
113
|
+
| 스타일 | SCSS: `assets/scss/` or `src/styles/`, CSS: `src/styles/`, Tailwind: `tailwind.config.*` |
|
|
59
114
|
|
|
60
|
-
|
|
61
|
-
|--------|-----------------|
|
|
62
|
-
| Layout shift | Which elements reflow? (e.g., horizontal → vertical stack) |
|
|
63
|
-
| Visibility | Which elements hide/show per viewport? |
|
|
64
|
-
| Typography scale | Font size ratio between viewports |
|
|
65
|
-
| Spacing scale | Padding/gap ratio between viewports |
|
|
66
|
-
| Component shape | Does the component change form? (e.g., drawer → sidebar) |
|
|
67
|
-
| Navigation | Does nav change? (e.g., hamburger ↔ full nav bar) |
|
|
115
|
+
### 2-3. Design Context 로드
|
|
68
116
|
|
|
69
|
-
|
|
117
|
+
순서대로 읽음 (나중 소스가 우선):
|
|
70
118
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
| Hero title | 24px | 48px | fluid: clamp() |
|
|
76
|
-
| Card grid | 1 column | 3 columns | grid auto-fit |
|
|
77
|
-
| Sidebar | hidden | visible | display toggle |
|
|
78
|
-
| Body text | 14px | 16px | fluid: clamp() |
|
|
79
|
-
| Padding | 16px | 48px | fluid: clamp() |
|
|
80
|
-
```
|
|
119
|
+
1. **`.claude/vibe/design-context.json`** — 브랜드, 접근성, 디바이스 제약
|
|
120
|
+
2. **`.claude/vibe/design-system/{project}/MASTER.md`** — 토큰 정의
|
|
121
|
+
|
|
122
|
+
**결정 규칙**: Figma 토큰 ≈ 기존 MASTER.md 토큰 (색상 ΔE < 5 또는 간격 ±2px) → 기존 토큰 사용, 중복 생성 금지.
|
|
81
123
|
|
|
82
124
|
---
|
|
83
125
|
|
|
84
|
-
##
|
|
126
|
+
## R-3. 브레이크포인트 + 스케일 팩터
|
|
85
127
|
|
|
86
|
-
###
|
|
128
|
+
### 소스 우선순위
|
|
87
129
|
|
|
88
|
-
|
|
130
|
+
| 순위 | 소스 | 방법 |
|
|
131
|
+
|------|------|------|
|
|
132
|
+
| 1 | **스토리보드** | Step A에서 추출한 `storyboardSpec.breakpoints` |
|
|
133
|
+
| 2 | **`~/.vibe/config.json`** | `figma.breakpoints` (CLI로 커스터마이즈) |
|
|
134
|
+
| 3 | **프로젝트 CSS/Tailwind** | `tailwind.config.*` → `theme.screens`, 또는 `@media` 패턴 |
|
|
135
|
+
| 4 | **기본값** | 아래 테이블 |
|
|
89
136
|
|
|
90
|
-
|
|
91
|
-
2. **Design tokens** — Colors (fill, stroke), font properties, spacing values, border radius, shadows
|
|
92
|
-
3. **Auto-layout** — Direction, gap, padding (maps directly to flex/grid)
|
|
93
|
-
4. **Constraints** — Fixed vs fluid sizing
|
|
94
|
-
5. **Component instances** — Identify reusable patterns
|
|
95
|
-
6. **Image fills** — Identify layers with `type: "IMAGE"` fills (see Phase 2-A)
|
|
137
|
+
### 기본 브레이크포인트
|
|
96
138
|
|
|
97
|
-
|
|
139
|
+
```
|
|
140
|
+
breakpoint: 1024px ← PC↔Mobile 경계 (@media min-width)
|
|
141
|
+
pcTarget: 1920px ← PC 메인 타겟
|
|
142
|
+
mobilePortrait: 480px ← Mobile portrait max
|
|
143
|
+
mobileMinimum: 360px ← Mobile 최소 지원
|
|
144
|
+
designPc: 2560px ← Figma PC 아트보드 (디자인 2x 스케일)
|
|
145
|
+
designMobile: 720px ← Figma Mobile 아트보드 (디자인 2x 스케일)
|
|
146
|
+
```
|
|
98
147
|
|
|
99
|
-
|
|
148
|
+
### 스케일 팩터 계산
|
|
100
149
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
"desktop": { "h1": 48, "body": 16, "padding": 48 } }
|
|
105
|
-
```
|
|
106
|
-
2. **Layout differences** — Auto-layout direction changes (e.g., HORIZONTAL → VERTICAL)
|
|
107
|
-
3. **Visibility map** — Which layers exist in one viewport but not the other
|
|
108
|
-
4. **Shared tokens** — Values identical across all viewports (colors, border-radius, shadows are usually shared)
|
|
150
|
+
```
|
|
151
|
+
PC: scaleFactor.pc = pcTarget / designPc (기본: 1920/2560 = 0.75)
|
|
152
|
+
Mobile: scaleFactor.mobile = mobilePortrait / designMobile (기본: 480/720 = 0.667)
|
|
109
153
|
|
|
110
|
-
|
|
154
|
+
적용: 코드 값 = Figma 추출 값 × scaleFactor
|
|
155
|
+
- 색상 hex → 스케일 불필요
|
|
156
|
+
- 타이포 (font-size, line-height) → 스케일 적용
|
|
157
|
+
- 간격 (padding, gap, margin) → 스케일 적용
|
|
158
|
+
```
|
|
111
159
|
|
|
112
|
-
|
|
160
|
+
### clamp() 계산 공식
|
|
113
161
|
|
|
114
|
-
|
|
162
|
+
```
|
|
163
|
+
Step 1: Figma 값 → 타겟 값
|
|
164
|
+
targetMobile = figmaMobileValue × scaleFactor.mobile
|
|
165
|
+
targetPc = figmaPcValue × scaleFactor.pc
|
|
166
|
+
|
|
167
|
+
Step 2: clamp() 생성
|
|
168
|
+
minVw = mobileMinimum (360px)
|
|
169
|
+
maxVw = pcTarget (1920px)
|
|
170
|
+
slope = (targetPc - targetMobile) / (maxVw - minVw)
|
|
171
|
+
intercept = targetMobile - slope × minVw
|
|
172
|
+
→ clamp({targetMobile/16}rem, {intercept/16}rem + {slope×100}vw, {targetPc/16}rem)
|
|
173
|
+
```
|
|
115
174
|
|
|
116
|
-
|
|
175
|
+
### CLI 커스터마이즈
|
|
117
176
|
|
|
177
|
+
```bash
|
|
178
|
+
vibe figma breakpoints # 현재 값 확인
|
|
179
|
+
vibe figma breakpoints --set breakpoint=768 # PC↔Mobile 경계 변경
|
|
118
180
|
```
|
|
119
|
-
fills: [{ type: "IMAGE", scaleMode: "FILL" | "FIT" | "CROP" | "TILE", imageRef: "..." }]
|
|
120
|
-
```
|
|
121
181
|
|
|
122
|
-
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## R-4. 이미지 분류 + Multi-Layer 패턴
|
|
185
|
+
|
|
186
|
+
### 분류 기준
|
|
123
187
|
|
|
124
188
|
| 판별 조건 | 분류 | 코드 패턴 |
|
|
125
189
|
|----------|------|----------|
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
-
|
|
|
130
|
-
|
|
|
190
|
+
| 프레임 배경이고 위에 텍스트/UI 겹침 | **Background** | `background-image` + `background-size` |
|
|
191
|
+
| 독립 레이어, 겹치는 요소 없음 | **Content** | `<img>` 또는 `<picture>` |
|
|
192
|
+
| 이름에 `icon`/`logo`/`avatar` | **Inline Asset** | `<img>` (작은 크기) |
|
|
193
|
+
| `scaleMode: "TILE"` 반복 패턴 | **Pattern** | `background-repeat` |
|
|
194
|
+
| 전체 덮음 + opacity < 1 또는 blendMode | **Overlay** | `background-image` + overlay |
|
|
131
195
|
|
|
132
|
-
|
|
196
|
+
### Multi-Layer 패턴 (배경 이미지 섹션 필수 구조)
|
|
133
197
|
|
|
134
198
|
```
|
|
135
|
-
|
|
136
|
-
|
|
199
|
+
.{section}Section ← 레이아웃 (position: relative, overflow: hidden)
|
|
200
|
+
.{section}Bg ← 배경 이미지 — z-index: 0
|
|
201
|
+
.{section}BgOverlay ← 오버레이 (선택) — z-index: 1
|
|
202
|
+
.{section}Character ← 캐릭터/일러스트 (선택) — z-index: 2
|
|
203
|
+
.{section}Content ← 텍스트/버튼/UI — z-index: 최상위
|
|
204
|
+
```
|
|
137
205
|
|
|
138
|
-
|
|
139
|
-
|
|
206
|
+
```css
|
|
207
|
+
.{section}Section { position: relative; overflow: hidden; }
|
|
208
|
+
.{section}Bg {
|
|
209
|
+
position: absolute; inset: 0; z-index: 0;
|
|
210
|
+
background-image: url('/images/{feature}/{name}.webp');
|
|
211
|
+
background-size: cover; background-position: center;
|
|
212
|
+
}
|
|
213
|
+
.{section}BgOverlay {
|
|
214
|
+
position: absolute; inset: 0; z-index: 1;
|
|
215
|
+
background: linear-gradient(to bottom, rgba(0,0,0,0.3), rgba(0,0,0,0.7));
|
|
216
|
+
}
|
|
217
|
+
.{section}Content { position: relative; z-index: 2; }
|
|
140
218
|
```
|
|
141
219
|
|
|
142
|
-
|
|
220
|
+
### 배경 이미지 클래스 분리 원칙
|
|
143
221
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
222
|
+
| 유형 | 클래스 예시 | 분리 이유 |
|
|
223
|
+
|------|-----------|----------|
|
|
224
|
+
| 섹션 전면 배경 | `.heroBg` | 시즌/이벤트별 이미지 교체 |
|
|
225
|
+
| 오버레이 | `.heroBgOverlay` | 투명도/그라데이션 독립 조절 |
|
|
226
|
+
| 패턴/텍스처 | `.sectionPattern` | repeat/size 별도 제어 |
|
|
227
|
+
| 캐릭터/일러스트 | `.heroCharacter` | 콜라보별 교체, position 조절 |
|
|
228
|
+
| 그라데이션 | `.sectionGradient` | 테마별 색상 변경 |
|
|
147
229
|
|
|
148
|
-
###
|
|
230
|
+
### 반응형 배경 이미지
|
|
149
231
|
|
|
150
|
-
|
|
232
|
+
```css
|
|
233
|
+
.heroBg { background-image: url('/images/hero-mobile.webp'); }
|
|
234
|
+
@media (min-width: var(--breakpoint)) {
|
|
235
|
+
.heroBg { background-image: url('/images/hero-pc.webp'); }
|
|
236
|
+
}
|
|
237
|
+
```
|
|
151
238
|
|
|
152
|
-
|
|
239
|
+
### 이미지 공통 규칙
|
|
153
240
|
|
|
154
|
-
|
|
241
|
+
| 규칙 | 설명 |
|
|
242
|
+
|------|------|
|
|
243
|
+
| format | `.webp` 우선 (fallback: `.png`/`.jpg`) |
|
|
244
|
+
| alt | 레이어 이름에서 파생, 장식은 `alt=""` + `aria-hidden="true"` |
|
|
245
|
+
| width/height | 항상 명시 (CLS 방지), 스케일 팩터 적용 |
|
|
246
|
+
| loading | 뷰포트 상단 → `eager`, 나머지 → `lazy` |
|
|
247
|
+
| object-fit | `cover` (배경), `contain` (로고/아이콘), `fill` 금지 |
|
|
155
248
|
|
|
156
249
|
---
|
|
157
250
|
|
|
158
|
-
##
|
|
251
|
+
## R-5. 컴포넌트 통합 규칙 (80% Rule)
|
|
159
252
|
|
|
160
|
-
###
|
|
253
|
+
### 유사도 판단
|
|
161
254
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
- `tailwind.config.*` → Tailwind CSS
|
|
166
|
-
- `next.config.*` → Next.js
|
|
167
|
-
- `nuxt.config.*` → Nuxt
|
|
168
|
-
- `*.module.css` → CSS Modules pattern
|
|
169
|
-
- `*.scss` / `sass` in deps → SCSS
|
|
170
|
-
- `styled-components` / `@emotion` in deps → CSS-in-JS
|
|
255
|
+
```
|
|
256
|
+
구조 80%+ 동일 (색상/크기/텍스트만 다름)
|
|
257
|
+
→ 하나의 컴포넌트 + variant prop으로 통합
|
|
171
258
|
|
|
172
|
-
|
|
259
|
+
구조 자체가 다름 (요소 추가/제거, 레이아웃 방향 변경)
|
|
260
|
+
→ 별도 컴포넌트 유지
|
|
261
|
+
```
|
|
173
262
|
|
|
174
|
-
|
|
263
|
+
### 스택별 variant 구현
|
|
175
264
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
2. **`.claude/vibe/design-system/{project}/MASTER.md`** — authoritative token definitions
|
|
183
|
-
- If MASTER.md exists: **map Figma tokens to MASTER.md tokens first**, only create new tokens for values with no match
|
|
184
|
-
- If no MASTER.md: generate `figma-tokens.css` as standalone token source
|
|
265
|
+
| Stack | 방법 |
|
|
266
|
+
|-------|------|
|
|
267
|
+
| React / Next.js | `variant` prop + 조건부 className |
|
|
268
|
+
| Vue / Nuxt | `variant` prop + `<slot>` |
|
|
269
|
+
| Svelte | `variant` prop + `<slot>` |
|
|
270
|
+
| React Native | `variant` prop + StyleSheet 조건 |
|
|
185
271
|
|
|
186
|
-
|
|
272
|
+
### Fragment / 래퍼 제거
|
|
187
273
|
|
|
188
|
-
|
|
274
|
+
스타일이나 이벤트가 없는 래핑 요소 → 프레임워크 제공 투명 래퍼 사용:
|
|
189
275
|
|
|
190
|
-
|
|
276
|
+
| Stack | 투명 래퍼 |
|
|
277
|
+
|-------|----------|
|
|
278
|
+
| React / Next.js | `<>...</>` |
|
|
279
|
+
| Vue / Nuxt | `<template>` (컴포넌트 루트 이외) |
|
|
280
|
+
| Svelte | `{#if}`, `{#each}` 블록 |
|
|
191
281
|
|
|
192
|
-
|
|
282
|
+
---
|
|
193
283
|
|
|
194
|
-
|
|
195
|
-
|----------|--------|-----|
|
|
196
|
-
| 1 | **Storyboard** | Phase 0-1에서 추출한 `storyboardSpec.breakpoints` |
|
|
197
|
-
| 2 | **`~/.vibe/config.json`** | `figma.breakpoints` — user-customized via `vibe figma breakpoints --set` |
|
|
198
|
-
| 3 | **Project CSS/Tailwind** | Grep `tailwind.config.*` → `theme.screens`, or `@media.*min-width` patterns in codebase |
|
|
199
|
-
| 4 | **Defaults** | Built-in values (breakpoint: 1024px, etc.) |
|
|
284
|
+
## R-6. 검증 루프 공통 규칙
|
|
200
285
|
|
|
201
|
-
|
|
286
|
+
모든 Step에서 사용하는 스크린샷 기반 검증 프로세스.
|
|
202
287
|
|
|
203
|
-
|
|
288
|
+
### 6-1. 원본 스크린샷 확보
|
|
204
289
|
|
|
205
290
|
```
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
designPc: 2560px ← Figma PC artboard width (design is 2x scale)
|
|
211
|
-
designMobile: 720px ← Figma Mobile artboard width (design is 2x scale)
|
|
291
|
+
Step A에서 get_screenshot으로 확보한 섹션별 원본 이미지를 기준으로 사용.
|
|
292
|
+
없으면 해당 섹션의 nodeId로 get_screenshot 재호출.
|
|
293
|
+
|
|
294
|
+
원본 = Figma 디자인 스크린샷 (디자이너 의도)
|
|
212
295
|
```
|
|
213
296
|
|
|
214
|
-
|
|
297
|
+
### 6-2. 생성 코드 렌더링 확보
|
|
215
298
|
|
|
216
299
|
```
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
300
|
+
방법 (우선순위):
|
|
301
|
+
1. /vibe.utils --preview → 브라우저 렌더링 스크린샷 자동 생성
|
|
302
|
+
2. dev 서버 실행 중이면 → 해당 페이지 스크린샷 (Playwright/Puppeteer)
|
|
303
|
+
3. 둘 다 불가능하면 → 생성된 코드를 직접 읽고 시각적 결과를 추론
|
|
220
304
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
- Values scale linearly between these bounds
|
|
305
|
+
⚠️ 방법 3(코드 읽기 추론)은 최후 수단.
|
|
306
|
+
가능한 한 실제 렌더링 결과를 확보해야 정확한 비교 가능.
|
|
307
|
+
```
|
|
225
308
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
309
|
+
### 6-3. 섹션별 비교 (전체 페이지가 아닌 섹션 단위)
|
|
310
|
+
|
|
311
|
+
```
|
|
312
|
+
각 섹션 컴포넌트를 개별로 비교:
|
|
313
|
+
원본: Figma 섹션 스크린샷 (get_screenshot per section)
|
|
314
|
+
생성: 렌더링된 섹션 스크린샷 (또는 코드 추론)
|
|
315
|
+
|
|
316
|
+
섹션별로 비교해야 하는 이유:
|
|
317
|
+
- 전체 페이지 비교는 스크롤 길이 차이로 오차가 큼
|
|
318
|
+
- 섹션 단위가 수정 범위를 좁힐 수 있음
|
|
319
|
+
- P1 발견 시 해당 섹션만 수정 → 재비교
|
|
230
320
|
```
|
|
231
321
|
|
|
232
|
-
|
|
322
|
+
### 6-4. 비교 항목 + P1/P2 분류
|
|
233
323
|
|
|
234
|
-
|
|
324
|
+
| 비교 항목 | P1 (필수 수정) | P2 (권장 수정) |
|
|
325
|
+
|----------|---------------|---------------|
|
|
326
|
+
| **레이아웃** | 요소 배치 방향 다름, 섹션 순서 다름 | 미세 정렬 차이 |
|
|
327
|
+
| **배경 이미지** | 누락, 완전히 다른 이미지 | 크기/위치 미세 차이 |
|
|
328
|
+
| **색상** | 배경/텍스트색 완전히 다름 | 미세한 톤 차이 (ΔE < 10) |
|
|
329
|
+
| **타이포** | 제목/본문 크기 비율 다름, 굵기 다름 | ±2px 차이 |
|
|
330
|
+
| **간격** | 섹션 간 간격 크게 다름, 요소 겹침 | ±4px 차이 |
|
|
331
|
+
| **이미지 에셋** | 다운로드 실패, 경로 깨짐 | 크기/비율 미세 차이 |
|
|
332
|
+
| **누락 요소** | 스크린샷에 보이는 요소가 코드에 없음 | — |
|
|
333
|
+
| **오버레이** | 배경 위 텍스트 가독성 확보 안 됨 | 투명도 미세 차이 |
|
|
235
334
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
335
|
+
### 6-5. Diff Report 출력
|
|
336
|
+
|
|
337
|
+
```markdown
|
|
338
|
+
## Visual Diff Report — {섹션명}
|
|
339
|
+
|
|
340
|
+
원본: Figma {섹션} 스크린샷
|
|
341
|
+
생성: 렌더링 결과 (또는 코드 추론)
|
|
342
|
+
|
|
343
|
+
### Match Score: {N}%
|
|
344
|
+
|
|
345
|
+
| # | 항목 | 원본 | 생성 코드 | 심각도 |
|
|
346
|
+
|---|------|------|----------|--------|
|
|
347
|
+
| 1 | 배경 이미지 | 눈 테마 + 그라데이션 | 누락 | P1 |
|
|
348
|
+
| 2 | 제목 font-size | ~36px (스케일 후) | 24px | P1 |
|
|
349
|
+
| 3 | 카드 border-radius | ~12px | 8px | P2 |
|
|
240
350
|
```
|
|
241
351
|
|
|
242
|
-
|
|
352
|
+
### 6-6. Auto-Fix Loop
|
|
243
353
|
|
|
244
|
-
|
|
354
|
+
```
|
|
355
|
+
P1이 있으면:
|
|
356
|
+
1. 해당 섹션의 컴포넌트/스타일 파일 수정
|
|
357
|
+
2. 수정 후 렌더링 재확보 (가능하면)
|
|
358
|
+
3. 원본 스크린샷과 재비교
|
|
359
|
+
4. P1=0 될 때까지 반복 — 횟수 제한 없음
|
|
360
|
+
|
|
361
|
+
같은 P1이 반복될 때:
|
|
362
|
+
- 이전과 동일한 수정을 반복하지 않는다
|
|
363
|
+
- 접근 방식을 바꿔서 시도한다 (다른 CSS 속성, 다른 레이아웃 전략)
|
|
364
|
+
- 접근을 바꿔도 해결 안 되면 → 사용자에게 해당 항목을 보여주고 방향 확인
|
|
365
|
+
- 사용자 확인 후에도 루프는 계속된다 — P1=0이 될 때까지 멈추지 않음
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### 6-7. 완료 조건
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
✅ 모든 섹션 Match Score 95%+
|
|
372
|
+
✅ P1 = 0 (전 섹션)
|
|
373
|
+
✅ 모든 이미지 에셋 표시 + Figma 임시 URL 잔존 0건
|
|
374
|
+
✅ (반응형) 각 뷰포트 독립 검증 통과
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## R-7. 스크린샷 중심 분석 프로세스
|
|
245
380
|
|
|
246
|
-
|
|
381
|
+
### 섹션별 분석 순서
|
|
247
382
|
|
|
248
383
|
```
|
|
249
|
-
|
|
250
|
-
→
|
|
251
|
-
→
|
|
252
|
-
|
|
253
|
-
|
|
384
|
+
Step 1: get_screenshot(섹션 nodeId)
|
|
385
|
+
→ 원본 디자인 이미지 확보
|
|
386
|
+
→ 시각 분석: 레이아웃 구조, 색상 팔레트, 폰트 크기/굵기, 간격, 배경 이미지 유무
|
|
387
|
+
|
|
388
|
+
Step 2: get_design_context(섹션 nodeId)
|
|
389
|
+
→ 이미지 에셋 URL 추출 (const xxxImage = 'https://figma.com/api/mcp/asset/...')
|
|
390
|
+
→ 참조 코드에서 구조 힌트 확인 (HTML 계층, 컴포넌트 분리 방식)
|
|
391
|
+
→ ⚠️ 참조 코드의 스타일 값은 스크린샷과 대조 후에만 채택
|
|
392
|
+
|
|
393
|
+
Step 3: 스크린샷 기반 코드 생성
|
|
394
|
+
→ 스크린샷에서 읽은 시각 정보로 스타일 작성
|
|
395
|
+
→ 참조 코드의 에셋 URL을 로컬 경로로 교체
|
|
396
|
+
→ 참조 코드 구조가 스크린샷과 다르면 → 스크린샷 기준으로 재구성
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### 스크린샷에서 읽어야 하는 것
|
|
254
400
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
401
|
+
| 항목 | 읽는 방법 |
|
|
402
|
+
|------|----------|
|
|
403
|
+
| 레이아웃 | 섹션 경계, flex/grid 방향, 요소 배치, 중첩 관계 |
|
|
404
|
+
| 배경 | 이미지 배경 vs 단색 vs 그라데이션, 오버레이 유무 |
|
|
405
|
+
| 색상 | 배경색, 텍스트색, 버튼색, 보더색 (hex 추정) |
|
|
406
|
+
| 타이포 | 제목/본문 크기 비율, 굵기, 줄간격 (스케일 팩터 적용) |
|
|
407
|
+
| 간격 | 섹션 패딩, 요소 간 gap, 마진 (스케일 팩터 적용) |
|
|
408
|
+
| 이미지 배치 | Background vs Content vs Overlay (R-4 분류) |
|
|
409
|
+
| 시각적 계층 | z-index 관계, 겹침 구조, 투명도 |
|
|
410
|
+
|
|
411
|
+
### 참조 코드에서 읽어야 하는 것 (보조)
|
|
412
|
+
|
|
413
|
+
```
|
|
414
|
+
✅ 이미지 에셋 URL (다운로드용) — 이것이 참조 코드의 핵심 가치
|
|
415
|
+
✅ 정확한 hex 색상값 (스크린샷 추정보다 정확할 때)
|
|
416
|
+
✅ 폰트 패밀리명
|
|
417
|
+
✅ 정확한 border-radius, shadow 값
|
|
418
|
+
⚠️ 레이아웃 구조 — 스크린샷과 대조 후 채택
|
|
419
|
+
❌ px 값 그대로 사용 — 반드시 스케일 팩터 적용
|
|
259
420
|
```
|