app-ui-deck — presentación .pptx a partir de capturas de la UI
Convierte una app web que corre en local en un PowerPoint pulcro: capturas nítidas
de cada vista (Chrome headless) + un deck 16:9 con portada, una diapositiva por
pantalla (título y descripción a la izquierda, captura enmarcada a la derecha) y
cierre. Todo con el acento de marca del usuario (rojo smartclip #E40523) e Inter.
El flujo es data-driven: escribes dos manifests JSON y ejecutas dos scripts que
viven en scripts/ de esta skill. No hace falta editar código por presentación.
Requisitos y gotchas (léelos, me costaron iteraciones)
- Dev server corriendo: la UI en su puerto (Vite suele ser
5173) con el backend detrás (proxy same-origin a3001). Verifícalo concurl -s -o /dev/null -w "%{http_code}" http://localhost:5173/. Si no corre, arráncalo (npm run dev) o usa la skillrun. Para apps tras smartclip-auth con datos reales, la skillsmartclip-auth-devmonta el proxy con la cookie. - Chrome del sistema, no descargar navegador: los scripts usan
playwright-coreconchannel: 'chrome'. Instala soloplaywright-coreenscripts/(cd <skill>/scripts && npm i playwright-core) — reutiliza el Chrome del Mac. - python-pptx en venv (PEP 668): macOS bloquea
pip installen el Python del sistema. Crea un venv en el scratchpad:python3 -m venv $SCRATCH/pptvenv && $SCRATCH/pptvenv/bin/pip install python-pptx pillow. Usa ese intérprete. - Feeds lentos / carga en frío: vistas con datos que tardan (p. ej. el feed GAM)
salen con “—” si capturas en frío. Caliéntalas antes con un
curla su API (curl -s "http://localhost:3001/api/sites?source=gam" >/dev/null) y sube elsettleMsde ese shot. - Nitidez: viewport
1440x900conscale: 2(deviceScaleFactor) → imágenes 2x. - Diálogos/menús: para capturar un modal, usa
clicksen el shot (rol accesible- nombre) para abrirlo antes del screenshot, y
escAfter: truepara cerrarlo.
- nombre) para abrirlo antes del screenshot, y
- No hay LibreOffice para renderizar el .pptx a imagen y revisarlo visualmente: verifica cada captura con Read antes de montar (esa es la revisión visual), y luego valida el .pptx de forma estructural (nº de diapositivas + media embebida).
Procedimiento
-
Scratchpad y dependencias
SCRATCH=<tu-scratchpad>; SKILL=~/.claude/skills/app-ui-deck mkdir -p $SCRATCH/shots (cd $SKILL/scripts && [ -d node_modules/playwright-core ] || npm i --silent playwright-core) [ -x $SCRATCH/pptvenv/bin/python ] || (python3 -m venv $SCRATCH/pptvenv && \ $SCRATCH/pptvenv/bin/pip install --quiet python-pptx pillow) -
Descubre las vistas: mira las rutas (p. ej.
App.tsx<Route path>) y el nav para saber qué pantallas existen y cuáles merecen diapositiva. Calienta las lentas concurla su API. -
Manifest de capturas
$SCRATCH/shots.json(ver cabecera decapture.mjs): una entrada por pantalla conname,pathysettleMs;clickspara diálogos. Ejecuta:OUT=$SCRATCH/shots MANIFEST=$SCRATCH/shots.json node $SKILL/scripts/capture.mjs -
REVISA cada PNG con Read. Es la única revisión visual. Si algo salió en frío, vacío o con un modal mal abierto, ajusta el manifest y recaptura solo ese shot.
-
Manifest del deck
$SCRATCH/deck.json(ver cabecera debuild_deck.py):brand,accent,title, unslides[]con{img, title, desc}por captura yclosing. Las descripciones: qué es la vista y para qué sirve, en prosa breve — nada técnico de implementación. Genera:SHOTS=$SCRATCH/shots DECK=$SCRATCH/deck.json OUT=$SCRATCH/presentacion.pptx \ $SCRATCH/pptvenv/bin/python $SKILL/scripts/build_deck.py -
Verifica y entrega: comprueba nº de diapositivas y que las imágenes quedaron embebidas (reabrir con python-pptx y contar
media), y copia el .pptx a~/Downloads/. Avisa que usa Inter (PowerPoint la sustituye si no está) y que no pudiste renderizarlo (revisión fue por capturas + estructura).
Diseño del deck (ya implementado en build_deck.py)
- 16:9 (13.333×7.5“). Fondo blanco, acento de marca en barra lateral (portada/cierre) y en el número + filete de cada diapositiva. Tipografía Inter.
- Portada: marca (
prefixtinta +suffixacento) + headline + subtítulo + footer. - Contenido: número + título + descripción a la izquierda (columna ~3.7“), captura enmarcada (borde fino, esquinas redondeadas) a la derecha, preservando aspecto. Marca pequeña arriba-derecha y footer abajo.
- Cierre: frase de remate + marca.
Adaptar a otra app
Cambia en deck.json: brand (prefix/suffix), accent (hex), footer, y las
rutas/settleMs en shots.json. Los scripts no se tocan. Para apps con auth real,
combina con smartclip-auth-dev; para arrancar la app, con run.