posterskill-academic-posters

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

posterskill — Academic Poster Generator

posterskill — 学术海报生成工具

Skill by ara.so — Daily 2026 Skills collection.
posterskill is a Claude Code skill that generates print-ready, interactive conference posters from your Overleaf paper source. It produces a single self-contained HTML file with a built-in drag-and-drop visual editor — no build step, no server required.
ara.so开发的Skill — 属于Daily 2026 Skills合集。
posterskill是一款Claude Code技能,可从你的Overleaf论文源文件生成可直接打印、支持交互的会议海报。它会生成一个独立的自包含HTML文件,内置拖放式可视化编辑器——无需构建步骤,无需服务器。

Installation & Setup

安装与设置

bash
git clone git@github.com:ethanweber/posterskill.git poster
cd poster
bash
git clone git@github.com:ethanweber/posterskill.git poster
cd poster

Clone your Overleaf paper source

克隆你的Overleaf论文源文件

Optional: add reference posters for style matching

可选:添加参考海报以匹配风格

cp ~/Downloads/some_reference_poster.pdf references/

Start Claude Code and trigger the skill:

```bash
claude
/make-poster
Claude will ask for your project website URL and any formatting specs, then generate a
poster/
directory with
index.html
.
cp ~/Downloads/some_reference_poster.pdf references/

启动Claude Code并触发该技能:

```bash
claude
/make-poster
Claude会询问你的项目网站URL和格式规范,然后生成包含
index.html
poster/
目录。

Directory Structure

目录结构

poster/                  # this repo
├── .claude/
│   └── commands/
│       └── make-poster.md   # the skill command
├── overleaf/            # your cloned Overleaf project
├── references/          # optional reference PDFs for style matching
└── poster/              # generated output
    ├── index.html       # the poster (self-contained)
    └── logos/           # downloaded institutional logos
poster/                  # 本仓库
├── .claude/
│   └── commands/
│       └── make-poster.md   # 技能命令
├── overleaf/            # 你克隆的Overleaf项目
├── references/          # 可选的参考PDF,用于风格匹配
└── poster/              # 生成的输出文件
    ├── index.html       # 海报文件(自包含)
    └── logos/           # 下载的机构标识

What Gets Generated

生成内容说明

The output
poster/index.html
is a React app (loaded via CDN) containing:
  • CARD_REGISTRY
    — each card's title, color, and JSX body content
  • DEFAULT_LAYOUT
    — column structure and card ordering
  • DEFAULT_LOGOS
    — institutional logos for the header
  • window.posterAPI
    — programmatic API for layout automation
输出的
poster/index.html
是一个通过CDN加载的React应用,包含:
  • CARD_REGISTRY
    — 每个卡片的标题、颜色和JSX主体内容
  • DEFAULT_LAYOUT
    — 列结构与卡片排序
  • DEFAULT_LOGOS
    — 页眉处的机构标识
  • window.posterAPI
    — 用于布局自动化的编程式API

Visual Editor Features

可视化编辑器功能

Open
poster/index.html
in Chrome to access the built-in editor:
FeatureHow to Use
Resize columnsDrag column dividers left/right
Resize cardsDrag row dividers up/down within a column
Swap cardsClick one diamond handle, then another
Move/insert cardsClick a handle, then click a drop zone
Adjust font sizeClick A- / A+ buttons in toolbar
Preview print layoutClick Preview button
Export layoutClick Copy Config to get JSON
在Chrome中打开
poster/index.html
即可访问内置编辑器:
功能使用方法
调整列宽左右拖动列分隔线
调整卡片高度在列内上下拖动行分隔线
交换卡片点击一个菱形手柄,再点击另一个
移动/插入卡片点击手柄,然后点击放置区域
调整字体大小点击工具栏中的A- / **A+**按钮
预览打印布局点击预览按钮
导出布局点击复制配置获取JSON

Programmatic API (
window.posterAPI
)

编程式API (
window.posterAPI
)

