컨퍼런스 포스터 생성기 (HTML)
전문 HTML 포스터를 생성합니다. 사용자 참고: $ARGUMENTS
포스터는 React 기반 대화형 편집기입니다. poster/ 디렉토리 안에 있는 단일 자체 포함 HTML 파일입니다. 빌드 단계가 필요 없습니다(React/Babel이 CDN을 통해 로드됨). 사용자는 브라우저에서 레이아웃을 시각적으로 조정한 후 구성을 클로드로 내보내 추가 변경을 요청할 수 있습니다.
프로젝트 폴더 구조
<project>/
├── overleaf/ # Overleaf에서 가져온 논문 소스
│ ├── paper.tex
│ ├── figures/
│ └── ...
├── references/ # 스타일 매칭을 위한 참조 포스터
│ └── (모든 형식: pdf, png, jpg, html, pptx, ...)
├── poster/ # 생성됨: 자체 포함 포스터 웹사이트
│ ├── index.html # 포스터 (React 앱)
│ ├── poster-config.json # 레이아웃 구성 (칼럼, 카드 순서, 높이, 글꼴 배율)
│ ├── logos/ # 기관 로고
│ ├── teaser.png # 복사/변환된 그림
│ ├── qr.png # 프로젝트 페이지 QR 코드
│ ├── qr-posterskill.png # Posterskill QR 코드
│ └── ...
└── .claude/skills/make-poster/
overleaf/에는 논문 소스가 들어 있습니다. 주요.tex파일과 해당 파일이\input{}하는 모든 파일을 읽으십시오.references/에는 사용자가 선호하는 시각적 스타일을 보여주는 예제 포스터가 포함되어 있습니다. 이 폴더의 모든 파일을 읽고/보고 디자인 언어를 일치시키십시오.poster/는 생성된 출력물(자체 포함 웹사이트)입니다. 모든 그림과 에셋이index.html과 함께 있으므로 상대 경로가 바로 작동합니다.
입력
- 논문 소스 -
overleaf/에 있습니다. 사용자에게 읽을 주요.tex파일(예:paper.tex,main.tex)을 물어보십시오. 그런 다음 해당 파일과\input{}하는 모든 파일을 읽으십시오. - 프로젝트 웹사이트 - 아직 알려지지 않은 경우 사용자에게 URL을 물어보십시오. WebFetch로 가져와 저자 정보, 호스팅된 이미지 및 링크를 추출하십시오.
- 참조 포스터 -
references/에서 자동으로 발견됩니다. 해당 폴더의 모든 파일을 보고 스타일을 일치시키십시오. - 저자 웹사이트 (선택 사항) - WebFetch로 가져와 디자인 신호(색상 팔레트, 타이포그래피, 로고)를 추출하십시오. 저자 사이트에서 기관 로고를 Playwright를 사용하여 다운로드하십시오(curl은 리디렉션으로 인해 실패할 수 있음):
page.request.get(url)로 원시 바이트를 다운로드하십시오. - 서식 요구 사항 - 포스터 치수, 방향, 칼럼 수를 물어보십시오.
- Git 저장소 (선택 사항) - 사용자에게 포스터를 푸시할 GitHub 저장소가 있는지 물어보십시오.
사용자가 서식을 지정하지 않은 경우, 진행하기 전에 물어보십시오. 치수, 방향 또는 칼럼 수에 대한 기본값을 가정하지 마십시오.
프로세스
0단계: 스타일 참조 분석
references/에서 PDF, PNG 또는 이미지 파일을 찾으십시오. PDF를 PNG로 변환하십시오(sips -s format png on macOS). 각각을 보고 시각적 스타일(레이아웃, 색상, 타이포그래피, 카드 스타일, 그림 배치)을 기록하십시오. 참조 스타일을 일치시키십시오 — 참조가 밝은 경우 어두운 테마를 기본값으로 사용하지 마십시오.
1단계: 논문 소스에서 콘텐츠 추출
사용자에게 읽을 .tex 파일을 물어보십시오. 추출: 제목, 저자, 소속, 초록(2-3문장), 핵심 방법, 결과(표 + 그림), 핵심 방정식(최대 1-2개), 결론.
2단계: 프로젝트 웹사이트 가져오기
WebFetch를 사용하여 저자 이름, 소속, 그림 URL, QR용 프로젝트 URL, 코드/arxiv/비디오 링크를 가져오십시오.
3단계: 에셋을 poster/로 수집
그림: overleaf/figures/에서 복사하고 PDF를 고해상도 PNG로 변환하십시오:
sips -s format png input.pdf --out poster/output.png -Z 3000
웹사이트 이미지: Playwright를 사용하여 프로젝트 웹사이트에서 더 높은 품질의 이미지를 다운로드하십시오(curl이 아닙니다 — 많은 사이트가 리디렉션함):
resp = page.request.get(url)
with open('poster/filename.png', 'wb') as f:
f.write(resp.body())
로고: Playwright를 사용하여 저자의 개인 웹사이트에서 기관 로고를 다운로드하십시오. poster/logos/에 저장하십시오. 템플릿이 헤더를 위해 자동으로 로고를 흰색으로 반전시킵니다.
QR 코드: 생성 및 저장:
curl -sL -o poster/qr.png "https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=PROJECT_URL"
curl -sL -o poster/qr-posterskill.png "https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=https://github.com/ethanweber/posterskill"
4단계: 이미지 종횡비 측정
여백 제거에 매우 중요합니다. 모든 이미지를 측정하십시오:
sips -g pixelWidth -g pixelHeight poster/*.png poster/*.jpg
그런 다음 종횡비에 따라 이미지를 칼럼에 할당하십시오:
- 넓은 이미지(>2:1 비율, 예: 티저, 아키텍처): 가장 넓은 칼럼에 배치
- 정사각형 이미지(~1:1 비율): 좁은 칼럼에 배치
- 세로 이미지(<1:1 비율): 가장 좁은 칼럼에 배치
이렇게 하면 #1 여백 문제(넓은 이미지가 좁은 셀에 있거나 그 반대의 경우)를 방지할 수 있습니다.
5단계: 포스터 HTML 생성
${{CLAUDE_SKILL_DIR}}/template.html을 시작점으로 사용하십시오. 템플릿은 다음과 같은 React 앱입니다:
아키텍처:
CARD_REGISTRY— 각 카드의 콘텐츠(제목, 색상, JSX 본문)를 정의DEFAULT_LAYOUT— 칼럼 구조와 카드 순서를 정의DEFAULT_LOGOS— 헤더용 기관 로고- React 상태가 레이아웃을 관리하며, localStorage로 지속성 제공
window.posterAPI는 프로그래밍 방식 제어를 위한 함수 노출
사용자 정의해야 할 주요 항목:
- 논문 콘텐츠로
CARD_REGISTRY업데이트(각 섹션은 카드) - 종횡비 최적화 칼럼 할당으로
DEFAULT_LAYOUT업데이트 - 사용자의 기관 로고로
DEFAULT_LOGOS업데이트 DEFAULT_FONT_SCALE업데이트(1.3에서 시작, 사용자가 A-/A+ 버튼으로 조정 가능)- 헤더 업데이트(제목, 저자, 소속, 컨퍼런스 배지, QR 코드)
- 포스터 치수에 맞게
@page { size: WIDTHmm HEIGHTmm; }및body { width: WIDTHmm; height: HEIGHTmm; }업데이트 - 동일한 치수로
posterAPIfit() 함수 업데이트
카드 콘텐츠 패턴:
- 그림 카드:
<div className="fig"><div className="fig-wrap"><img src="file.png" alt="..." /></div><div className="cap"><b>캡션 제목.</b> 설명.</div></div> - 텍스트 카드:
<div className="hl"><p>강조 텍스트</p></div><ul><li>포인트 1</li></ul> - 표 카드:
<table><thead>...</thead><tbody>...</tbody></table>(우승 셀에className="best"사용) - 방정식 카드:
<div className="eq">{'$LaTeX 방정식$'}</div>(JSX에서 백슬래시 이스케이프)
여백 제로를 위한 중요한 CSS 규칙:
- 이미지는 반드시
width:100%; height:100%; object-fit:contain을 사용해야 합니다(max-width/max-height가 아님 — 확장을 방지함) - 각 칼럼은 항상 하나의
grow: true카드(flex:1)를 가져야 하며, 이 카드가 남은 공간을 채웁니다 isCardGrow()함수는 이를 자동으로 보장합니다 — grow 카드가 없으면 마지막 카드가 grow를 받습니다
뷰포트 스케일링:
translate() + scale()을 body에 사용하여 포스터를 모든 브라우저 뷰포트에 중앙 정렬 및 맞춤transform-origin: top left가 중요합니다@media print는 올바른 인쇄 해상도를 위해transform: none !important를 설정해야 합니다getBoundingClientRect()는 스케일링된 값을 반환합니다 — 크기 조정 핸들러에서 항상currentScaleRef.current로 나누어야 합니다
6단계: Playwright로 레이아웃 자동 최적화
생성 후 Playwright를 사용하여 여백을 측정하고 최적의 칼럼 너비를 찾으십시오:
from playwright.sync_api import sync_playwright
import os
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={'width': 3200, 'height': 2260})
page.goto('file://' + os.path.abspath('poster/index.html'))
page.wait_for_load_state('networkidle')
page.wait_for_timeout(3000)
# 여백 측정
waste = page.evaluate('window.posterAPI.getWaste()')
print(f"총 여백: {waste['total']}px")
for d in waste['details']:
print(f" {d['card']}: H={d['wasteH']} W={d['wasteW']} ({d['pct']}%)")
# 여백을 최소화하기 위해 다른 칼럼 너비 시도
best_waste = waste['total']
best_c1, best_c3 = 300, 230
for c1 in range(200, 350, 10):
for c3 in range(160, 280, 10):
page.evaluate(f'window.posterAPI.setColumnWidth("col1", {c1})')
page.evaluate(f'window.posterAPI.setColumnWidth("col3", {c3})')
page.wait_for_timeout(30)
w = page.evaluate('window.posterAPI.getWaste().total')
if w < best_waste:
best_waste = w
best_c1, best_c3 = c1, c3
# 최적값 적용 및 스크린샷
page.evaluate(f'window.posterAPI.setColumnWidth("col1", {best_c1})')
page.evaluate(f'window.posterAPI.setColumnWidth("col3", {best_c3})')
page.wait_for_timeout(500)
page.screenshot(path='/tmp/poster_screenshot.png')
# 칼럼 간 카드 교체도 시도
page.evaluate('window.posterAPI.swapCards("cardA", "cardB")')
# ... 여백 다시 측정 ...
browser.close()
그런 다음 /tmp/poster_screenshot.png를 읽어 시각적으로 검사하십시오. 여러 번 반복하십시오 — 스크린샷을 찍고, 문제를 수정하고, 포스터에 최소한의 빈 공간이 생길 때까지 다시 스크린샷을 찍으십시오.
최적값을 찾은 후에는 이를 HTML의 DEFAULT_LAYOUT, DEFAULT_CARD_HEIGHTS 등에 포함시키십시오.
7단계: PDF 생성 및 확인
page.pdf(
path='poster/poster.pdf',
width='841mm', height='594mm', # 포스터 치수와 일치
margin={'top':'0','right':'0','bottom':'0','left':'0'},
print_background=True
)
PDF를 PNG로 변환하고 읽어 전체 해상도로 렌더링되는지 확인하십시오:
sips -s format png poster/poster.pdf --out /tmp/poster_pdf_check.png -Z 3000
8단계: 사용자와 함께 열고 반복
브라우저에서 포스터를 여십시오:
open poster/index.html
사용자에게 편집 컨트롤을 설명하십시오:
- 미리보기 — 편집 UI를 꺼서 인쇄될 모습을 정확히 봄
- A-/A+ — 글꼴 크기를 전역적으로 조정
- 칼럼 구분선 드래그(세로 파란색 막대) — 칼럼을 왼쪽/오른쪽으로 크기 조정
- 행 구분선 드래그(가로 파란색 막대) — 칼럼 내에서 카드를 위/아래로 크기 조정
- 클릭하여 교체 — 한 카드의 다이아몬드 핸들(주황색으로 변함)을 클릭한 다음 다른 카드를 클릭하여 교체
- 이동/삽입 — 카드 핸들을 클릭한 다음 점선 주황색 드롭 영역을 클릭하여 그곳으로 이동
- 저장 —
poster-config.json다운로드 - 구성 복사 — 레이아웃 JSON을 클립보드에 복사
- 초기화 — 기본값 복원
적극적으로 개선 사항 제안: 첫 번째 초안을 보여준 후, 구체적인 변경을 제안하십시오:
- "모델 아키텍처 카드에 여백이 있습니다 — 위의 행 구분선을 아래로 드래그하여 공간을 줄여보세요"
- "완료 그림은 더 넓으므로 칼럼 2에 있으면 더 좋을 수 있습니다 — 다이아몬드를 클릭한 다음 칼럼 2의 드롭 영역을 클릭해보세요"
- "A+를 몇 번 눌러 글꼴 크기를 키우는 것이 좋을 수도 있습니다"
피드백 루프를 장려하십시오: 사용자에게 알리십시오:
브라우저에서 포스터를 재배열해보세요! 레이아웃이 마음에 들면 오른쪽 상단 도구 모음에서 구성 복사를 클릭하고 여기에 붙여넣으십시오 — 그 변경 사항을 기본값에 반영하여 유지하겠습니다.
사용자가 구성 JSON을 붙여넣으면 HTML의 DEFAULT_LAYOUT, DEFAULT_CARD_HEIGHTS, DEFAULT_FONT_SCALE 및 DEFAULT_LOGOS를 일치하도록 업데이트하십시오. 또한 poster-config.json에 기록하십시오.
9단계: GitHub에 푸시(선택 사항)
사용자가 GitHub 저장소 URL을 제공하는 경우:
cd poster
git init
git remote add origin <REPO_URL>
git add .
git commit -m "포스터: <논문 제목>"
git push -u origin main
중요 지침
- 빈 공간 없음. 이것이 최우선 순위입니다. 종횡비를 인식한 칼럼 할당, 이미지에
width:100%; height:100%; object-fit:contain, 자동 증가 카드, Playwright 최적화 프로그램을 사용하십시오. 여백이 최소화될 때까지 반복하십시오. - 텍스트를 최소화하십시오. 포스터는 시각적입니다 — 문단이 아닌 글머리 기호입니다. 2분 이해.
- 참조 스타일을 일치시키십시오. 참조 포스터가 밝고 깔끔하면 어두운 테마를 사용하지 마십시오. 전체적인 미적 감각을 일치시키십시오.
- 글꼴 스케일링. 모든 텍스트 크기는
calc(Xpt * var(--font-scale))를 사용하므로 A-/A+ 버튼이 작동합니다.--font-scale: 1.3으로 시작하고 사용자가 조정하도록 하십시오. - 인쇄 최적화 CSS.
@media print는 모든 편집 UI를 숨기고transform: none !important를 설정합니다.@page는 정확한 치수를 설정합니다. - Posterskill QR. 항상 헤더에 "내 Claude 스킬로 만든 포스터"라는 레이블과 함께
https://github.com/ethanweber/posterskill에 연결되는 QR 코드를 포함하십시오. - 감사 페이지 없음. 포스터를 깔끔하게 유지하십시오 — 기본적으로 바닥글 없음.
- 헤더의 로고. 저자 웹사이트에서 기관 로고를 다운로드하여
poster/logos/에 저장하고DEFAULT_LOGOS에 나열하십시오. CSS 필터를 통해 자동으로 흰색으로 반전됩니다. - 자체 포함. 빌드 단계, npm, 서버가 필요 없습니다. CDN 종속성이 있는 단일 HTML 파일입니다.
file://로 직접 열 때 작동합니다. - 방정식. KaTeX를 사용하십시오(CDN을 통해 로드). JSX 문자열에서 백슬래시를 이스케이프하십시오:
{'$\mathcal{E}$'}.
그림 처리
- 필요한 그림은 항상
poster/로 복사하십시오 — HTML에서overleaf/경로를 참조하지 마십시오. - PDF를 고해상도 PNG로 변환:
sips -s format png input.pdf --out poster/output.png -Z 3000 - Playwright의
page.request.get()을 통해 웹사이트 이미지를 다운로드하십시오(curl이 아님 — 웹사이트는 종종 리디렉션합니다). sips -g pixelWidth -g pixelHeight로 종횡비를 측정하고 그에 따라 칼럼에 할당하십시오.
구성 업데이트를 위한 사용자 워크플로우
사용자는 브라우저에서 포스터를 조정하고 변경 사항을 다시 공유할 수 있습니다:
- 사용자가 도구 모음에서 "구성 복사"를 클릭합니다
- 사용자가 JSON을 채팅에 붙여넣습니다
- Claude가
DEFAULT_LAYOUT,DEFAULT_CARD_HEIGHTS,DEFAULT_FONT_SCALE,DEFAULT_LOGOS를index.html에서 일치하도록 업데이트합니다 - Claude도 구성을
poster-config.json에 기록합니다 - 사용자가 새로 고치고 "초기화"를 클릭하여 새 기본값을 로드합니다
프로그래밍 방식 API (window.posterAPI)
브라우저 콘솔 또는 Playwright를 통해 사용 가능:
swapCards(id1, id2)— 두 카드 교체(칼럼 간 작동)moveCard(cardId, targetColId, position)— 카드를 특정 위치로 이동setColumnWidth(colId, widthMm)— 칼럼 너비 설정(null은 flex)- ...
[번역을 위해 잘림]
