Figma 원본 이미지
reference/ 는 Figma 「Cocode Scaffold App v1.0」 페이지 49:7 의 화면 프레임 78개를 1배율로 내보낸 원본 PNG 다
(폰 390 34장 · 태블릿 1024 11장 · 데스크톱 1440 33장). 화면마다의 노드 id · 섹션 · 역할 · 기기 · 크기 · 캡션 · 원본 링크는
화면 대장 docs/product/figma-screens.json 에 있고, 대장의 image 가 이 폴더의 파일을 가리킨다.
구현 캡처와 견줄 기준 이미지다 — 구현 캡처로 덮어쓰지 않는다.
이 폴더와 대장은 scaffold-booking(7f28d21)의 docs/design/figma/ 와 같은 모양이다(#9). 달라진 것: 대장을 손으로 짓지
않고 읽기 전용 레시피 tool/design/figma/export_ledger.figma.js 가 읽은 값을 tool/design/figma/build_ledger.py 가
digest 로 검산하며 짓는다(아래 「대장 다시 만들기」).
내보낸 방법
- 2026-11-02 에 내보냈다(대장
exportedAt=2026-11-02T07:38:55Z— 마지막 PNG 를 받은 시각). - Figma MCP
get_screenshot에maxDimension= 프레임의 긴 변,contentsOnly: true를 주면 1배율 PNG 의 짧은 수명 URL 이 온다. 받자마자curl -f -L로 저장했다. 파일 이름은 대장key+.png다(예:CL-A7+CL-A5@1024.png). - 이미지는 크기를 바꾸거나 고치지 않는다. 모든 PNG 가 프레임 크기 그대로다 — 세로로 긴 프레임(예: 390×1389)도 그 크기가 기준이다.
78장 모두 응답의
original_width/height와 PNG IHDR 크기가 프레임 크기와 같다. Figma 렌더 그대로라 Figma 쪽 결함도 그대로 담긴다. 고칠 곳은 Figma 다.
대장의 insets · modes
insets.top은 상태 바(SystemBarPhone) 띠의 아래 끝,insets.bottom은 홈 인디케이터(HomeIndicator) 띠의 높이다(논리 px, 없으면 0). 인스턴스 안에 든 것까지 찾는다. 앱이 그리지 않는 띠라 대조에서 가린다.- 폰 34장: 위 44 는 모두. 아래 34 는 30장이고, 홈 인디케이터가 없는
CL-08·CL-09·CL-10·CL-S14장은 0. - 태블릿 11장은 모두 폰용
SystemBarPhone(44)을 1024 폭으로 쓴다. 수강생 태블릿 5장(CL-01·CL-03·CL-04·CL-11·CL-05)만 홈 인디케이터(34)가 있고 관리자 태블릿 6장은 없다(0). - 데스크톱 33장은 0/0.
- 폰 34장: 위 44 는 모두. 아래 34 는 30장이고, 홈 인디케이터가 없는
modes.typography는 CoUI 「Semantic/ Typography」,modes.color는 앱 색 확장 컬렉션 (「Semantic/ Color · CoUI → Violet (…)」 — 앱 색 컬렉션 「Semantic/ Color · Violet」를 CoUI 변수에 덮어쓴 것)의 모드 이름이다. 프레임의explicitVariableModes를 읽고, 프레임에 없으면resolvedVariableModes(상속 · 컬렉션 기본값)를 적었다 — 78장 모두 색 모드Light가 프레임에 명시돼 있고, 1024 11장 + 1440 33장 = 44장은 글자 모드Desktop도 명시돼 있다. 390 34장은 글자 모드를 명시하지 않아 기본 모드Mobile이다.
대장 다시 만들기
Figma 가 바뀌었을 때(화면이 늘거나 캡션 · 띠가 바뀜) 다시 읽는다. 앱마다 바꾸는 값은 레시피 머리의 두 줄(페이지 id · 코드 접두사)뿐이다.
tool/design/figma/export_ledger.figma.js를 Figma MCPuse_figma에 그대로 넣어 돌린다(읽기 전용). 반환{digest, notesDigest, count, rows, notes}를 파일(예:/tmp/ledger-export.json)로 옮겨 적는다.- 프레임 목록(
{fileKey, page, frames:[{nodeId,name,keys,device,width,height,section}]})을 준비한다 —get_metadata의 페이지 XML 에서 Caption 프레임을 뺀 것. python3 tool/design/figma/build_ledger.py --frames <프레임 목록> --export /tmp/ledger-export.json --prefix CL— 옮겨 적기를 digest 로 검산하고 프레임 목록과 이름 · 크기를 대조해 대장을 쓴다.
한 화면 다시 내보내기
- 대장에서 그 화면의
node·width·height를 확인한다. get_screenshot(fileKey6yq0C3oSVVR2HdaOe807eB,nodeId=node,maxDimension= 긴 변,contentsOnly: true)으로 받은 URL 을 바로curl -f -L -o docs/design/figma/reference/<key>.png "<url>"로 저장한다(URL 은 곧 만료된다 — 어디에도 적지 않는다).- 프레임 크기 · 캡션 · 상태 바 · 홈 인디케이터가 바뀌었으면 대장의 해당 필드도 고치고,
exportedAt을 내보낸 시각(UTC)으로 바꾼다. - 확인:
dart tool/design/check_figma_screens.dart— 필드 · key · PNG IHDR 크기 · 기기 폭과, 대장이 가리키지 않는 PNG 를 본다. 계약 게이트tool/gates/check_all.sh도 이 검사를 부른다.
글자 사양 spec/ — 화면마다 더한다
spec/<key>.design.json 은 그 화면의 글자 노드만 담은 co_golden.design_spec 이다(서체 · 굵기 · 크기 · 행간 · 자간 · 색 변수 ·
잉크 상자). 수락 보고의 「글자 밖」 수와 co_golden 구조 대조가 읽는다. 화면 구현 PR 이 그 화면 몫을 더한다(지금은 CL-01 세 크기).
tool/design/figma/export_text_spec.figma.js의PAGE_ID·FRAME(대장의node) 두 줄을 고쳐use_figma로 돌린다(읽기 전용). 반환{digest, len, count, json}의json을 파일로 옮겨 적는다.python3 tool/design/figma/build_text_spec.py --key CL-01@390 --export <그 파일> --digest <digest> --len <len>— 옮겨 적기를 digest 로 검산하고 대장의 이름 · 크기와 견준 뒤spec/<key>.design.json을 쓴다. 프레임 밖에 걸친 글자(스크롤로만 닿는 줄)는 싣지 않는다.- 앱 이름 글자가 담기므로
identity.yaml의files에 올린다.
Figma 쪽에서 본 것 (Figma 는 고치지 않았다)
- 페이지 머리말의 「수강생 7장 + 관리자 2장」은 지금 화면 수(수강생 14 · 관리자 17 · 시작 3)와 다르다(원문 그대로 대장
notes에 있다). - 관리자 태블릿 6장(
CL-A7+CL-A5·CL-A4·CL-A8·CL-A11·CL-A15·CL-A16)의 resolved 모드에 다른 CoUI 컬렉션 「1-2. Semantic/ Typography」(Desktop)도 보인다 — 일부 컴포넌트가 그 컬렉션에 묶인 듯하다(추측). - scrim 사각형 2개(
CL-13@390·CL-13@1440)는 레이어 불투명도 0.32 에 채움 불투명도 0.6 이 곱해져 실효 0.192 다. CoUI 는 같은 검정에 0.6(CoreOpacity.scrim)을 쓴다 — scaffold-booking 의 오너 결정(11-02)은 「Figma scrim 레이어 불투명도를 0.6 으로」였다. - 앱 색 확장 컬렉션은 CoUI 라이브러리 변수 149개 중 49개만 앱 색으로 덮는다(나머지 100개는 라이브러리 값). 그 100개 가운데 앱
컬렉션에도 같은 이름이 있는데 값이 다른 것이 19개다(
tertiary계열 ·*-fixed·primary-text-large·accent등) —docs/design/figma/tokens/brand-colors.json의couiExtension.notOverriddenDiffering.