Available in the browser console or via Playwright automation:
js
// Swap two cards by ID
posterAPI.swapCards('method', 'results')

// Move a card to a specific column and position
posterAPI.moveCard('quant', 'col1', 2)

// Resize a column (in mm)
posterAPI.setColumnWidth('col1', 280)

// Set a specific card's height (in mm)
posterAPI.setCardHeight('method', 150)

// Scale all text globally
posterAPI.setFontScale(1.5)

// Measure whitespace waste (lower = better layout)
posterAPI.getWaste()

// Get the current layout as an object
posterAPI.getLayout()

// Get the full config as JSON (paste back to Claude)
posterAPI.getConfig()

// Reset to default layout
posterAPI.resetLayout()
可在浏览器控制台或通过Playwright自动化使用:
js
// 通过ID交换两张卡片
posterAPI.swapCards('method', 'results')

// 将卡片移动到指定列和位置
posterAPI.moveCard('quant', 'col1', 2)

// 调整列宽(单位:毫米)
posterAPI.setColumnWidth('col1', 280)

// 设置指定卡片的高度(单位:毫米)
posterAPI.setCardHeight('method', 150)

// 全局缩放所有文本
posterAPI.setFontScale(1.5)

// 测量空白浪费率(数值越低,布局越优)
posterAPI.getWaste()

// 获取当前布局对象
posterAPI.getLayout()

// 获取完整配置的JSON(可粘贴回Claude)
posterAPI.getConfig()

// 重置为默认布局
posterAPI.resetLayout()

Iteration Workflow

迭代工作流程

The core loop for refining your poster:
  1. Claude generates first draft, opens
    poster/index.html
    in your browser
  2. You edit in the browser — drag dividers, swap cards, resize columns
  3. Click "Copy Config" in the toolbar to export your layout as JSON
  4. Paste the JSON back to Claude — it updates
    DEFAULT_LAYOUT
    in the HTML
  5. Repeat until the layout is perfect
  6. Print to PDF: File → Print → Margins: None, Background Graphics: On
优化海报的核心循环:
  1. Claude生成初稿,在浏览器中打开
    poster/index.html
  2. 你在浏览器中编辑 — 拖动分隔线、交换卡片、调整列宽
  3. **点击“复制配置”**导出布局为JSON
  4. 将JSON粘贴回Claude — 它会更新HTML中的
    DEFAULT_LAYOUT
  5. 重复直到布局完美
  6. 打印为PDF:文件 → 打印 → 边距:无,背景图形:开启

Playwright Automation (used internally by Claude)

Playwright自动化(Claude内部使用)

Claude uses Playwright to automate layout verification. You can use it too:
js
const { chromium } = require('playwright');

async function optimizePoster() {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  
  await page.goto(`file://${__dirname}/poster/index.html`);
  
  // Use the posterAPI to adjust layout programmatically
  const waste = await page.evaluate(() => posterAPI.getWaste());
  console.log('Whitespace waste:', waste);
  
  // Resize a column
  await page.evaluate(() => posterAPI.setColumnWidth('col1', 300));
  
  // Take a screenshot for visual verification
  await page.screenshot({ path: 'poster-preview.png', fullPage: true });
  
  // Generate PDF at print resolution
  await page.pdf({
    path: 'poster.pdf',
    width: '841mm',   // A0 landscape width
    height: '1189mm',
    printBackground: true,
  });
  
  await browser.close();
}
Claude使用Playwright自动验证布局,你也可以使用:
js
const { chromium } = require('playwright');

async function optimizePoster() {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  
  await page.goto(`file://${__dirname}/poster/index.html`);
  
  // 使用posterAPI以编程方式调整布局
  const waste = await page.evaluate(() => posterAPI.getWaste());
  console.log('Whitespace waste:', waste);
  
  // 调整列宽
  await page.evaluate(() => posterAPI.setColumnWidth('col1', 300));
  
  // 截图用于视觉验证
  await page.screenshot({ path: 'poster-preview.png', fullPage: true });
  
  // 生成打印分辨率的PDF
  await page.pdf({
    path: 'poster.pdf',
    width: '841mm',   // A0横向宽度
    height: '1189mm',
    printBackground: true,
  });
  
  await browser.close();
}

