@su-record/vibe 2.8.37 → 2.8.38
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 +66 -46
- package/skills/vibe.figma/templates/figma-handoff.md +4 -4
- package/skills/vibe.figma.convert/SKILL.md +298 -141
- package/skills/vibe.figma.convert/rubrics/conversion-rules.md +71 -80
- package/skills/vibe.figma.convert/templates/component.md +90 -98
- package/skills/vibe.figma.extract/SKILL.md +129 -79
- package/skills/vibe.figma.extract/rubrics/image-rules.md +1 -1
package/package.json
CHANGED
|
@@ -1,32 +1,34 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: vibe.figma
|
|
3
|
-
description: Figma design to code —
|
|
3
|
+
description: Figma design to code — 트리 기반 구조적 코드 생성
|
|
4
4
|
triggers: []
|
|
5
5
|
tier: standard
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# vibe.figma —
|
|
8
|
+
# vibe.figma — Structural Code Generation
|
|
9
9
|
|
|
10
10
|
## 핵심 원칙
|
|
11
11
|
|
|
12
12
|
```
|
|
13
|
-
|
|
13
|
+
Figma 트리가 코드의 원천이다. 스크린샷은 검증용이다.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
✅
|
|
17
|
-
✅
|
|
18
|
-
✅
|
|
15
|
+
✅ Figma Auto Layout → CSS Flexbox 1:1 기계적 매핑
|
|
16
|
+
✅ Figma CSS 속성 → SCSS 직접 변환 (추정 없음)
|
|
17
|
+
✅ Claude는 시맨틱 판단만: 태그 선택, 컴포넌트 분리, 인터랙션
|
|
18
|
+
✅ 스크린샷은 생성이 아닌 검증에만 사용
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## 금지 사항
|
|
22
22
|
|
|
23
23
|
```
|
|
24
|
-
❌
|
|
24
|
+
❌ 스크린샷을 보고 CSS 추정 (범용 LLM의 약점)
|
|
25
|
+
❌ Figma 레이어를 무분별하게 div soup로 변환
|
|
25
26
|
❌ CSS로 이미지 재현 (gradient/shape으로 그림 그리기)
|
|
26
27
|
❌ 이미지 다운로드 없이 코드 생성 진행
|
|
27
28
|
❌ placeholder / 빈 src="" 남기기
|
|
28
|
-
❌
|
|
29
|
+
❌ tree.json에 없는 CSS 값을 추정하여 작성
|
|
29
30
|
❌ 컴포넌트 파일 안에 <style> 블록 / 인라인 style=""
|
|
31
|
+
✅ tree.json의 CSS 속성을 SCSS에 직접 매핑
|
|
30
32
|
✅ 외부 SCSS 파일에만 스타일 작성
|
|
31
33
|
```
|
|
32
34
|
|
|
@@ -34,11 +36,12 @@ tier: standard
|
|
|
34
36
|
|
|
35
37
|
```
|
|
36
38
|
/vibe.figma
|
|
37
|
-
→ Phase 0: Setup (스택 감지, 디렉토리
|
|
39
|
+
→ Phase 0: Setup (스택 감지, 디렉토리 생성, 기존 자산 인덱싱)
|
|
38
40
|
→ Phase 1: Storyboard (스토리보드 → 레이아웃 + 컴포넌트 + 기능 정의)
|
|
39
|
-
→ Phase 2: 재료 확보 (디자인 URL →
|
|
40
|
-
→ Phase 3:
|
|
41
|
-
→ Phase
|
|
41
|
+
→ Phase 2: 재료 확보 (디자인 URL → 트리 + 이미지 + 스크린샷)
|
|
42
|
+
→ Phase 3: 구조적 코드 생성 (트리 → HTML+SCSS 매핑 + 시맨틱 보강)
|
|
43
|
+
→ Phase 3.5: 컴파일 게이트 (tsc → build → dev 확인)
|
|
44
|
+
→ Phase 4: 시각 검증 루프 (렌더링 vs 스크린샷 비교 → 수정)
|
|
42
45
|
```
|
|
43
46
|
|
|
44
47
|
---
|
|
@@ -242,8 +245,14 @@ URL에서 fileKey, nodeId 추출
|
|
|
242
245
|
*/
|
|
243
246
|
- TypeScript 인터페이스
|
|
244
247
|
- 목 데이터 (빈 배열 금지, 3~7개 아이템)
|
|
248
|
+
- 목 데이터의 image 필드: 실제 다운로드할 이미지 경로 사용 금지
|
|
249
|
+
→ Phase 1에서는 이미지 경로를 '' (빈 문자열) 또는 placeholder 텍스트로 설정
|
|
250
|
+
→ Phase 2에서 실제 이미지 다운로드 후 경로를 업데이트
|
|
251
|
+
→ ❌ '/images/{feature}/token-100.png' (존재하지 않는 파일 참조 금지)
|
|
245
252
|
- 이벤트 핸들러 stub (body는 // TODO:)
|
|
246
253
|
|
|
254
|
+
❌ <client-only> 래핑 금지 — SSR hydration 실패 위험
|
|
255
|
+
(<client-only>는 window/document 직접 접근하는 컴포넌트에만 사용)
|
|
247
256
|
<style> 블록 없음 — 스타일은 Phase 3에서 외부 파일로.
|
|
248
257
|
|
|
249
258
|
3. 공통 컴포넌트 (SHARED에서 파악):
|
|
@@ -267,6 +276,8 @@ Phase 1 완료 조건:
|
|
|
267
276
|
□ 클릭하면 핸들러가 실행된다
|
|
268
277
|
□ 모든 컴포넌트에 [기능 정의] + [인터랙션] + [상태] JSDoc
|
|
269
278
|
□ 빈 배열 0개, 빈 template 0개, <style> 블록 0개
|
|
279
|
+
□ <client-only> 전체 래핑 0개
|
|
280
|
+
□ 목 데이터의 image 필드에 존재하지 않는 파일 경로 0개
|
|
270
281
|
□ 빌드 성공
|
|
271
282
|
|
|
272
283
|
빈 화면 = Phase 1 미완성. Phase 2로 넘어가지 않는다.
|
|
@@ -313,6 +324,16 @@ URL에서 fileKey, nodeId 추출
|
|
|
313
324
|
node "[FIGMA_SCRIPT]" images {fileKey} {nodeId} --out=/tmp/{feature}/images/ --depth=10
|
|
314
325
|
→ 모든 이미지 에셋 확보. 누락 0건, 0byte 0건.
|
|
315
326
|
|
|
327
|
+
3.5단계 — 아이템/아이콘 노드 렌더링 (추가 시각 재료):
|
|
328
|
+
tree.json에서 INSTANCE/COMPONENT 타입 중 아이템 후보를 식별:
|
|
329
|
+
- name에 "item", "icon", "reward", "token", "coin", "badge" 포함
|
|
330
|
+
- 크기 50~300px 범위의 독립 요소
|
|
331
|
+
- fill 이미지가 없지만 시각적으로 의미 있는 노드
|
|
332
|
+
해당 노드를 개별 렌더링:
|
|
333
|
+
node "[FIGMA_SCRIPT]" images {fileKey} {nodeId} --render --nodeIds={id1},{id2},... --out=/tmp/{feature}/images/
|
|
334
|
+
→ 이미지 fill이 아닌 벡터/인스턴스 에셋도 PNG로 확보
|
|
335
|
+
→ Phase 3에서 목 데이터의 image 경로에 연결
|
|
336
|
+
|
|
316
337
|
4단계 — 섹션별 스크린샷 (부분 정답):
|
|
317
338
|
트리의 1depth 자식 프레임 각각:
|
|
318
339
|
node "[FIGMA_SCRIPT]" screenshot {fileKey} {child.nodeId} --out=/tmp/{feature}/sections/{child.name}.png
|
|
@@ -542,40 +563,40 @@ Phase 1에서 생성한 빈 SCSS 파일에 기본 내용 Write:
|
|
|
542
563
|
❌ 90% 유사한데 새로 만들기 금지
|
|
543
564
|
```
|
|
544
565
|
|
|
545
|
-
### 3-1.
|
|
566
|
+
### 3-1. 트리 기반 구조적 코드 생성
|
|
546
567
|
|
|
547
568
|
```
|
|
548
|
-
각 섹션에
|
|
549
|
-
|
|
550
|
-
1. 정답 확인 — 섹션 스크린샷을 Read로 본다
|
|
551
|
-
/tmp/{feature}/sections/{section}.png
|
|
552
|
-
→ "이 화면처럼 만들어야 한다"
|
|
569
|
+
각 섹션에 대해 (vibe.figma.convert 참조):
|
|
553
570
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
- 텍스트: TEXT 노드의 characters
|
|
571
|
+
1. 트리 구조 읽기 — tree.json에서 해당 섹션 노드를 Read
|
|
572
|
+
→ Auto Layout 속성(flex, gap, padding)이 코드의 기반
|
|
573
|
+
→ 스크린샷은 검증용으로만 참조
|
|
558
574
|
|
|
559
|
-
|
|
575
|
+
2. 기계적 매핑 (추정 없음):
|
|
560
576
|
a. 이미지 복사: images/ → static/images/{feature}/
|
|
561
|
-
b.
|
|
562
|
-
-
|
|
563
|
-
-
|
|
564
|
-
-
|
|
565
|
-
-
|
|
566
|
-
-
|
|
567
|
-
c.
|
|
568
|
-
-
|
|
569
|
-
|
|
570
|
-
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
-
|
|
576
|
-
-
|
|
577
|
-
-
|
|
578
|
-
|
|
577
|
+
b. 노드 → HTML 매핑:
|
|
578
|
+
- Auto Layout 있음 → <div> + flex (direction/gap/padding 직접)
|
|
579
|
+
- Auto Layout 없음 → <div> + position:relative (자식 absolute)
|
|
580
|
+
- TEXT 노드 → <span> (Claude가 h2/p/button으로 승격)
|
|
581
|
+
- imageRef 있음 → <img src="다운로드된 파일">
|
|
582
|
+
- 반복 패턴 (동일 구조 3+) → v-for
|
|
583
|
+
c. CSS 직접 매핑:
|
|
584
|
+
- node.css의 모든 속성을 SCSS에 1:1 매핑
|
|
585
|
+
- scaleFactor 적용 (px 값만)
|
|
586
|
+
- tree.json에 없는 CSS 값은 작성하지 않음
|
|
587
|
+
d. Phase 1의 JSDoc, 인터페이스, 핸들러 보존
|
|
588
|
+
|
|
589
|
+
3. Claude 시맨틱 보강:
|
|
590
|
+
- div → section/h2/p/button 태그 승격
|
|
591
|
+
- 컴포넌트 분리 + props 설계
|
|
592
|
+
- 접근성 (alt, aria)
|
|
593
|
+
- 인터랙션 (클릭, 상태)
|
|
594
|
+
|
|
595
|
+
4. 자가 검증:
|
|
596
|
+
- template 클래스 ↔ SCSS 클래스 1:1 일치
|
|
597
|
+
- 모든 img src가 static/에 실제 존재
|
|
598
|
+
- Auto Layout 노드 → SCSS에 flex 속성 존재
|
|
599
|
+
- 스크린샷과 비교 (시각 확인)
|
|
579
600
|
```
|
|
580
601
|
|
|
581
602
|
### 3-2. 코드 작성 규칙
|
|
@@ -583,11 +604,10 @@ Phase 1에서 생성한 빈 SCSS 파일에 기본 내용 Write:
|
|
|
583
604
|
```
|
|
584
605
|
컴포넌트 (Vue 예시):
|
|
585
606
|
<template>
|
|
586
|
-
|
|
587
|
-
|
|
607
|
+
tree.json의 Auto Layout 구조를 HTML flex 레이아웃으로 직접 매핑.
|
|
608
|
+
Claude가 시맨틱 태그로 승격 (div → section/h2/p/button).
|
|
588
609
|
Phase 1의 기능 요소(v-for, @click, v-if) 보존.
|
|
589
|
-
|
|
590
|
-
이미지 경로: /images/{feature}/파일명.png
|
|
610
|
+
이미지 경로: /images/{feature}/파일명.png (실제 파일 존재 확인)
|
|
591
611
|
텍스트: tree.json의 TEXT 노드 characters 값 그대로.
|
|
592
612
|
|
|
593
613
|
<script setup>
|
|
@@ -40,11 +40,11 @@ Breakpoint threshold: `@media (min-width: {{BP_PC}}px)`
|
|
|
40
40
|
|
|
41
41
|
## Sections
|
|
42
42
|
|
|
43
|
-
| # | Section Name | Component File |
|
|
44
|
-
|
|
45
|
-
| 1 | {{SECTION_NAME}} | `components/{{FEATURE_KEY}}/{{ComponentName}}.vue` | {{
|
|
43
|
+
| # | Section Name | Component File | Tree Nodes | Height (design) |
|
|
44
|
+
|---|-------------|---------------|-----------|----------------|
|
|
45
|
+
| 1 | {{SECTION_NAME}} | `components/{{FEATURE_KEY}}/{{ComponentName}}.vue` | {{NODE_COUNT}} | {{HEIGHT}}px |
|
|
46
46
|
|
|
47
|
-
**
|
|
47
|
+
**Generation:** tree.json → HTML+SCSS 구조적 매핑 (external SCSS)
|
|
48
48
|
|
|
49
49
|
---
|
|
50
50
|
|