Générateur de Poster de Conférence (HTML)
Générez un poster HTML professionnel. Notes utilisateur : $ARGUMENTS
Le poster est un éditeur interactif basé sur React — un seul fichier HTML autonome dans le répertoire poster/. Aucune étape de build nécessaire (React/Babel chargés via CDN). L'utilisateur peut ajuster visuellement la mise en page dans son navigateur, puis exporter la configuration vers Claude pour d'autres modifications.
Structure du dossier du projet
<projet>/
├── overleaf/ # Source de l'article depuis Overleaf
│ ├── paper.tex
│ ├── figures/
│ └── ...
├── references/ # Posters de référence pour l'adaptation stylistique
│ └── (tout format : pdf, png, jpg, html, pptx, ...)
├── poster/ # GÉNÉRÉ : site web autonome du poster
│ ├── index.html # Le poster (application React)
│ ├── poster-config.json # Configuration de la mise en page (colonnes, ordre des cartes, hauteurs, échelle de police)
│ ├── logos/ # Logos des institutions
│ ├── teaser.png # Figures copiées/converties
│ ├── qr.png # Code QR de la page du projet
│ ├── qr-posterskill.png # Code QR de Posterskill
│ └── ...
└── .claude/skills/make-poster/
overleaf/contient la source de l'article. Lisez le fichier.texprincipal et tous les fichiers qu'il inclut avec\input{}.references/contient des exemples de posters montrant le style visuel préféré de l'utilisateur. Lisez/visualisez TOUS les fichiers de ce dossier pour reproduire leur langage de conception.poster/est la sortie générée — un site web autonome. Toutes les figures et ressources se trouvent aux côtés deindex.htmlpour que les chemins relatifs fonctionnent simplement.
Entrées
- Source de l'article - Située dans
overleaf/. Demandez à l'utilisateur quel fichier.texest le principal à lire (par exemple,paper.tex,main.tex). Lisez-le ainsi que tous les fichiers qu'il inclut avec\input{}. - Site web du projet - Demandez l'URL à l'utilisateur si elle n'est pas déjà connue. Récupérez-la avec WebFetch pour extraire les informations sur les auteurs, les images hébergées et les liens.
- Posters de référence - Découverts automatiquement dans
references/. Visualisez tous les fichiers et reproduisez leur style. - Site web de l'auteur (optionnel) - Récupérez-le avec WebFetch et extrayez les signaux de conception (palette de couleurs, typographie, logos). Téléchargez les logos institutionnels depuis le site de l'auteur avec Playwright (curl peut échouer à cause des redirections) :
page.request.get(url)pour télécharger les octets bruts. - Exigences de formatage - Demandez les dimensions du poster, l'orientation, le nombre de colonnes.
- Dépôt Git (optionnel) - Demandez à l'utilisateur s'il a un dépôt GitHub pour pousser le poster.
Si l'utilisateur ne spécifie pas le formatage, demandez-lui avant de continuer. Ne supposez pas de valeurs par défaut pour les dimensions, l'orientation ou le nombre de colonnes.
Processus
Étape 0 : Analyser les références de style
Cherchez dans references/ tout fichier PDF, PNG ou image. Convertissez les PDF en PNG (sips -s format png sur macOS). Visualisez chacun et notez le style visuel — mise en page, couleurs, typographie, styles de cartes, placement des figures. Adaptez le style de référence — ne choisissez pas un thème sombre si la référence est claire, etc.
Étape 1 : Extraire le contenu de la source de l'article
Demandez à l'utilisateur quel fichier .tex lire. Extrayez : titre, auteurs, affiliations, résumé (2-3 phrases), méthode clé, résultats (tableaux + figures), équations clés (1-2 maximum), conclusion.
Étape 2 : Récupérer le site web du projet
Utilisez WebFetch pour obtenir les noms des auteurs, affiliations, URL des figures, URL du projet pour le QR, liens vers le code/arxiv/vidéo.
Étape 3 : Rassembler les ressources dans poster/
Figures : Copiez depuis overleaf/figures/, en convertissant les PDF en PNG à haute résolution :
sips -s format png input.pdf --out poster/output.png -Z 3000
Images du site web : Téléchargez des images de meilleure qualité depuis le site web du projet avec Playwright (pas curl — de nombreux sites redirigent) :
resp = page.request.get(url)
with open('poster/filename.png', 'wb') as f:
f.write(resp.body())
Logos : Téléchargez les logos institutionnels depuis le site web personnel de l'auteur avec Playwright. Sauvegardez dans poster/logos/. Le modèle les inverse automatiquement en blanc pour l'en-tête.
Codes QR : Générez et sauvegardez :
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"
Étape 4 : Mesurer les proportions des images
Ceci est crucial pour éliminer les espaces blancs. Mesurez chaque image :
sips -g pixelWidth -g pixelHeight poster/*.png poster/*.jpg
Ensuite, assignez les images aux colonnes en fonction du rapport hauteur/largeur :
- Images larges (>2:1 ratio, par exemple teaser, architecture) : placez dans la colonne la plus large
- Images carrées (~1:1 ratio) : placez dans les colonnes étroites
- Images portrait (<1:1 ratio) : placez dans la colonne la plus étroite
Cela évite le problème numéro 1 des espaces blancs : les images larges dans des cellules étroites (ou vice versa) laissant de grands vides.
Étape 5 : Générer le HTML du poster
Utilisez le modèle situé à ${{CLAUDE_SKILL_DIR}}/template.html comme point de départ. Le modèle est une application React avec :
Architecture :
CARD_REGISTRY— définit le contenu de chaque carte (titre, couleur, corps JSX)DEFAULT_LAYOUT— définit la structure des colonnes et l'ordre des cartesDEFAULT_LOGOS— logos institutionnels pour l'en-tête- L'état React gère la mise en page, avec persistance dans localStorage
window.posterAPIexpose des fonctions pour le contrôle programmatique
Éléments clés à personnaliser :
- Mettez à jour
CARD_REGISTRYavec le contenu de l'article (chaque section est une carte) - Mettez à jour
DEFAULT_LAYOUTavec les assignations de colonnes optimisées par rapport hauteur/largeur - Mettez à jour
DEFAULT_LOGOSavec les logos institutionnels de l'utilisateur - Mettez à jour
DEFAULT_FONT_SCALE(commencez à 1.3, l'utilisateur peut ajuster avec les boutons A-/A+) - Mettez à jour l'en-tête (titre, auteurs, affiliations, badge de conférence, codes QR)
- Mettez à jour
@page { size: LARGEURmm HAUTEURmm; }etbody { width: LARGEURmm; height: HAUTEURmm; }pour les dimensions du poster - Mettez à jour la fonction
posterAPIfit() avec les mêmes dimensions
Motifs de contenu des cartes :
- Carte de figure :
<div className="fig"><div className="fig-wrap"><img src="file.png" alt="..." /></div><div className="cap"><b>Titre de la légende.</b> Description.</div></div> - Carte de texte :
<div className="hl"><p>Texte en surbrillance</p></div><ul><li>Point 1</li></ul> - Carte de tableau :
<table><thead>...</thead><tbody>...</tbody></table>avecclassName="best"sur les cellules gagnantes - Carte d'équation :
<div className="eq">{'$Équation LaTeX$'}</div>(échappez les backslashes dans JSX)
Règles CSS critiques pour zéro espace blanc :
- Les images DOIVENT utiliser
width:100%; height:100%; object-fit:contain(PAS max-width/max-height — celles-ci empêchent l'agrandissement) - Chaque colonne doit toujours avoir une carte avec
grow: true(flex:1) qui remplit l'espace restant - La fonction
isCardGrow()garantit cela automatiquement — si aucune carte n'a grow, la dernière carte l'obtient
Mise à l'échelle de la zone d'affichage :
- Utilisez
translate() + scale()sur body pour centrer et adapter le poster à n'importe quelle zone d'affichage du navigateur transform-origin: top leftest critique@media printdoit définirtransform: none !importantpour une résolution d'impression correctegetBoundingClientRect()retourne des valeurs MISES À L'ÉCHELLE — divisez toujours parcurrentScaleRef.currentdans les gestionnaires de redimensionnement
Étape 6 : Optimiser automatiquement la mise en page avec Playwright
Après la génération, utilisez Playwright pour mesurer les espaces blancs et trouver les largeurs de colonnes optimales :
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)
# Mesurer les espaces blancs
waste = page.evaluate('window.posterAPI.getWaste()')
print(f"Espace total perdu : {waste['total']}px")
for d in waste['details']:
print(f" {d['card']}: H={d['wasteH']} W={d['wasteW']} ({d['pct']}%)")
# Essayer différentes largeurs de colonnes pour minimiser le gaspillage
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
# Appliquer le meilleur et faire une capture d'écran
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')
# Essayer aussi d'échanger des cartes entre les colonnes
page.evaluate('window.posterAPI.swapCards("cardA", "cardB")')
# ... mesurer le gaspillage à nouveau ...
browser.close()
Ensuite, lisez /tmp/poster_screenshot.png pour inspecter visuellement. Itérez plusieurs fois — prenez des captures d'écran, corrigez les problèmes, re-capturez jusqu'à ce que le poster ait un espace blanc minimal.
Après avoir trouvé les valeurs optimales, intégrez-les dans DEFAULT_LAYOUT, DEFAULT_CARD_HEIGHTS, etc. dans le HTML.
Étape 7 : Générer le PDF et vérifier
page.pdf(
path='poster/poster.pdf',
width='841mm', height='594mm', # correspondre aux dimensions du poster
margin={'top':'0','right':'0','bottom':'0','left':'0'},
print_background=True
)
Convertissez le PDF en PNG et lisez-le pour vérifier qu'il s'affiche en pleine résolution :
sips -s format png poster/poster.pdf --out /tmp/poster_pdf_check.png -Z 3000
Étape 8 : Ouvrir et itérer avec l'utilisateur
Ouvrez le poster dans le navigateur :
open poster/index.html
Expliquez les contrôles d'édition à l'utilisateur :
- Aperçu — basculez l'interface d'édition pour voir exactement comment il s'imprimera
- A-/A+ — ajustez la taille de la police globalement
- Faites glisser les séparateurs de colonnes (barres bleues verticales) — redimensionnez les colonnes à gauche/droite
- Faites glisser les séparateurs de lignes (barres bleues horizontales) — redimensionnez les cartes vers le haut/bas dans les colonnes
- Cliquez pour échanger — cliquez sur la poignée en losange d'une carte (devient orange), puis cliquez sur une autre pour les échanger
- Déplacer/insérer — cliquez sur la poignée d'une carte, puis cliquez sur une zone de dépôt en pointillés orange pour l'y déplacer
- Sauvegarder — télécharge
poster-config.json - Copier la configuration — copie le JSON de mise en page dans le presse-papiers
- Réinitialiser — restaurer les valeurs par défaut
Proposez proactivement des améliorations : Après avoir montré la première ébauche, suggérez des modifications spécifiques :
- "La carte d'architecture du modèle a des espaces blancs — essayez de faire glisser le séparateur de ligne au-dessus vers le bas pour lui donner moins d'espace"
- "La figure de complétion pourrait mieux paraître dans la colonne 2 car elle est plus large — essayez de cliquer sur son losange, puis de cliquer sur une zone de dépôt dans la colonne 2"
- "Vous pourriez augmenter la taille de la police avec A+ quelques fois"
Encouragez la boucle de rétroaction : Dites à l'utilisateur :
Essayez de réorganiser le poster dans votre navigateur ! Lorsque vous êtes satisfait de la mise en page, cliquez sur Copier la configuration dans la barre d'outils en haut à droite et collez-la ici — j'intégrerai ces modifications dans les valeurs par défaut pour qu'elles persistent.
- Sauvegarder — télécharge
poster-config.json - Copier la configuration — copie le JSON de mise en page dans le presse-papiers pour le coller à Claude
- Réinitialiser — restaurer les valeurs par défaut
Lorsque l'utilisateur colle un JSON de configuration, mettez à jour DEFAULT_LAYOUT, DEFAULT_CARD_HEIGHTS, DEFAULT_FONT_SCALE, et DEFAULT_LOGOS dans le HTML en conséquence. Écrivez-le également dans poster-config.json.
Étape 9 : Pousser vers GitHub (optionnel)
Si l'utilisateur fournit une URL de dépôt GitHub :
cd poster
git init
git remote add origin <URL_DÉPÔT>
git add .
git commit -m "Poster : <titre de l'article>"
git push -u origin main
Directives importantes
- Pas d'espace blanc. C'est la priorité numéro 1. Utilisez l'assignation de colonnes basée sur le rapport hauteur/largeur,
width:100%; height:100%; object-fit:containsur les images, les cartes à croissance automatique, et l'optimiseur Playwright. Itérez jusqu'à ce que le gaspillage soit minimal. - Gardez le texte minimal. Les posters sont visuels — des puces, pas des paragraphes. Compréhension en 2 minutes.
- Adaptez le style de référence. Si le poster de référence est clair/propre, n'utilisez pas un thème sombre. Reproduisez l'esthétique globale.
- Mise à l'échelle de la police. Toutes les tailles de texte utilisent
calc(Xpt * var(--font-scale))pour que les boutons A-/A+ fonctionnent. Commencez avec--font-scale: 1.3et laissez l'utilisateur ajuster. - CSS optimisé pour l'impression.
@media printmasque toute l'interface d'édition et définittransform: none !important.@pagedéfinit les dimensions exactes. - QR Posterskill. Incluez toujours un code QR pointant vers
https://github.com/ethanweber/posterskilldans l'en-tête avec le label "Poster réalisé avec ma compétence Claude". - Pas de pied de page de remerciements. Gardez le poster propre — pas de pied de page par défaut.
- Logos dans l'en-tête. Téléchargez les logos institutionnels depuis le site web de l'auteur, sauvegardez-les dans
poster/logos/, et listez-les dansDEFAULT_LOGOS. Ils sont automatiquement inversés en blanc via le filtre CSS. - Autonome. Pas d'étape de build, pas de npm, pas de serveur. Un seul fichier HTML avec des dépendances CDN. Fonctionne lorsqu'il est ouvert directement en tant que
file://. - Équations. Utilisez KaTeX (chargé via CDN). Échappez les backslashes dans les chaînes JSX :
{'$\mathcal{E}$'}.
Gestion des figures
- Copiez toujours les figures nécessaires dans
poster/— ne référencez pas les cheminsoverleaf/dans le HTML. - Convertissez les PDF en PNG à haute résolution :
sips -s format png input.pdf --out poster/output.png -Z 3000 - Téléchargez les images du site web via
page.request.get()de Playwright (pas curl — les sites web redirigent souvent). - Mesurez les rapports hauteur/largeur avec
sips -g pixelWidth -g pixelHeightet assignez-les aux colonnes en conséquence.
Flux de travail utilisateur pour les mises à jour de configuration
L'utilisateur peut ajuster le poster dans son navigateur et partager les modifications :
- L'utilisateur clique sur "Copier la configuration" dans la barre d'outils
- L'utilisateur colle le JSON dans le chat
- Claude met à jour
DEFAULT_LAYOUT,DEFAULT_CARD_HEIGHTS,DEFAULT_FONT_SCALE,DEFAULT_LOGOSdansindex.htmlen conséquence - Claude écrit également la configuration dans
poster-config.json - L'utilisateur actualise et clique sur "Réinitialiser" pour charger les nouvelles valeurs par défaut
API programmatique (window.posterAPI)
Disponible dans la console du navigateur ou via Playwright :
swapCards(id1, id2)— échange deux cartes (fonctionne entre les colonnes)moveCard(cardId, targetColId, position)— déplace une carte vers une position spécifiquesetColumnWidth(colId, widthMm)— définit la largeur d'une colonne (null pour flex)- ...
[truncated for translation]