Card Registry Structure

卡片注册表结构

Each card in the poster is defined in
CARD_REGISTRY
:
js
const CARD_REGISTRY = {
  abstract: {
    title: "Abstract",
    color: "#f0f4ff",
    body: `
      <p>Your abstract text here. Supports full JSX including
      <strong>bold</strong>, <em>italic</em>, and inline math.</p>
    `
  },
  method: {
    title: "Method",
    color: "#fff8f0",
    body: `
      <img src="figures/pipeline.png" style={{width:'100%'}} />
      <p>Caption describing the pipeline above.</p>
    `
  },
  results: {
    title: "Results",
    color: "#f0fff4",
    body: `
      <table>...</table>
    `
  }
};
海报中的每个卡片都在
CARD_REGISTRY
中定义:
js
const CARD_REGISTRY = {
  abstract: {
    title: "Abstract",
    color: "#f0f4ff",
    body: `
      <p>Your abstract text here. Supports full JSX including
      <strong>bold</strong>, <em>italic</em>, and inline math.</p>
    `
  },
  method: {
    title: "Method",
    color: "#fff8f0",
    body: `
      <img src="figures/pipeline.png" style={{width:'100%'}} />
      <p>Caption describing the pipeline above.</p>
    `
  },
  results: {
    title: "Results",
    color: "#f0fff4",
    body: `
      <table>...</table>
    `
  }
};

Default Layout Structure

默认布局结构

js
const DEFAULT_LAYOUT = {
  columns: [
    {
      id: 'col1',
      widthMm: 280,
      cards: ['abstract', 'method']
    },
    {
      id: 'col2', 
      widthMm: 320,
      cards: ['results', 'quant']
    },
    {
      id: 'col3',
      widthMm: 280,
      cards: ['conclusion', 'references']
    }
  ]
};
js
const DEFAULT_LAYOUT = {
  columns: [
    {
      id: 'col1',
      widthMm: 280,
      cards: ['abstract', 'method']
    },
    {
      id: 'col2', 
      widthMm: 320,
      cards: ['results', 'quant']
    },
    {
      id: 'col3',
      widthMm: 280,
      cards: ['conclusion', 'references']
    }
  ]
};

Inputs Claude Uses

Claude使用的输入信息

