Héroe de Cuerda de Tender (Washing Line Hero)
La primera pantalla de un sitio web: la barra de la marca y la navegación en la parte superior, un título grande con una frase de color, una línea de introducción, uno o dos botones y una nota pequeña, y a su lado una cuerda de tender extendida a través del cielo. En la cuerda cuelga una tela de algodón sujetada por pinzas de madera, impresa con el póster de la propia marca: un nombre, una línea pequeña, dos palabras grandes, una columna de especificaciones y un pequeño gráfico de barras. Una brisa la levanta de vez en cuando y las nubes se deslizan detrás.
Está hecha para ser tocada. Mueve el puntero sobre la tela y la yema del dedo la hunde. Presiona y arrastra, y la tela sigue tu mano: levanta una esquina, dóblala sobre la cuerda, estírala hacia ti. Suéltala y cae, se balancea y se asienta. En los teléfonos, un dedo hace lo mismo y la página no se desplaza mientras se sostiene la tela. La tela está simulada (una cuadrícula de partículas unidas por restricciones de estiramiento, corte y curvatura, con pasos fijos a 120 Hz), por lo que se comporta como una tela real sin importar dónde se agarre, en lugar de reproducir una animación predefinida.
Describe el héroe y la impresión en hero.json. La construcción verifica todo y escribe out/index.html, una página completa en un solo archivo, y out/embed.html, la misma sección para pegar en un sitio que ya tengas. Como la simulación se ejecuta con un paso fijo desde un inicio en reposo, record.mjs puede avanzarla fotograma a fotograma: en el video, un puntero dibujado tira de una esquina, la suelta y luego pasa la yema del dedo por la tela, mostrando lo que los visitantes pueden hacer, igual en cualquier máquina.
Lo que no es: la tela no se rasga, no se enreda consigo misma ni se vuela de la cuerda (no tiene autocolisión, por lo que si la doblas con fuerza a través de sí misma, pasa a través y cae hacia atrás), y la impresión la dibuja la página con tus palabras, no es una foto que subas.
Lo que necesitas
- Node.js 18 o más reciente. Nada que instalar.
- Chrome, Chromium o Edge, para las comprobaciones y la grabación (los scripts lo encuentran; establece
CHROME_PATHsi no lo hacen). - ffmpeg, para el video (
brew install ffmpeg,winget install ffmpeg,apt install ffmpeg; o estableceFFMPEG_PATH). - Acceso a Internet cuando se abre la página: three.js y las fuentes se cargan desde jsDelivr en versiones fijas con hashes de integridad. Sin él, los visitantes ven la imagen estática (la misma línea y tela, dibujadas planas) y las fuentes del sistema; la página sigue funcionando.
La carpeta de esta habilidad es <skill> a continuación: la carpeta en la que se encuentra este SKILL.md.
Pasos
1. Recopila la marca y las palabras
Pregúntale a la persona, o encuentra en su sitio actual:
- Nombre y el logotipo como un archivo SVG (cuadrado o casi; uno simple, sin scripts). Sin uno, hasta tres letras forman un monograma.
- Colores: el fondo, que también es el cielo en el horizonte (el color del texto debe alcanzar 7:1 sobre él), y un acento. Un azul claro da un cielo del mediodía con texto oscuro; un azul marino profundo o ciruela da un cielo crepuscular con texto claro y un sol bajo y cálido.
- Fuentes: una cara de exhibición para el título y las palabras grandes en la tela, y otra para el resto. Estas se cargan fijas y verificadas: Space Grotesk, Inter, Instrument Sans, Instrument Serif, DM Sans, Manrope, Fraunces, Sora, Outfit, Bricolage Grotesque, IBM Plex Sans, JetBrains Mono, Plus Jakarta Sans, Newsreader, Playfair Display. Cualquier otra familia de Google Fonts también funciona, sin fijar.
- Las palabras en la página: un título de unas pocas palabras con la frase para colorear, una o dos oraciones sobre qué es y para quién, el botón principal y un segundo opcional con a dónde llevan, hasta cinco enlaces de navegación y el botón en la barra. Una pequeña insignia sobre el título y una nota debajo de los botones son opcionales.
- Las palabras en la tela: el nombre a imprimir en la parte superior (a menudo el producto y la versión), una línea pequeña debajo, dos a cuatro palabras grandes (dos líneas se leen mejor), hasta seis pares cortos de especificaciones (etiqueta y valor), un pie de foto para el gráfico, y una dirección web para la esquina.
Cada nombre, número, afirmación y fecha debe provenir de la persona. No inventes especificaciones o cifras; mejor omite una especificación. Las barras del gráfico son decoración dibujada a partir de la semilla, no datos: ponle un pie de foto que no afirme números, o desactívalo.
2. Escribe hero.json
Copia la carpeta de ejemplo más cercana y reemplaza todo: examples/paperwind/ (una app de notas, cielo claro del mediodía, cuatro pinzas) o examples/halden/ (una marca de lino, cielo crepuscular, tres pinzas, una tela más cuadrada).
| Campo | Qué es | Límite |
|---|---|---|
brand.name, brand.href | El nombre en la parte superior izquierda, y a dónde enlaza (por defecto /) | 28 |
brand.logo | Un archivo .svg junto a hero.json, incluido en la página; o hasta 3 letras para un monograma | – |
nav[] | Hasta 5 { "label", "href" } en una píldora (oculto en teléfonos) | 18 |
action | El botón en la parte superior derecha, { "label", "href" }; false para ninguno | 22 |
hero.badge | Una línea pequeña en mayúsculas sobre el título | 40 |
hero.title | El título. *frase* lo pone en el color de acento; \n salta la línea (hasta 3 líneas) | 72 |
hero.lede | Qué es y para quién. Markdown en línea: código, enlaces, negrita, cursiva | 220 |
hero.actions[] | 1 o 2 { "label", "href" }: el primero es el botón principal sólido con una flecha, el segundo uno delineado | 26 |
hero.note | Una línea pequeña debajo de los botones | 90 |
hero.align | left (línea y tela a la derecha, por defecto) o right (reflejado). center pone la tela detrás del texto; no recomendado | – |
theme.background, theme.ink, theme.accent | Colores hex. ink debe alcanzar 7:1 sobre background | – |
theme.mode | light o dark; se deduce del fondo cuando se omite | – |
theme.fonts | { "display", "body", "weight" }: nombres de familia (false para la fuente del sistema) y el peso del título, 300–800 (por defecto 500) | – |
theme.scrim | 0–1: qué tan fuerte se lava el cielo detrás del texto al color de fondo. Por defecto 0.3 | – |
effect | El cielo, la línea y la tela, a continuación | – |
motion.speed | 0.25–2, por defecto 1: qué tan rápido se mueve todo | – |
motion.pointer | true (por defecto) | – |
meta | title (70) y description (170) para búsqueda y vistas previas de enlaces; url e image (direcciones https completas), lang (por defecto en) | – |
La impresión (effect): al menos printTitle o printHeadline.
| Configuración | Límite | Por defecto | Qué es |
|---|---|---|---|
printTitle | 28 caracteres | ninguno | El nombre en la parte superior de la impresión |
printLine | 64 caracteres | ninguno | Una línea pequeña debajo del nombre |
printHeadline | 48 caracteres | ninguno | Las palabras grandes; \n salta la línea. Se encogen para caber en su columna |
printSpecs | 0 a 6 { "label", "value" }, 12 y 14 caracteres | ninguno | La columna de especificaciones a la derecha; las etiquetas se imprimen en mayúsculas |
printChart | true / false | true | Un pequeño gráfico de barras debajo de las especificaciones, su barra más alta en theme.accent |
printChartLabel | 32 caracteres | ninguno | Pie de foto debajo del gráfico |
printFoot | 40 caracteres | ninguno | Texto pequeño en la esquina inferior, p. ej., una dirección web |
cloth | color | #ecebe6 | El algodón |
printInk | color | #15181d | La impresión. Debe alcanzar 7:1 sobre cloth |
La escena (effect), cada configuración opcional:
| Configuración | Rango | Por defecto | Qué hace |
|---|---|---|---|
seed | 1–9999 | 7 | Siembra las nubes y las barras del gráfico |
skyTop | color | #5f9be0 claro, el fondo oscurecido cuando es oscuro | El cielo en la parte superior del héroe |
skyBottom | color | theme.background | El cielo en el horizonte |
clouds | 0–1 | 0.6 | Cuánto del cielo es nube; 0 es despejado |
cloudColor | color | blanco (claro), un gris violeta suave (oscuro) | Las nubes |
drift | 0–1 | 0.35 | Qué tan rápido se deslizan las nubes |
light | day, dusk | day para claro, dusk para oscuro | Sol del mediodía desde arriba, o un sol bajo cálido y una luz de cielo fría |
aspect | 0.8–1.7 | 1.35 | Ancho de la tela sobre su altura |
pegs | 2–6 | 4 | Pinzas de madera a lo largo del borde superior |
peg | color | #c39a64 | Las pinzas |
rope | color | #6f6a62 claro, #cfc6b8 oscuro | La línea |
breeze | 0–1 | 0.45 | Qué tan fuerte la brisa levanta la tela |
weave | 0–1 | 0.5 | Qué tan fuerte se muestra el tejido liso de cerca |
poke | 0–1 | 1 | Qué tan profunda es la hendidura debajo del puntero; 0 la desactiva |
drag | true / false | true | Permitir que los visitantes agarren la tela y la tiren |
size | 0.6–1 | 0.76 | Cuánto del espacio junto al texto ocupa la tela (deja espacio para ser tirada) |
hint | 40 caracteres | "Presiónala · jálela · suéltela" | Una pequeña leyenda en la esquina inferior lejana en pantallas anchas que dice a los visitantes que pueden tocarla; " · " separa sus partes; vacía para ninguna |
Consejos de escritura: el título en la página y las palabras grandes en la tela deben decir cosas diferentes; la tela se lee como un póster, así que mantén sus palabras pocas y grandes. Dos o tres pares de especificaciones se leen mejor que seis. Si la marca tiene una línea divertida sobre ser ligera, volar, secar o colgar, la tela es el lugar para ello.
3. Construir
node <skill>/scripts/build.mjs hero.json out
Enumera cada problema en hero.json de una vez (campos faltantes, texto sobre su límite, una configuración fuera de rango, colores que no contrastan, tinta de impresión demasiado clara en la tela) y no escribe nada hasta que se arreglen. Luego imprime las configuraciones que usó y cualquier cosa que valga la pena revisar, como un acento que oscureció para que el título se lea a 4.5:1.
Escribe out/index.html (CSS, script, logotipo e imagen estática en línea), out/embed.html y out/assets/logo.svg (el icono de pestaña).
4. Verificar
node <skill>/scripts/check.mjs out/index.html
Carga la página a 390, 768, 1024 y 1440 px y debe decir ok en cada una: nada más ancho que la pantalla o cortado, contraste legible para cada línea de texto contra el cielo detrás, nombres en cada enlace y botón, un h1. Las líneas marcadas con · vale la pena revisarlas pero no hacen que falle.
5. Mírala, y tócala
node <skill>/scripts/record.mjs out/index.html --still 1.6 --size 1440x900
node <skill>/scripts/record.mjs out/index.html --still 3.5 --size 1440x900
node <skill>/scripts/record.mjs out/index.html --still 1.6 --size 390x844 --scale 2
node <skill>/scripts/screenshot.mjs out/index.html
La primera es la tela en reposo, la segunda a medio tirón (la mano del script tiene una esquina levantada), la tercera el teléfono. Míralas: ¿está toda la tela en pantalla con espacio alrededor, se lee la impresión, se asientan las pinzas en la línea? screenshot.mjs ejecuta Chrome sin GPU, por lo que muestra la imagen estática que los visitantes ven sin WebGL o cuando la red falla (en out/screens/); verifica que también se lea.
Luego abre out/index.html en un navegador y juega con ella: pasa el ratón, presiona, tira de una esquina sobre la línea, suéltala. En un teléfono, arrastra con un dedo y verifica que la página aún se desplaza cuando deslizas al lado de la tela.
6. Grabar el video
node <skill>/scripts/record.mjs out/index.html --seconds 10
Avanza el héroe a través de 10 segundos a 30 fps a 1920×1080 y escribe out/preview.mp4 y out/poster.png (el fotograma a los 3.5 s, a medio tirón). En el video, un puntero dibujado agarra la esquina inferior a los 2.2 s, la tira hacia arriba hacia ti, la suelta a los 4.4 s, y desde los 6 s pasa la yema del dedo por la tela. Opciones: --size 1080x1350 (retrato), --size 1080x1920, --fps 60, --poster 1.6. Los fotogramas son los mismos en cualquier máquina, siempre que la grabación comience desde 0 (siempre lo hace).
7. Publicarlo
- Como página: sube
out/index.htmlyout/assets/a cualquier host estático (Cloudflare Pages, Netlify, Vercel, GitHub Pages, S3). Usaout/poster.png(o un recorte de 1200×630) comometa.image, subido con el sitio. - En un sitio existente: pega
out/embed.htmldonde vaya el héroe. Todo está bajo el ámbito de#mh-washing-line; mueve los enlaces<link>de fuentes a<head>si lo deseas. Si el sitio ya tiene un<script type="importmap">, fusiona las entradasimportsyintegritydel embed en él. La sección tiene la altura completa de la ventana; establece--mh-heighten ella (p. ej.,style="--mh-height:760px") para menos. En React u otros frameworks, coloca el marcado en el componente y las etiquetas<script>en la página, o renderízalo en un iframe. - Para cambiar la impresión, edita
hero.jsony construye de nuevo.
Solución de problemas
build: fix hero.json first: cada línea nombra el campo y qué cambiar; los problemas de color sugieren un color que funcione.- La tela se corta en el borde: baja
size, o haz la tela más cuadrada (aspectmás cerca de 1). - Las palabras grandes en la tela son pequeñas: se encogen para caber junto a la columna de especificaciones. Usa menos palabras, un
\n, o menos especificaciones y ningún gráfico (las palabras entonces toman el ancho completo). - La tela no se asienta, o se agita demasiado: baja
breeze. - La hendidura es demasiado fuerte o demasiado suave:
poke(0 la desactiva; arrastrar sigue funcionando). record: the effect didn't start: la página cayó a su imagen estática: Chrome no pudo cargar three.js desde jsDelivr (verifica la conexión o un proxy) o no tiene WebGL.ffmpeg not found: instálalo o estableceFFMPEG_PATH.- Los visitantes ven una tela estática: su navegador tiene WebGL desactivado o la CDN está bloqueada (la imagen plana), o pidieron movimiento reducido (un fotograma de la tela viva en reposo, que no se mueve). Esto es por diseño.
- En un teléfono la página no se desplaza: solo detiene el desplazamiento mientras un dedo sostiene la tela; desliza al lado de ella. Si la tela llena la pantalla del teléfono, baja
size.
Archivos
scripts/build.mjs,scripts/record.mjs: lo que ejecutas. Llaman al kit de Motion Heroes.scripts/kit/: el kit compartido por cada habilidad de Motion Heroes: la construcción y verificaciones (build.mjs), el CSS de la sección (shell.css), el tiempo de ejecución del navegador (runtime.js: reloj, pausa, relación de píxeles, movimiento reducido, respaldo), el grabador (record.mjs,cdp.mjs), el three.js y las fuentes fijas (three.json,fonts.json) yKIT.md, que los explica.scripts/effect/: la cuerda de tender en sí:effect.mjs(sus configuraciones, verificaciones e imagen estática),effect.js(el sombreador del cielo, la
…