Figma Bridge
Figma에는 공개 쓰기 API가 없습니다. 이 스킬은 로컬 브리지를 사용합니다. HTTP를 통한 명명된 작업이 플러그인 내부에서 Figma Plugin API를 통해 실행됩니다. OAuth나 토큰이 필요하지 않습니다.
저장소: https://github.com/iggypcnfsky/figma-bridge — AGENTS.md, docs/ops-reference.md.
사전 조건 — 다른 모든 작업 전에 확인
figma가 PATH에 있으므로, 파일 시스템에서 저장소를 검색하지 마십시오:
figma doctor # 저장소, 서버, 연결된 윈도우, img-forge + FAL 키를 한 번에 확인
figma clients # 연결된 모든 Figma 윈도우의 id, 파일, 페이지
figma rules # 프로젝트 제약 조건: 타입 플로어, 그리드, 프레임 크기, 버전 명명 규칙
디자인하기 전에 figma rules를 읽으십시오. 캔버스를 아무리 읽어도 알 수 없는 명확하지 않은 제한(예: "Poppins 20/25가 최소")이 포함되어 있습니다. "confirmed": false는 사용자에게 확인해야 할 가정으로 취급하고, {}는 "묻고, 임의로 만들지 마십시오"로 처리하십시오.
명령어가 누락된 경우, 물어본 후에만 node "$(figma where)/server.mjs"를 사용하십시오. 저장소를 find하거나 경로를 추측하지 마십시오.
pluginConnected: false→ 중지하십시오. 사용자에게 조작하려는 파일의 창에서Plugins → Development → Figma Bridge를 실행하도록 요청하십시오. 재시도해도 도움이 되지 않습니다./run에서503은 같은 의미입니다.504 PLUGIN_GONE은 플러그인 창을 닫았다는 뜻입니다.409는 여러 Figma 창이 연결되어 있고 선택되지 않았음을 의미합니다. 사용자가 지정한 파일(--file <NAME>) 또는 클라이언트 id(--client <ID>)를 선택하십시오. 맹목적으로 재시도하지 마십시오. 잘못된 파일을 편집할 수 있습니다.
루프
- 위치 파악.
./bin/figma status→ 파일 이름, 현재 페이지, 선택 항목, 모든 페이지. - 읽기.
selection 2,node <id> 2,find {"name":"Header","allPages":true}.nodeId는 추측하지 마십시오. Figma id는4022:2처럼 보이며 유도할 수 없습니다. - 계획. 부모, 크기, 순서를 결정하십시오. 새 노드는
parentId가 제공되지 않으면 현재 페이지로 이동합니다. - 쓰기.
./bin/figma run '[{...},{...}]'. - 확인.
./bin/figma export <id> out/check.png PNG 2를 실행하고 실제로 이미지를 확인하십시오.
명령어
./bin/figma op '{"op":"status"}'
./bin/figma run '[{"op":"createFrame","name":"Card","width":320,"height":200,"fill":"#0B0B0F",
"props":{"cornerRadius":16,"layoutMode":"VERTICAL","paddingTop":24,"paddingLeft":24,"itemSpacing":12}}]'
./bin/figma run '[{"op":"createText","parentId":"12:34","characters":"Title","fontSize":24,"color":"#FFFFFF"}]'
./bin/figma op '{"op":"varFill","nodeId":"12:34","variableName":"color/bg/surface"}'
./bin/figma export 12:34 out/card.png PNG 2
./bin/figma image 12:34 out/cover.png FILL # 로컬 이미지 파일 → 채우기 (클라우드 업로드 없음)
작업: ping status pages variables styles fonts inventory · selection node find · createFrame createRect createEllipse createText createPage createInstance · update clone reparent remove goto group ungroup select · grids setGrids align distribute effects · applyStyle varFill · export imageFill · exec.
전체 매개변수: docs/ops-reference.md.
알아두면 유용한 디자인 작업 단축키:
- grid는 GRID를 의미합니다: 사용자가 "그리드 설정"이라고 말하면 열이 아닌 정사각형 레이아웃 그리드를 원하는 것입니다:
{"op":"setGrids","nodeId":"…","grid":true}(40px 셀, 기본 40%) 또는"grid":40.columns/rows는 사용자가 열, 12열 그리드, 거터/마진 값을 지정할 때만 사용하십시오. 사각형으로 그리드를 가짜로 만들지 마십시오.kind:"grid"와 함께applyStyle을 사용하면 저장된 그리드 스타일이 적용됩니다. - 항목 행: 먼저 만든 다음
{"op":"align","nodeIds":[…],"mode":"TOP"}및{"op":"distribute","nodeIds":[…],"axis":"HORIZONTAL","gap":24}를 사용하십시오. - 깊이:
{"op":"effects","nodeId":"…","shadow":{"y":8,"blur":24,"color":"#00000033"}}또는{"op":"effects","nodeId":"…","blur":{"type":"BACKGROUND","radius":20}}. - 그라데이션:
{"op":"gradient","nodeId":"…","kind":"linear","angle":135,"stops":[[0,"#8B76FF"],[1,"#0E0E12"]]}— 각도 0은 왼쪽 → 오른쪽, 90은 위쪽 → 아래쪽입니다. 사각형을 쌓아서 그라데이션을 가짜로 만들지 마십시오. - 디자인 시스템:
COMPONENTid로createInstance를 사용한 다음, 변형을 위한instanceProps(먼저 이름 읽기) 및 분리하지 않고 텍스트를 변경하기 위한instanceText를 사용하십시오.applyStyle은 스타일용입니다. 라이브러리에 이미 있는 것을 다시 그리지 말고, 텍스트를 "수정"하기 위해 인스턴스를 분리하지 마십시오. - 간격 확인:
{"op":"measure","a":"1:2","b":"1:3"}은 측면별 간격과 중심 거리를 반환합니다. 정렬을 판단하기 위해 스크린샷을 내보내는 대신 사용하십시오. - 스타일:
saveStyle은 이름으로text/paint/effect/grid스타일을 만들거나 업데이트하고,applyStyle은 적용합니다. 토큰을 한 번 만들고 모든 곳에 적용하십시오. - 반응형:
sizing은 축별로HUG/FILL/FIXED와 최소/최대를 설정합니다.constraints는 자동 레이아웃이 아닌 하위 요소(STRETCH/MIN/MAX/CENTER/SCALE)를 다룹니다. 변경하기 전에node에서 둘 다 읽으십시오.sizing은 속성이 적용되지 않을 때 Figma의 이유와 함께skipped를 반환합니다.
이미지
아트웍이 필요하신가요? 형제 CLI img-forge
(https://github.com/iggypcnfsky/img-forge)로 생성한 다음 배치하십시오. 생성은 Figma 외부에서 이루어지므로
API 키가 플러그인 코드에 들어가지 않고 느린 렌더링이 캔버스를 차단할 수 없습니다:
cd ../img-forge
./img gen --prompt "abstract gradient cover, purple to black" --preset 16:9@2k --out out/cover.png
./img edit --prompt "make it night with neon accents" --ref out/cover.png # 또는 기존 에셋 편집
cd ../figma-bridge
./bin/figma image 12:34 ../img-forge/out/cover.png FILL
FILL은 노드에 맞게 자르고, FIT는 레터박스, TILE은 반복, CROP은 기존 자르기를 존중합니다.
사용자가 선택한 것을 편집하려면 먼저 내보내고(./bin/figma export <nodeId> out/sel.png PNG 2)
해당 파일을 --ref로 전달하십시오.
플러그인 창에는 사람을 위한 생성 / 편집 패널(모델, 크기 사전 설정, 비용, 삽입)도 있습니다.
패널을 프로그래밍 방식으로 구동하지 마십시오. CLI를 사용하십시오. CLI는 더 많은 기능(마스크, 변형, 드라이 런)을 제공합니다.
해당 패널에 저장된 사전 설정은 figma-bridge/presets.json에 있습니다.
기존 초안 작업
"완성되지 않은" 초안도 여전히 결정 사항을 인코딩합니다: 무엇이 옆에 있는지, 무엇이 그룹화되었는지, 요소의 순서, 간격 리듬. 디자인하기 전에 읽고 그대로 유지하십시오.
{"op":"inventory"}— 프레임, 크기 및 타이포그래피 통계.{"op":"structure","nodeId":"<frame>"}— 간격과readingOrder가 있는 행으로 그룹화된 하위 요소; 이것이 작성자가 선택한 그룹화입니다.{"op":"node",…,"depth":2}는 더 깊이 있는 동일한 트리를 제공합니다.- 패턴(반복되는 왼쪽 여백, 항상 세 열 위에 있는 제목)을 기록하고 유지하십시오. 요청에 필요한 것을 변경하고 나머지는 그대로 두십시오.
- 수행한 변경 사항을 보고하십시오 — "레이아웃을 개선했습니다"가 아니라 "바닥글을 40만큼 위로 이동했습니다".
초안을 조용히 정규화하지 마십시오. 일관성을 위해 사용자가 배치한 요소를 이동해야 하는 경우 말하고 물어보십시오. 깔끔해 보이지만 그룹화가 손실된 슬라이드는 개선이 아니라 퇴보입니다.
규칙
- 쓰기 전에 읽으십시오. 최소 두 번의 호출: 검사, 그 다음 변경.
- 한 배치 = 한 가지 생각. 작업은 이전 작업의 결과를 참조할 수 없습니다. 새 노드의
id가 필요하면 두 번의 호출로 나누십시오. - 상속받은 배열을 존중하십시오: 형제 순서, 근접성, 그룹화는 의도입니다. 요청하지 않으면 초안을 더 깔끔하게 보이도록 다시 정렬하지 마십시오. 일관성을 위해 요소를 이동해야 하는 경우 먼저 물어보십시오.
- 명시적인 지시 없이 기존 사용자 레이어를 건드리지 마십시오 (
update,remove,reparent). 자신이 만든 것에는 접두사를 붙이십시오:Bridge / …. - 재작업은 원본 바로 옆, 가능한 한 가깝게 배치하십시오. 슬라이드/화면/섹션을 다시 실행하라는 요청을 받으면:
복제하고
{"op":"placeNear","nodeId":"<new id>","move":true,"gap":80,"name":"Bridge / v2 — <name>"}을 호출하여 복사본이 추측된 좌표 대신 첫 번째 빈 면에 배치되도록 하고 원본은 그대로 두십시오. 도구가free: false를 보고하면 어디로 가야 하는지 물어보십시오. 사용자가 명시적으로 요청한 경우에만 제자리에서 요소를 교체하십시오. goto는 사용자의 보기를 변경합니다 — 요청 시에만.exec는 최후의 수단입니다. 작동하지만(Figma 샌드박스는new Function을 허용함) 모든 매개변수 검증을 우회합니다. JSON 직렬화 가능한 값만 반환하십시오.- 테스트 아티팩트를 정리하거나 유지할지 물어보십시오.
함정
localhost를 사용하십시오.127.0.0.1은 사용하지 마십시오. 플러그인 매니페스트는http://localhost:3847만 허용 목록에 추가합니다(devAllowedDomains). Figma는 IP를 거부합니다. 서버는127.0.0.1과::1모두에서 수신합니다.figma.currentPage는 해당 Figma 창에서 열려 있는 페이지입니다. 저장된 포인터가 아닙니다. 탭을 전환하면 다음 호출에서 보이는 것이 변경됩니다.- 위치는 부모를 기준으로 하며,
parentId가 생략되면 현재 페이지를 의미합니다. - 타이포그래피 관련 질문(글꼴, 크기, 개수)은 한 번의 호출로 처리됩니다:
{"op":"fonts"}; 전체 파일에 대해"allPages":true를 추가하십시오. 자체 스크립트로 프레임을 탐색하지 마십시오. - 슬라이드 데크 개요도 한 번의 호출로 처리됩니다:
{"op":"inventory"}는 형상,minFontSize, 글꼴, 그리드 개수 및 채우기와 함께 모든 프레임을 반환합니다. "프레임 11–19"를 선택하거나 최소 크기 미만의 텍스트를 찾기에 충분합니다. - 참조 문서에 나열되지 않은 필드는 인덱싱하지 마십시오.
summary는 TEXT에 대해font,fontSize,lineHeight및letterSpacing을 전달합니다. 다른 모든 것은 실제 API 이름과 함께exec에서 가져옵니다. 혼합 스타일은 문자열"MIXED"이므로.get()및 대체 값으로 보호하십시오. - 사각형은 하위 요소를 가질 수 없습니다. 텍스트나 아이콘이 도형 안에 있어야 하는 경우 프레임을 사용하십시오.
- 로컬 변수가 없으면
variables는collections: []를 반환하고varFill은 실패합니다. 먼저 확인하십시오. - 텍스트에는 글꼴이 필요합니다:
createText는loadFontAsync를 통해 로드합니다. 패밀리가 없으면Inter를 사용하십시오. export는 8MB로 제한됩니다. 재시도하는 대신scale을 낮추십시오.- 현재 페이지가 아닌 페이지의 하위 요소를 읽으려면
loadAllPagesAsync가 필요합니다. 브리지가 자동으로 한 번 재시도하지만allPages: true와 함께find를 사용하는 것이 좋습니다. - 플러그인 파일(
code.js,ui.html)을 편집한 후 사용자는 플러그인을 다시 실행해야 합니다.manifest.json의 변경 사항은 다시 가져와야 합니다.