InputWhere It Comes FromRequired
Paper content
overleaf/
directory
Yes
Project websiteURL (asked at runtime)Yes
Reference posters
references/*.pdf
No
Author websiteURL for brand matchingNo
Formatting specsConference URL or textAsked if missing
LogosAuto-downloaded to
poster/logos/
Auto
输入内容来源是否必填
论文内容
overleaf/
目录
项目网站运行时询问的URL
参考海报
references/*.pdf
作者网站用于品牌匹配的URL
格式规范会议URL或文本缺失时询问
标识自动下载到
poster/logos/
自动处理

Common Patterns

常见使用模式

Adding a custom figure card

添加自定义图片卡片

js
// In CARD_REGISTRY, add a new card
custom_fig: {
  title: "Qualitative Results",
  color: "#fafafa",
  body: `
    <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:'8px'}}>
      <img src="figures/result1.png" style={{width:'100%'}} />
      <img src="figures/result2.png" style={{width:'100%'}} />
    </div>
    <p style={{fontSize:'0.85em', textAlign:'center'}}>
      Comparison on held-out test scenes.
    </p>
  `
}
Then add it to
DEFAULT_LAYOUT
:
js
{ id: 'col2', widthMm: 320, cards: ['results', 'custom_fig'] }
js
// 在CARD_REGISTRY中添加新卡片
custom_fig: {
  title: "Qualitative Results",
  color: "#fafafa",
  body: `
    <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:'8px'}}>
      <img src="figures/result1.png" style={{width:'100%'}} />
      <img src="figures/result2.png" style={{width:'100%'}} />
    </div>
    <p style={{fontSize:'0.85em', textAlign:'center'}}>
      Comparison on held-out test scenes.
    </p>
  `
}
然后将其添加到
DEFAULT_LAYOUT
js
{ id: 'col2', widthMm: 320, cards: ['results', 'custom_fig'] }

Logos configuration

标识配置

js
const DEFAULT_LOGOS = [
  { src: 'logos/university.png', height: 60 },
  { src: 'logos/lab.png', height: 50 },
  { src: 'logos/sponsor.png', height: 45 },
];
js
const DEFAULT_LOGOS = [
  { src: 'logos/university.png', height: 60 },
  { src: 'logos/lab.png', height: 50 },
  { src: 'logos/sponsor.png', height: 45 },
];

Printing to PDF

打印为PDF

In Chrome:
  1. Open
    poster/index.html
  2. Click Preview to verify layout
  3. Ctrl+P
    /
    Cmd+P
  4. Set Margins: None
  5. Enable Background graphics
  6. Set paper size to your conference spec (A0, 36×48in, etc.)
  7. Save as PDF
在Chrome中:
  1. 打开
    poster/index.html
  2. 点击预览验证布局
  3. Ctrl+P
    /
    Cmd+P
  4. 设置边距:无
  5. 开启背景图形
  6. 设置纸张尺寸为会议要求(A0、36×48英寸等)
  7. 保存为PDF

Troubleshooting

常见问题排查

Poster looks different in print vs browser → Use Chrome (not Firefox/Safari). Enable "Background graphics" in print dialog.
Figures not loading → Ensure figure paths in the HTML are relative to
poster/index.html
. Claude copies figures to
poster/figures/
— verify the directory exists.
Logos not fetched → Claude uses Playwright to download logos from your project website. If it fails, manually copy logo files to
poster/logos/
and update
DEFAULT_LOGOS
paths.
Layout config not updating after paste → Make sure you paste the full JSON from Copy Config — Claude looks for the complete
DEFAULT_LAYOUT
and
DEFAULT_LOGOS
objects to replace.
Font too small/large for poster size → Use
posterAPI.setFontScale(1.2)
in the browser console, or click A+ / A- buttons, then Copy Config and paste to Claude.
Whitespace gaps between cards → Run
posterAPI.getWaste()
in console to quantify. Use
posterAPI.setCardHeight('cardId', heightMm)
to tune card heights, or drag row dividers manually.
海报打印效果与浏览器显示不一致 → 使用Chrome(不要用Firefox/Safari)。在打印对话框中开启“背景图形”。
图片无法加载 → 确保HTML中的图片路径是相对于
poster/index.html
的。Claude会将图片复制到
poster/figures/
目录——请确认该目录存在。
标识未获取到 → Claude使用Playwright从你的项目网站下载标识。如果失败,手动将标识文件复制到
poster/logos/
并更新
DEFAULT_LOGOS
中的路径。
粘贴后布局配置未更新 → 确保粘贴的是“复制配置”中的完整JSON——Claude会查找完整的
DEFAULT_LAYOUT
DEFAULT_LOGOS
对象进行替换。
海报尺寸下字体过大/过小 → 在浏览器控制台使用
posterAPI.setFontScale(1.2)
,或点击A+ / **A-**按钮,然后复制配置并粘贴回Claude。
卡片之间存在空白间隙 → 在控制台运行
posterAPI.getWaste()
量化空白率。使用
posterAPI.setCardHeight('cardId', heightMm)
调整卡片高度,或手动拖动行分隔线。

Example Output

示例输出

See the Fillerbuster poster (repo) as a live example of posterskill output.
查看Fillerbuster海报仓库),这是posterskill输出的一个实际示例。",