Plantilla

Widget de contador animado para MCP Apps

Unas pocas cifras grandes que cuentan desde cero y entran una detrás de otra. Es el widget para celebrar resultados, no para vigilarlos.

Usa GSAP

Acabamos de cerrar el primer año del programa de mentorías. ¿Me enseñas lo más destacado?

Ha usado show_milestones

El de la casa: contorno negro, amarillo mantequilla y subrayado de rotulador en el título.

Cuándo usar un widget de contador animado

Hay cifras que se merecen su momento. Un balance del año, la primera semana tras un lanzamiento, el cierre de una campaña: no se trata de compararse con el mes pasado, sino de enseñar lo conseguido. Que los números suban desde cero convierte tres datos en una pequeña revelación.

Úsalo para:

  • Balances anuales o trimestrales: personas alcanzadas, eventos celebrados, horas ahorradas.
  • Resultados de un lanzamiento: altas, descargas, países, en los primeros días.
  • Hitos de una comunidad: miembros, colaboradores, pull requests aceptadas.
  • Cierres de proyecto que el equipo va a capturar y compartir.

Si las cifras necesitan una flecha de tendencia y la comparación con el periodo anterior, usa la plantilla de indicadores. Hitos es para celebrar; indicadores, para revisar.

Cómo lo rellena el modelo

El esquema pide un title y una lista de items, con al menos uno. Cada item lleva un label y un value numérico, más tres campos opcionales:

  • decimals (de 0 a 3), para cifras como una nota sobre diez.
  • suffix, que sale detrás del número en pequeño: un signo de porcentaje, "k", una unidad como "km".
  • note, una línea corta de contexto bajo la etiqueta, por ejemplo de dónde sale el dato.

value es un número, no un texto ya formateado. Y eso importa: el widget lo formatea en el idioma que indica el host, con su separador de miles y su coma decimal, y necesita un número de verdad para animarlo. Como el esquema lo declara numérico, el modelo manda 4800 y no "4.800". Encima del título cabe un kicker opcional.

La descripción de la tool le indica al modelo que lo use para balances anuales, resultados de lanzamientos y logros. Funciona mejor con tres a cinco items; con más, la cascada se alarga.

Qué hace en el chat

Las tarjetas suben a su sitio una tras otra y cada número rueda desde cero hasta su valor en algo más de un segundo, frenando al final. Cada tarjeta toma el siguiente color de la paleta del diseño para su marca.

La animación corre con GSAP, cargado como módulo ES de versión fijada desde jsDelivr a través del import map del widget. Como usa una librería, su recurso declara https://cdn.jsdelivr.net en la CSP (resourceDomains y connectDomains), y la exportación lo lleva en el manifiesto. Los hosts bloquean los orígenes que no se declaran, así que eso es lo que mantiene viva la animación en ChatGPT y Claude. La guía de la CSP explica el porqué.

Con el movimiento reducido activado, el script se salta la animación y aparecen sin más las cifras finales, que ya pintó la plantilla. Si llegan datos nuevos, la línea de tiempo anterior se detiene antes de empezar la siguiente.

No declara acciones del host.

Hazlo tuyo

Funciona con todos los diseños. En Nórdico las cifras son finas y grandes; Aurora ilumina cada tarjeta de cristal desde una esquina; Brutalista las convierte en bloques de color planos inclinados como pegatinas; Editorial compone columnas con filetes y cifras Didot, como el lateral de una revista; Neón hace brillar cada número en su color.

La línea de tiempo son unas pocas líneas de script: ahí cambias el escalonado, la duración o la curva. Añade un data-wg-message a cada tarjeta para que un clic le pida al modelo la historia detrás de esa cifra.

Llévalo a tu servidor

Enlaza el widget publicado desde tu servidor MCP para que los cambios le lleguen sin desplegar, o descarga el HTML y el manifiesto. La guía para añadir una interfaz a tu servidor MCP cubre las dos vías. Para que lo cree y lo publique tu agente, mira cómo crear widgets con un agente de IA.

Los datos que recibe

CampoTipoQué es
kickerstring
titleobligatoriostring
itemsobligatorioobject[]
└ labelobligatoriostring
└ valueobligatorionumber
└ decimalsinteger
└ suffixstringShown after the number, e.g. "%" or "k"
└ notestring

Datos de ejemplo

{
  "kicker": "Datos de ejemplo",
  "title": "Un año de formaciones",
  "items": [
    {
      "label": "Personas formadas",
      "value": 1240,
      "note": "en 38 talleres"
    },
    {
      "label": "Satisfacción",
      "value": 9.4,
      "decimals": 1,
      "suffix": "/10"
    },
    {
      "label": "Horas ahorradas",
      "value": 6,
      "suffix": "h/semana",
      "note": "por persona, según encuesta"
    }
  ]
}

La tool que lo muestra

Un widget hecho con esta plantilla se muestra con una tool. El modelo lee su descripción para decidir cuándo llamarla y rellena el esquema de entrada con los datos. Esta es la definición que exporta Widgetry:

{
  "name": "show_milestones",
  "title": "Hitos",
  "description": "Celebrates a few headline numbers: each one counts up from zero with its label and an optional note. Use it for year-in-review summaries, launch results or any achievement worth celebrating.",
  "inputSchema": {
    "type": "object",
    "required": [
      "title",
      "items"
    ],
    "properties": {
      "kicker": {
        "type": "string"
      },
      "title": {
        "type": "string"
      },
      "items": {
        "type": "array",
        "minItems": 1,
        "items": {
          "type": "object",
          "required": [
            "label",
            "value"
          ],
          "properties": {
            "label": {
              "type": "string"
            },
            "value": {
              "type": "number"
            },
            "decimals": {
              "type": "integer",
              "minimum": 0,
              "maximum": 3
            },
            "suffix": {
              "type": "string",
              "description": "Shown after the number, e.g. \"%\" or \"k\""
            },
            "note": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}

Tu primer widget, en el chat en unos minutos

Elige una plantilla, pon tus datos y míralo como lo enseñarán ChatGPT o Claude. Después enlázalo desde tu servidor MCP, o deja que tu agente haga el siguiente.