Markdown Exporter
bowenliang123/markdown-exporter
Convert Markdown text to DOCX, PPTX, XLSX, PDF, PNG, SVG, HTML, IPYNB, MD, CSV, JSON, JSONL, XML files, and extract code blocks in Markdown to Python, Bash,JS and etc files.
Convert academic papers (PDF) into conference posters (HTML/PNG).
$ npx skills add QuZhan51496/paper2anything --skill paper2poster -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install QuZhan51496/paper2anything paper2poster --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/QuZhan51496/paper2anything.git skills-src && mkdir -p .claude/skills && cp -r skills-src/paper2poster .claude/skills/paper2poster && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "paper2poster" agent skill from https://github.com/QuZhan51496/paper2anything/tree/main/paper2poster into .claude/skills/paper2poster/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "paper2poster", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/QuZhan51496/paper2anything/tree/main/paper2posterType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add QuZhan51496/paper2anything --skill paper2poster -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install QuZhan51496/paper2anything paper2poster --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/QuZhan51496/paper2anything.git skills-src && mkdir -p .agents/skills && cp -r skills-src/paper2poster .agents/skills/paper2poster && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "paper2poster" agent skill from https://github.com/QuZhan51496/paper2anything/tree/main/paper2poster into .agents/skills/paper2poster/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "paper2poster", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add QuZhan51496/paper2anything --skill paper2poster -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install QuZhan51496/paper2anything paper2poster --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/QuZhan51496/paper2anything.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/paper2poster .cursor/skills/paper2poster && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "paper2poster" agent skill from https://github.com/QuZhan51496/paper2anything/tree/main/paper2poster into .cursor/skills/paper2poster/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "paper2poster", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/QuZhan51496/paper2anything.git --path paper2poster--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add QuZhan51496/paper2anything --skill paper2poster -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install QuZhan51496/paper2anything paper2poster --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/QuZhan51496/paper2anything.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/paper2poster .gemini/skills/paper2poster && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "paper2poster" agent skill from https://github.com/QuZhan51496/paper2anything/tree/main/paper2poster into .gemini/skills/paper2poster/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "paper2poster", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install QuZhan51496/paper2anything paper2posterInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add QuZhan51496/paper2anything --skill paper2poster -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/QuZhan51496/paper2anything.git skills-src && mkdir -p .github/skills && cp -r skills-src/paper2poster .github/skills/paper2poster && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "paper2poster" agent skill from https://github.com/QuZhan51496/paper2anything/tree/main/paper2poster into .github/skills/paper2poster/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "paper2poster", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add QuZhan51496/paper2anything --skill paper2poster -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install QuZhan51496/paper2anything paper2poster --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/QuZhan51496/paper2anything.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/paper2poster .opencode/skills/paper2poster && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "paper2poster" agent skill from https://github.com/QuZhan51496/paper2anything/tree/main/paper2poster into .opencode/skills/paper2poster/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "paper2poster", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
paper2posterConvert academic papers (PDF) into conference posters (HTML/PNG).
Paper2poster is an agent skill from QuZhan51496/paper2anything. Convert academic papers (PDF) into conference posters (HTML/PNG). You are the conductor: you decide what each section needs — an original paper figure or text — write the outline, hand-author the poster HTML, and iterate on the render using your own visual read and a blind-reader content quiz. Use when the user wants a poster from a paper PDF.
Its SKILL.md is about 9.2k tokens, which your agent loads only when the skill is triggered. The skill folder holds 23 other files, including scripts and reference files (for example `references/agent_design_rules_from_posters.md`, `references/color_palettes.md` and `references/layout_guide.md`).
It sits in Documents & Office, covering PDF. It works with Bash. The repository describes itself as: An agent skills pack that turns an academic paper PDF into slides, a poster, a webpage, a Xiaohongshu post, or a WeChat article (paper2slides/poster/html/xhs/wechat). The licence is Apache-2.0.
10 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 72bf82d. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
BashReadWriteGlobGrepAgentAskUserQuestionFrom allowed-tools in the SKILL.md frontmatter.
Ships 4 files in scripts/ (Python, from the files we listed), which the agent can run.
Shell commands in SKILL.md call:
condapipplaywrightFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
mineru.netFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
MINERU_API_TOKENFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Paper2poster loads about 9.2k tokens when it runs, and up to ~5.2M if it reads all its reference files. Until then it costs about 90 tokens; SKILL.md has 4,836 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
d):** all keys live in the package-root `.env` (copy from `.env.example`, gitignored). Export once per shell before runnallowed-tools: Bash, Read, Write, Glob, Grep, Agent, AskUserQuestionAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from QuZhan51496/paper2anything at commit 72bf82d, republished under its Apache-2.0 licence (© QuZhan51496). 4,836 words, ~9,208 tokens.
.claude/skills/paper2poster/SKILL.md (or your agent's skills folder). This skill also uses 20 other files; get the full folder from GitHub.Convert a paper PDF into an academic conference poster (HTML/PNG) by walking a small set of CLI scripts. You are the conductor: this file is the recipe, not an orchestrator. There is no run_pipeline.py — at each step you run one Bash command, read the intermediate artifact, and ask the user for confirmation at the decision points below.
PDF
→ parse_pdf.py (MinerU → content.md + figures/)
→ intake QA (you ask size/venue/authors/visual policy)
→ auto_outline.py (digest.json + assets[])
→ choose visuals (you read parsed/figures/ + captions: which sections use an original figure, which use text)
→ outline.json (you write from content.md; user confirms)
→ poster.html (you hand-author the poster: original figures where they help, text elsewhere)
→ render + score (Playwright PNG → deterministic geometry check + your own visual read + blind-reader content quiz)
→ iterate on poster.html (edit + re-render + re-score until it reads like a real poster)
→ poster.pngproblem_context, method_main, and result_evidence are a useful reading-order spine to think about — what's the paper about, how does it work, what's the evidence. For each, decide what carries it best: an original paper figure if one reads well at poster scale, or text (a worded explanation, a labelled box, a short list) if no figure fits. There is no figure quota — use as many or as few original figures as the content calls for, down to zero. A text-only section, or a text-only poster, is a legitimate outcome when the figures don't earn their place.
This skill only works if you execute it as a sequence of small Bash + Read + AskUserQuestion turns. Do not try to short-circuit it.
Bash tool, exactly as written below. Use absolute paths under ${SKILL_DIR} (the directory this skill lives in — e.g. <…>/paper2anything/paper2poster; set it once per shell with export SKILL_DIR=<…>/paper2anything/paper2poster).parsed/figures/ (and their captions in digest.json), and which sections you decided to carry with text instead,poster.png, plus your visual read and the blind-reader quiz result.AskUserQuestion:poster.html/poster.png to poster_candN.html/poster_candN.png) and record its scores. Pick the final from the best-scoring candidate, not just the latest edit. Never let a higher-scoring intermediate be silently overwritten by a worse one.Unified environment: every
pythoncommand in this skill runs in the paper2anything package's unified conda environment (created from the top-levelenvironment.yml), each prefixed withconda run -n paper2anything --no-capture-output. Thepip installbelow is only a fallback when the unified environment is missing a dependency;playwright install chromiumstill needs to be run once on its own.
conda run -n paper2anything --no-capture-output python ${SKILL_DIR}/scripts/check_env.pyIf anything is missing:
pip install Pillow requests playwright
playwright install chromiumCredentials (unified): all keys live in the package-root .env (copy from .env.example, gitignored). Export once per shell before running any command below: set -a; source <paper2anything package root>/.env; set +a. This skill needs only MINERU_API_TOKEN (PDF parsing). Everything else — figure choice, design, the visual read (Step 6), and the content check (Step 7) — is done by you and a blind subagent, with no external VLM / LLM API.
| Variable | Purpose | Default |
|---|---|---|
MINERU_API_TOKEN | MinerU PDF parsing | — |
All artifacts land next to the paper in <pdf dir>/.paper2anything/poster/<stem>/ (multiple papers in the same directory are split by <stem> and never overwrite each other). Each step below is an independent Bash call that shares no shell variables with the others, so every command block that needs the run directory recomputes RUN_DIR from $pdf_path right at its top (just like the always-available ${SKILL_DIR} — re-set it every time; never export it once in one step and expect it to survive into later steps). The scripts still live in ${SKILL_DIR}/scripts.
RUN_DIR="$(dirname "$pdf_path")/.paper2anything/poster/$(basename "${pdf_path%.*}")"
mkdir -p "$RUN_DIR"
conda run -n paper2anything --no-capture-output python ${SKILL_DIR}/scripts/parse_pdf.py "$pdf_path" \
--output-dir "${RUN_DIR}/parsed"MinerU (cloud) is the only parser — on failure the script exits non-zero. Fix the token / network and re-run.
Produces:
parsed/content.md — full text in Markdownparsed/metadata.json — title, authors, affiliations, abstractparsed/mineru_raw.json — typed blocks with bbox + captions (MinerU only)parsed/figures/, parsed/tables/Before designing anything, collect the few choices that actually change the poster. Now that the PDF is parsed you can show the user the parsed title/authors and ask the rest in one short grouped AskUserQuestion (don't turn this into a long form). The full checklist and defaults are in references/poster_intake_qa.md; the five that matter:
48x36 in landscape, 36x24, A0, 16:9 screen. Default: 48x36 in landscape (or 16:9 if the user says demo/slide/screen). This sets the render pixel size in Step 5.Anonymous Authors, blind review), or custom text. Default: parsed.parsed/, digest.json, outline.json, poster.html, poster.png, the score JSONs, any candidates) is written here, not just the final poster. Default: ${RUN_DIR}. Ask so the user can redirect the entire run to a folder they choose (e.g. their Desktop or a project dir); if they name one, use it as the --output-dir / --output base for every step below (Step 1 parse, Step 2 digest, Step 4 outline, Step 5 render, Steps 6–7 scores) so nothing lands in the default work dir. Report that path in Step 8.The output is an HTML/PNG poster (poster.html + poster.png). If the user just says "make a poster" with no answers, state the defaults you're using and proceed — don't block. Record the answers in outline.poster_intake (Step 4) so the design and any critique treat them as hard constraints. The size you settle on here is what Step 5 renders at (e.g. 20x15 in → 1920x1440 px, 48x36 in → 2304x1728 at 48 dpi or scale to taste).
RUN_DIR="$(dirname "$pdf_path")/.paper2anything/poster/$(basename "${pdf_path%.*}")"
conda run -n paper2anything --no-capture-output python ${SKILL_DIR}/scripts/auto_outline.py \
--parsed-dir "${RUN_DIR}/parsed" \
--output "${RUN_DIR}/digest.json"digest.json is ~17× smaller than mineru_raw.json: section-grouped, figures/tables attached to their nearest preceding section, References/Appendix dropped. It also exposes a typed assets[] array (PosterAgent-style) where each entry has type (claim / metric / figure / table), role (problem / method / result / takeaway / contribution / limitation), and priority (1–5). The role/priority tags are raw keyword heuristics — convenience hints, not a ranking to trust. When you write the outline (Step 3) you judge content importance yourself from content.md; don't defer to these scores.
(mineru_raw.json is always produced by the MinerU parse, so auto_outline.py always has its input.)
Deciding what carries each section is the same judgment you make when hand-authoring the HTML (does this section need a figure at all; if so, which one dominates, which is wide enough to span full width). So make it yourself, here, by looking at the figures — not with a keyword script.
List the extracted figures. digest.json has a figures[] / tables[] array (each with image_path, caption, section, page); the image files live in parsed/figures/. Read the captions, and Read the actual image files for the plausible candidates — a caption that says "pipeline" can sit over a figure that is useless at poster scale, and only your eyes catch that.
For each part of the reading-order spine, decide figure-or-text:
problem_context — frames the task / prior-work limitation / a vivid input example. "What is this paper about" should land here.method_main — how it works: the dominant pipeline / architecture / algorithm.result_evidence — the strongest evidence for the headline claim: a comparison plot, a qualitative grid, an ablation curve, or results numbers.For each, use an original figure if one is self-explanatory at a glance, large enough to stay sharp when enlarged, and not awkwardly tall/narrow — otherwise carry that part with text (a worded explanation, a labelled box, or a short list). Don't reuse the same figure twice, don't force a figure where none fits, and don't cap yourself at three — a section outside this spine can take a figure too if it earns one. The spine is a thinking aid, not a quota.
Confirm with the user via AskUserQuestion: lay out your per-section plan (for each: figure id + one-line "why this one", or "text — no good figure"), and ask accept this plan, or swap something? Proceed only when accepted.
You don't need to copy files anywhere — just record each chosen figure's path so you can reference it in outline.json (Step 4) and embed it in the HTML (Step 5).
You read the full parsed paper (parsed/content.md) and write outline.json directly with the Write tool, following the per-section visual plan you set in Step 3 (which sections embed an original figure, which are carried by text). You are the conductor here — selecting and condensing the paper's content into poster form is a judgment task, not a mechanical extraction. Do not just copy digest.json's auto-extracted sections (they are dense source prose); decide yourself what belongs on the poster and how to phrase it.
Goal, not quota. Make a poster that reads like a real conference poster — study the 8 real CVPR/ICLR examples in references/poster_examples/ for how much text, how many sections, and what density real posters use. Let the paper's own shape drive the structure: a method-heavy paper may need a long process section with a big diagram; a results paper may be one line plus a dominant table. There is no fixed section count or bullet count — use what the content and the real-poster aesthetic call for.
The one hard constraint is physical, not stylistic: every bullet and label must fit inside its panel and stay readable at 1–2 m — no overflow, no text shrunk to fit. The geometry check and your visual read in Step 5 measure this; if a panel overflows or is too sparse, that's your signal to cut, tighten, or add — not a reason to keep dense source text. Write each bullet as **Bold lead**: short detail, keep raw numbers inside worded sentences/lists rather than as standalone visual anchors, and for any section you decided gets an original figure (Step 3), reference it in that section's figure field. Sections you decided to carry with text simply have no figure field.
Then use AskUserQuestion to confirm structure with the user before continuing to the render step.
If the user wants an explicitly text-only poster, set outline.poster_intake.visual_policy = "text_only"; this also short-circuits the fallback figure gate. (Choosing text for some sections while using figures in others does not need this flag — it's just your normal per-section judgment from Step 3.)
(Outline JSON schema is below; color palettes too.)
You are the poster designer, not a template picker. The best posters in this pipeline are the ones you write yourself: you have seen the paper, you know each section's visual plan (figure or text) and the real pixel dimensions of any figures you chose, and you can study real conference posters. A fixed template cannot make the design judgments a good poster needs — whether a section even wants a figure, which figure dominates, whether a wide figure spans full width, where the claim anchors the eye, how dense each region is. So write the poster's HTML directly and iterate on it by scoring the render. There is no template to select and no repair-op vocabulary to obey.
Design fresh for each paper — do not reuse a house style. A real risk when you've made posters before is silently copying your last one's look (same title band, same color blocking, same grid). Resist it. Let this paper's content, field, and figure shapes drive the layout: a benchmark paper, an RL/method paper, and a systems paper should not look alike. Vary the palette (match the field or the paper's own accent color), the structure (3-column grid vs a left-spine flow vs a hero-on-top), and what dominates. If your new draft looks like your previous poster, that's a signal to rethink, not a shortcut to take.
Study the references. Read 2–3 of the real CVPR/ICLR posters in
references/poster_examples/ so your design
targets that visual language (strong title band, a dominant hero element, a
one-sentence claim, color-blocked sections, generous whitespace, big type).
Those examples are wide (~2:1); at a squarer size like the 48×36 default
(≈4:3) a full-width hero band or figure eats too much vertical budget and
overflows — keep the hero column-scoped (or pick a 2:1 size) so the vertical fits.
Check any figures' real shape. For each section you decided gets an
original figure, get its pixel size
(e.g. conda run -n paper2anything --no-capture-output python -c "from PIL import Image; print(Image.open('…').size)"). A
wide figure (≈2–3:1) must be placed full-column or full-width so it stays
sharp — never squeeze a wide figure into a narrow box; that is what makes
figures look like thumbnails.
Write poster.html yourself with the Write tool. While iterating,
reference figures by relative path (src="parsed/figures/x.jpg") —
screenshot.py and geom_check.py resolve them via file://, and the file
stays small and editable. Only at the end run
collect_figures once — conda run -n paper2anything --no-capture-output python ${SKILL_DIR}/scripts/collect_figures.py "${RUN_DIR}/poster.html" — to copy the
referenced figures into a sibling images/ directory and rewrite each src to
images/<name>, giving a portable poster (poster.html + images/). Design freely —
pick the grid, the type scale, the color blocking, where the claim sits, what
dominates. Size the poster to the intake (poster_intake.size, e.g. 20×15 in
→ 1920×1440 px at 96 dpi). Use the outline you wrote in Step 4 as the content
source. Sections you planned as text get a worded treatment (a paragraph, a
styled text box, or a short list); sections with a figure embed it.
Figure CSS — make the border hug the image, never frame empty space. A
recurring bug: setting width:100% + max-height:X + object-fit:contain
on an <img> paints the border on the full-width box while the image
shrinks to fit inside it, leaving large white margins between the border and
the actual picture (a small image floating in a big framed box). Avoid it —
pick one of two patterns so the border traces the image edge:
display:block; width:100%; height:auto; + border. The image spans the
column and the border hugs it; this also keeps the figure's own labels as
large as possible.display:inline-block; max-height:X; width:auto; height:auto; + border, in
a text-align:center wrapper. The border still traces the image; a small
side margin is fine — what you must avoid is object-fit:contain on a
fixed-width box. Don't combine width:100% with object-fit:contain.Never force a fixed height (or fixed width and height) to fill a
gap — it distorts the figure. Tempting fix when a panel has leftover
whitespace: stretch its image taller with height:640px. Don't. A figure
must always scale proportionally — set at most ONE axis (width:100%; height:auto, or max-height:X; width:auto) and let the other follow. A real
run set height:640px; width:auto on a 1.64:1 chart; a competing width
constraint then pinned the width too, squashing it to 1.02:1 (60% vertical
stretch) — a screenshot bug the eye catches instantly. Fill leftover
whitespace with content (a takeaway box, an extra bullet) or by rebalancing
columns — never by distorting a figure. Verify after every render:
renderedWidth/renderedHeight must equal naturalWidth/naturalHeight within
~0.02 for every <img>; flag any mismatch as a distortion bug.
Render, then score it — three checks, every render. Screenshot at the poster's exact pixel size with the standalone screenshot instrument:
RUN_DIR="$(dirname "$pdf_path")/.paper2anything/poster/$(basename "${pdf_path%.*}")"
conda run -n paper2anything --no-capture-output python ${SKILL_DIR}/scripts/screenshot.py \
"${RUN_DIR}/poster.html" \
"${RUN_DIR}/poster.png" \
--width 2304 --height 1728The example uses the default intake size (48×36 in → 2304×1728 at 48 dpi).
Set --width/--height to your intake size (e.g. 20×15 in → 1920×1440 at 96 dpi)
— they must match the size you recorded in poster_intake, not the example.
This tool only screenshots the HTML you wrote — it picks no template and makes
no design decision. Then run all three checks (none is optional — they are how
you know what to fix next):
(a) Deterministic geometry check — two-sided. Overflow, clipping, unequal columns, and underfill are all measurable — measure them, don't eyeball a downscaled PNG. Run the shipped checker for the three structure-agnostic gates (no overflow; fill ratio ≥ 0.95 computed from the true content frontier — real text/image extent, not a fixed-height container; per-image aspect within 0.02). It exits non-zero on failure:
conda run -n paper2anything --no-capture-output python ${SKILL_DIR}/scripts/geom_check.py \
"${RUN_DIR}/poster.html" 2304 1728(pass the same width/height you rendered at — the example is the 48×36 default) It does not know your panel structure — still measure the per-panel voids below yourself (Playwright box model) and read the PNG:
body.scrollHeight must be <= the canvas height (else
content spills off the bottom); each figure's <img> right/bottom must sit
inside its panel; columns should end at roughly the same y.scrollHeight does NOT catch this — when flexbox stretches panels to equal
height, a panel with too little content silently pools a large empty gap at
its bottom while the page still looks "full." Measure both the
bottom gap AND the gaps between a panel's children: for each panel,
panel.bottom − lastChild.bottom (bottom void) and
max(child[j].top − child[j−1].bottom) (inter-element void); flag either
if it exceeds ~60px. Measuring only the bottom gap has a blind spot:
justify-content:space-between (and similar) makes the bottom gap read ~0
while shoving the same whitespace between the figure and the text — a
real run looked "fixed" by the bottom test yet had a 347px hole between a
figure and its caption. Fill a void with real content, not by spacing
things apart. The right fixes: add genuine paper content (one or two
more bullets — papers usually have more findings than one panel shows),
enlarge a figure to fill the column (proportionally — never a forced
height), bump the body type scale (also helps legibility), or rebalance
which sections share a column. The wrong fix is space-between /
margin:auto / giant gaps, which just relocate the void. (A real run that
filled the voids with real content read markedly cleaner than the same
poster "fixed" with space-between, which only moved the whitespace around.)geom_check PASS does not prove blocks don't overlap: a flex:1 column
whose content exceeds its shrunk height escapes downward (overflow is
visible by default) and can paint over a following full-width band, yet the
box and the content both fit the canvas so overflow/fill/clip all pass. While
you measure the per-panel boxes, also confirm each column's content bottom
sits above the next full-width band's top — never trust the gate alone
for overlap.<img>, the
rendered width/height must match naturalWidth/naturalHeight within
~0.02. A figure stretched to fill space (e.g. a forced height:) is an
obvious eyesore you and any viewer catch instantly. (A real run
squashed a 1.64:1 chart to 1.02:1.) If flagged, restore proportional
scaling — see the figure-CSS rule in step 3, and fill the freed space with
content, not a stretched image.overflow:hidden/auto on a flex equal-height
column whose content is taller than the box silently cuts the bottom off, and
page-level scrollHeight won't catch it. If clipped_panels fires, don't
mask it with overflow:hidden — drop the hidden so the box can grow, or cut
the content until it genuinely fits.This check is two-sided on purpose: a single "did it overflow?" test has
only a ceiling and silently passes an under-filled, shrunk-down poster. Do not
stop at "fits." After every edit, re-measure and confirm 0.95 ≤ fill ≤ 1.0
with no overflow — this is a pass/fail gate you verify yourself, not a
suggestion, and how you reach it (what to resize, cut, reflow, or enlarge) is
your judgment. Your eyes on a shrunk full-poster PNG can mis-read
a full-bleed figure as "clipped" and miss both real bottom overflow and dead
whitespace — trust the pixel math over your eyes for anything geometric.
(b) Your own visual read — required, every render. Read the rendered
poster.png yourself and judge hierarchy, density, balance, and readability —
the subjective read the geometry check can't give you. This is the standing
"eyes" of the loop. Caveat: some harnesses/proxies strip image blocks, so
Read returns empty for a valid image — sanity-check at run start by
Read-ing one small known PNG. If it comes back empty you have no eyes here:
lean on the deterministic geometry check (a), keep the design conservative, and
tell the user the visual read was unavailable. Never fake a visual judgment on a
PNG you couldn't actually see.
(c) Blind-reader content check — at milestones (Step 7). A good-looking
poster can still fail to convey the paper. You write questions from the paper,
then spawn a blind subagent given only the rendered poster.png (not the
paper) to answer them — which roles it gets wrong are the roles not landing.
Run this at milestones (it spawns an agent), not on every micro-edit.
Iterate until it reads like a real poster AND scores well. Let the three
checks drive each edit: the geometry check catches overflow/clipping/imbalance
and underfill; your visual read catches weak hierarchy, cramped or sparse
panels, a bare number used instead of a sentence, poor balance; the blind-reader quiz catches
content that isn't getting through. When a check flags something, edit the HTML
and re-render — shrink/cut overflowing text, enlarge a figure that reads as a
thumbnail, fill or merge an empty panel with text, rewrite a number into a claim
sentence, or move/replace a figure. Re-run the three checks after each edit.
Before a big restyle or structural change, snapshot the current render as a
numbered candidate (poster_candN.html + poster_candN.png) with its scores,
so a regression doesn't destroy a version that read better — iteration isn't
always monotonic, and you pick the final from the best-scoring candidate, not the
latest edit. Repeat until the geometry check passes (no overflow and fill ratio
≥ 0.95), your visual read is clean, and the blind-reader quiz shows the key roles land. Don't stop the
moment content stops overflowing — that only clears the ceiling; verify the
fill gate too, or you ship a shrunk-down poster full of whitespace. This is open
visual iteration — your judgment guided by the scores, not a fixed op set.
Hard constraint (the only one): every piece of text and every figure label must be fully visible inside its panel and readable at 1–2 m. No overflow, no clipping, no text shrunk to illegibility. If content does not fit, cut or condense it (back in the outline) — never let it spill or shrink to dust.
The final poster is ${RUN_DIR}/poster.png (+ poster.html for editing).
This is the "eyes" of the iteration loop (Step 5, check b). After each render,
Read ${RUN_DIR}/poster.png yourself and judge it as a poster: visual hierarchy
(does the title / claim / hero dominate?), density (any panel cramped or too
sparse?), balance (columns even? whitespace intentional?), and readability at
1–2 m. Note the top 2–3 issues and let them drive the next edit — exactly the
subjective read the deterministic geometry check can't give you. No external model
needed — this is your own judgment on the rendered PNG.
A good-looking poster can still fail to convey the paper. This is the PaperQuiz idea (PosterAgent metric, arXiv:2505.21497): its whole value is that the answerer is blind — it sees only the poster, never the paper — so a wrong answer means the poster didn't carry that content. You authored the poster and have the paper in context, so you cannot answer blind yourself (you'd score inflated). Keep the independence by splitting the roles:
problem / method / result / takeaway (+ optional
contribution / limitation), with distractors pulled from sibling sections so
wrong options stay plausible. Keep the correct answers to yourself.Agent tool) whose
context contains only the rendered poster.png and the questions — not
the paper, digest, or outline. Ask it to answer each (single letter A/B/C/D + a
one-line "where on the poster I saw it", or ? if absent). Because it has only
the poster, its answers measure what the poster actually communicates.Run this at milestones (after the poster reads cleanly, and before user preview), not on every micro-edit — each round spawns an agent. Use it to: drive a repair round on a failing role; decide if it's good enough to ship (all key roles answered correctly); and re-rank candidates when you tried more than one layout.
You fix content fidelity by editing the outline / poster.html directly.
Once your own iteration (Steps 5–7) has the poster reading cleanly and scoring well, show it to the user:
Read ${RUN_DIR}/poster.png.
If image read is unavailable in your harness, rely on the deterministic geometry
check (Step 5a) and say so when you present.AskUserQuestion to offer:${RUN_DIR}/poster.png as final.poster.html
directly and re-render. Same scored iteration as Steps 5–7 — re-run the
three checks after the edit. No fixed repair vocabulary.poster.html.When approved, report the final poster.png from the run directory (outline.poster_intake.output_dir, e.g. ${RUN_DIR}/poster.png by default, or the folder the user chose in Step 2 — where every artifact for this run already lives).
By default the deliverable is buried in .paper2anything/poster/<stem>/ and hard to find. Once finalized, copy it to a
<stem>_poster/ directory alongside the PDF (the copy inside .paper2anything stays untouched) so the user can open it right next to the paper:
pdf_path="/path/to/paper.pdf"
RUN_DIR="$(dirname "$pdf_path")/.paper2anything/poster/$(basename "${pdf_path%.*}")" # if Step 2 changed output_dir, use your actual run directory
DEST="${pdf_path%.*}_poster" # same directory as the PDF, same name + _poster suffix
i=2; while [ -e "$DEST" ]; do DEST="${pdf_path%.*}_poster_v$i"; i=$((i+1)); done # on name collision, append _v2, _v3
mkdir -p "$DEST"
cp "$RUN_DIR/poster.png" "$RUN_DIR/poster.html" "$DEST/"
[ -d "$RUN_DIR/images" ] && cp -r "$RUN_DIR/images" "$DEST/" # figures are referenced as images/<name>, so bring them alongPut poster.png, poster.html, and images/ (poster.html references figures as images/<name>) into the <stem>_poster/ subdirectory; <stem>_poster/poster.png is the final poster.
{
"title": "Paper Title",
"authors": "Author1, Author2",
"affiliations": "University of X",
"contact": "email@example.com",
"poster_intake": {
"size": "20x15 in landscape",
"venue": "AAAI poster session",
"author_policy": "parsed",
"output_target": "html_png",
"output_dir": "<pdf dir>/.paper2anything/poster/<stem>",
"visual_policy": "original_figures_or_text"
},
"color_scheme": {
"primary": "#1B3A5C", "secondary": "#2E86AB",
"accent": "#A3D5FF", "background": "#FFFFFF", "text": "#1A1A2E"
},
"sections": [
{
"title": "Method", "column": "middle",
"content": [
"**Key Idea**: one-sentence summary",
"Step 1: …", "Step 2: …"
],
"figure": "figures/fig1.png"
}
]
}Suggested starting palettes (pick whatever the design calls for — color_scheme is free): CS/AI blue (#1B3A5C/#2E86AB), Bio/Med green (#2D6A4F/#52B788), Physics/Math purple (#5A189A/#9D4EDD), Engineering orange (#E76F51/#F4A261). More in references/color_palettes.md.
MINERU_API_TOKEN from https://mineru.net/apiManage/token.parse_pdf.py already does this with a trust_env=False session (setting proxies={...} alone doesn't work because requests still honors ALL_PROXY).pip install playwright && playwright install chromium. The geometry check (Step 5, check a) and screenshot.py both need it.content.md + mineru_raw.json + figures/ into parsed/ by hand.For layout principles see references/layout_guide.md and references/poster_design_guide.md. For agent-extracted design rules see references/agent_design_rules_from_posters.md.
© QuZhan51496, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 20 other files (scripts, references) in paper2poster of QuZhan51496/paper2anything.
Open the folder on GitHubat commit 72bf82d
Paper2poster next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Paper2poster this skillQuZhan51496/paper2anything | 450 | — | ~9.2k | Automated safety check: Notes | Apache-2.0 | |
| Markdown Exporterbowenliang123/markdown-exporter | 272 | 1 repos | ~5.3k | Automated safety check: Pass | Apache-2.0 | |
| Document Generationbionic-gpt/bionic-gpt | 2.4k | — | ~1.1k | Automated safety check: Pass | Apache-2.0 | |
| Export PDFbluzir/claude-code-design | 106 | — | ~811 | Automated safety check: Pass | None | |
| Split PDFscunning1975/MixtapeTools | 474 | 2 repos | ~2.9k | Automated safety check: Pass | None | |
| Paper Interpretationdigoal/blog | 8.6k | — | ~1.5k | Automated safety check: Pass | GPL-2.0 |
bowenliang123/markdown-exporter
Convert Markdown text to DOCX, PPTX, XLSX, PDF, PNG, SVG, HTML, IPYNB, MD, CSV, JSON, JSONL, XML files, and extract code blocks in Markdown to Python, Bash,JS and etc files.
bionic-gpt/bionic-gpt
Create polished printable documents and PDFs, including forms, checklists, reports, briefs, comparisons, worksheets, task lists, and other operational documents.
bluzir/claude-code-design
Export an HTML artifact to PDF via headless Chromium (puppeteer Page.pdf).
scunning1975/MixtapeTools
Download, split, and deeply read academic PDFs. An agent skill from scunning1975/MixtapeTools.
digoal/blog
从论文 PDF 文件或论文 PDF URL 生成通俗易懂、图文并茂、带批判性评估的中文 Markdown 解读,并保存到当前项目的 markdown 目录。Use when the user asks to interpret,精读,解读,summarize,explain,analyze, or write an article from an academic paper PDF…
YSQ-boop/paper-lens
Read and critically analyze one academic paper from an arXiv URL/ID or a local PDF, producing a source-grounded Markdown report that can grow from a quick read into a reviewer-level deep review.
QuZhan51496/paper2anything
Convert an academic paper PDF into a publish-ready, self-contained single-page project homepage (a self-contained index.html) — the kind of paper landing page researchers host on GitHub Pages.
QuZhan51496/paper2anything
Turn an academic paper PDF into a presentation deck (.pptx) end-to-end.
QuZhan51496/paper2anything
把学术论文 PDF 转成微信公众号深度解读推文(长文 + 配图 + 封面)。你主导设计的协调式:机械活(MinerU 解析 PDF、生成封面、md2wechat 发布草稿箱)交给 scripts/ 下的小工具,论文理解、文章结构、长文撰写由你亲自完成并在关键点与用户确认。当用户说“论文转公众号”、“paper2wechat”、“把论文写成公众号文章”、“论文转微信推文”、“PDF…
QuZhan51496/paper2anything
把学术论文 PDF 转成小红书多图帖(标题 + 正文 + 标签 + 封面 + 论文主图/主实验结果配图)。你主导设计的协调式:机械活(MinerU 解析 PDF、生成封面与配图、半自动发布)交给 scripts/ 下的小工具,论文理解、选题角度、文案撰写由你亲自完成并在关键点与用户确认。当用户说“论文转小红书”、“paper2xhs”、“把这篇论文发小红书”、“论文转社交媒体”、“PDF…
Works with
Categories
Convert academic papers (PDF) into conference posters (HTML/PNG). Paper2poster is an agent skill from QuZhan51496/paper2anything. Convert academic papers (PDF) into conference posters (HTML/PNG).
Paper2poster fits situations like: the user wants a poster from a paper PDF; tasks that involve PDF.
Run `npx skills add QuZhan51496/paper2anything --skill paper2poster -a claude-code`. Or copy the skill folder (paper2poster in QuZhan51496/paper2anything) into .claude/skills/paper2poster in your project. Claude Code loads it when a task matches its description.
Run `npx skills add QuZhan51496/paper2anything --skill paper2poster -a codex`. Or copy the skill folder (paper2poster in QuZhan51496/paper2anything) into .agents/skills/paper2poster in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add QuZhan51496/paper2anything --skill paper2poster -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/paper2poster, .gemini/skills/paper2poster, .github/skills/paper2poster and .opencode/skills/paper2poster in your project.
Going by SKILL.md and its folder, Paper2poster needs Python for the scripts in its folder, the command-line tools its instructions call (conda, pip and playwright) and credentials named MINERU_API_TOKEN. Our summary lists: Python 3; A credential in MINERU_API_TOKEN. Its frontmatter pre-approves these tools: Bash, Read, Write, Glob, Grep, Agent, AskUserQuestion.
SKILL.md names 1 domain. In commands or code: mineru.net; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (mentions a .env file; pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Paper2poster is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 9.2k tokens (SKILL.md is roughly 37k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 5.2M tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Paper2poster: Markdown Exporter (bowenliang123/markdown-exporter, 272 stars), Document Generation (bionic-gpt/bionic-gpt, 2.4k stars), Export PDF (bluzir/claude-code-design, 106 stars) and Split PDF (scunning1975/MixtapeTools, 474 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
QuZhan51496 (a GitHub user) maintains it in QuZhan51496/paper2anything, which has 450 GitHub stars. The repository holds 5 skills in this directory. The repository was last updated on July 16, 2026.
Source: QuZhan51496/paper2anything on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.