mviz v1.7.0
¿Qué hace mviz?
Genera gráficos y paneles limpios y centrados en datos a partir de especificaciones JSON compactas o Markdown. Maximiza la relación datos-tinta con un mínimo de elementos decorativos, rejillas y adornos. Utiliza un sistema de diseño de rejilla de 16 columnas.
Configuración
No requiere instalación. Usa npx -y -q mviz que se descarga automáticamente desde npm. La bandera -q reduce la salida de npm mientras aún muestra errores de lint.
Para un uso repetido más rápido, instala globalmente: npm install -g mviz
Qué hace esta habilidad
mviz son dos cosas:
- Un lenguaje de especificación — Markdown con bloques de código delimitados que describen componentes (gráficos, KPI, tablas, notas, etc.). Un archivo Markdown (o una única especificación JSON) describe una visualización completa.
- Un conjunto de renderizadores que convierten esa especificación en HTML para diferentes contextos de visualización. Hoy hay dos:
visualize:show_widget(en línea) — cuando estás en claude.ai con la herramienta de visualización disponible, renderiza la especificación mviz como un fragmento HTML dewidget_codeutilizando el sistema de diseño de claude.ai (Chart.js, tokensvar(--color-*)). El widget aparece en línea en la conversación.- CLI de mviz (independiente) —
mviz dashboard.md -o report.htmlproduce un documento HTML completo con el propio sistema de diseño de mviz (tema mdsinabox, ECharts). Adecuado para descargas, mosaicos iframe, impresión/PDF.
La especificación Markdown de mviz es canónica; el renderizador se elige según dónde aparecerá la visualización. Misma especificación, dos renderizaciones. Un tercero podría construir un renderizador diferente (CLI basado en Chart.js, renderizador con tema de Slack, etc.) sin cambiar la especificación.
Elegir un renderizador
Primero compón siempre la especificación Markdown de mviz, incluso al renderizar en línea. La especificación es el artefacto canónico — emítela en un bloque de código delimitado en tu respuesta para que el usuario pueda copiar/reutilizar/tubería a CLI después. Luego renderízala con el renderizador que se ajuste a la solicitud.
Antes de renderizar, decide qué renderizador se ajusta — y indica tu inferencia para que el usuario pueda corregirte. Algunas señales:
En línea (visualize:show_widget):
- "muéstrame X" / "cómo fue X" / "cómo cambió X" / "renderiza"
- Una visualización pequeña (normalmente de 1 a 4 componentes) que fluye con la prosa circundante
- El usuario está explorando datos, no preparando algo para compartir
visualize:show_widgetestá disponible en esta conversación
Independiente (CLI de mviz):
- "haz un informe" / "envíame el archivo" / "exporta a PDF" / "guarda"
- Vista compuesta de varias secciones (más de 5 componentes, divisores, saltos de página, tablas de ancho completo)
- El usuario quiere algo para guardar, compartir, imprimir o incrustar en un host externo (mosaico iframe, celda de panel)
visualize:show_widgetno está disponible (sin superficie de renderizado en línea)
Por defecto, usa en línea cuando sea ambiguo. Indica la inferencia explícitamente:
"Renderizaré esto en línea ya que pediste verlo en el chat. Si prefieres un archivo descargable, puedo ejecutar la CLI de mviz en la misma especificación — solo dilo."
Si el usuario luego pide la versión de archivo después de un renderizado en línea, la especificación ya está en la conversación — canalízala a través de mviz ... -o out.html sin recomponer.
Estilo visual (tema mdsinabox — para el renderizador CLI)
- Fuente: Helvetica Neue, Arial (limpia sans-serif)
- Firma: Línea de acento naranja en la parte superior de los paneles
- Paleta: Azul primario, naranja secundario, colores semánticos (verde=positivo, ámbar=advertencia, rojo=error)
- Fondo: Papel (
#f8f8f8claro) / Oscuro (#231f20oscuro) - Principios: Alta relación datos-tinta, sin elementos decorativos, mínimas rejillas, los datos hablan por sí mismos
Renderizador: CLI de mviz (HTML independiente)
El renderizador CLI produce un documento HTML completo con el estilo del tema mdsinabox anterior. La salida es adecuada para visualización directa en el navegador, exportación a PDF, incrustación en iframe o uso compartido como archivo.
Gráfico único (JSON)
echo '<json_spec>' | npx -y -q mviz -o chart.html
Panel desde Markdown
npx -y -q mviz dashboard.md -o dashboard.html
Panel desde carpeta
npx -y -q mviz my-dashboard/ -o dashboard.html
Salida incrustada en iframe (--embed)
Cuando el HTML renderizado vivirá dentro del iframe de otro producto (mosaicos de mdw-turbo Prism, celdas de panel, etc.), pasa --embed para eliminar el marco de página (barra de acento rojo, fila de título, alternancia de tema) y aplicar una batería de post-procesos que adelgazan el cuerpo: poda de CSS, fondos transparentes para que el marco de la tarjeta del anfitrión se vea a través, script de ECharts eliminado cuando no hay gráficos presentes, marked eliminado cuando no hay llamada marked.parse(...), minificación de JS, etc.
npx -y -q mviz dashboard.md --embed -o tile.html
El modo embed emite un documento HTML completo (DOCTYPE + html + head + body intactos). No es la herramienta adecuada para visualize:show_widget — para eso, usa el otro renderizador (ver más abajo).
Sistema de rejilla de 16 columnas
Los componentes se dimensionan usando la sintaxis size=[cols,rows]:
```big_value size=[4,2]
{"value": 1250000, "label": "Revenue", "format": "currency0m"}
```
```bar size=[8,6]
{"title": "Sales", "x": "month", "y": "sales", "file": "data/sales.json"}
```
- 16 columnas de ancho total (tanto vertical como horizontal)
- Alto de fila: ~32px por unidad de fila (aproximado - los gráficos tienen relleno)
- Capacidad de página: Vertical [16c × 30r], Horizontal [16c × 22r]
- Los componentes en la misma línea comparten la fila
- Línea vacía = nueva fila
Guías de altura:
| Unidades de fila | Altura aproximada | Bueno para |
|---|---|---|
| 2 | ~64px | KPI, notas de una línea |
| 4 | ~128px | Tablas pequeñas, bloques de texto |
| 5-6 | ~160-192px | Gráficos estándar |
| 8+ | ~256px+ | Tablas densas, gráficos detallados |
Para gráficos con muchas categorías (más de 10 barras, más de 10 filas en gráfico de mancuernas), aumenta las unidades de fila para evitar la compresión.
Diseño lado a lado
Crítico: Para colocar componentes lado a lado, sus bloques de código NO deben tener líneas en blanco entre ellos:
```bar size=[8,5]
{"title": "Chart A", ...}
```
```line size=[8,5]
{"title": "Chart B", ...}
```
Esto renderiza el Gráfico A y el Gráfico B en la misma fila. Agregar una línea en blanco entre ellos los pondría en filas separadas.
Encabezados y saltos de sección
| Sintaxis | Efecto |
|---|---|
# H1 | Título de página |
## H2 | Título de sección |
### H3 | Encabezado en línea ligero (sutil, texto más pequeño) |
--- | Línea divisoria visual |
=== | Salto de página para impresión |
empty_space | Espaciador de celda de rejilla invisible (por defecto 4 columnas × 2 filas) |
Guías de encabezados:
- Establece el título de la página con el frontmatter
title:o un# H1inicial, no ambos. - Usa
## H2para títulos de sección dentro de una página (más común). - Usa
### H3para subtítulos ligeros que no interrumpan el flujo.
Saltos de sección vs página:
- Usa
---para separar secciones lógicas visualmente. El contenido fluye naturalmente a la siguiente página cuando es necesario. - Usa
===solo cuando quieras explícitamente forzar una nueva página (por ejemplo, separando capítulos o secciones principales del informe para salida PDF). - Nunca uses
===por defecto. Solo agrega saltos de página cuando el usuario los solicite específicamente.
Tamaños por defecto
| Componente | Tamaño por defecto | Notas |
|---|---|---|
big_value | [4, 2] | Caben 4 por fila |
delta | [4, 2] | Caben 4 por fila |
sparkline | [4, 2] | Gráfico compacto en línea |
bar, line, area | [8, 5] | Mitad de ancho |
pie, scatter, bubble | [8, 5] | Mitad de ancho |
funnel, sankey, heatmap | [8, 5] | Mitad de ancho |
histogram, boxplot, waterfall | [8, 5] | Mitad de ancho |
combo | [8, 5] | Mitad de ancho |
dumbbell | [12, 6] | 3/4 de ancho |
table | [16, 4] | Ancho completo |
textarea | [16, 4] | Ancho completo |
calendar | [16, 3] | Ancho completo |
xmr | [16, 6] | Ancho completo, alto |
mermaid | [8, 5] | Mitad de ancho (usa ascii: true para arte de texto) |
alert, note, text | [16, 1] | Ancho completo, una fila |
empty_space | [4, 2] | Espaciador invisible |
Combinaciones de tamaño recomendadas
| Objetivo de diseño | Componentes | Tamaños |
|---|---|---|
| 4 KPI en una fila | 4× big_value | [4,2] cada uno |
| 5 KPI en una fila | 4× big_value + 1 más ancho | [3,2] + [4,2] |
| KPI + contexto | big_value + textarea | [3,2] + [13,2] |
| KPI + gráfico | big_value + bar | [4,2] + [12,5] |
Ejemplo: Fila densa de KPI
```big_value size=[3,2]
{"value": 1250000, "label": "Revenue", "format": "currency0m"}
```
```big_value size=[3,2]
{"value": 8450, "label": "Orders", "format": "num0k"}
```
```big_value size=[3,2]
{"value": 2400000000, "label": "Queries", "format": "num0b"}
```
```delta size=[3,2]
{"value": 0.15, "label": "MoM", "format": "pct0"}
```
```delta size=[4,2]
{"value": 0.08, "label": "vs Target", "format": "pct0"}
```
Esto crea una fila con 5 KPI (3+3+3+3+4 = 16 columnas).
Ejemplo: Dos gráficos lado a lado
```bar size=[8,6] file=data/region-sales.json
```
```line size=[8,6] file=data/monthly-trend.json
```
Tipos compatibles
Gráficos: bar, line, area, pie, scatter, bubble, boxplot, histogram, waterfall, xmr, sankey, funnel, heatmap, calendar, sparkline, combo, dumbbell, mermaid
Componentes de UI: big_value, delta, alert, note, text, textarea, empty_space, table
Formato de tablas
Las tablas admiten formato a nivel de columna y celda:
Opciones de columna: bold, italic, type ("sparkline" o "heatmap")
{
"type": "table",
"columns": [
{"id": "product", "title": "Product", "bold": true},
{"id": "category", "title": "Category", "italic": true},
{"id": "sales", "title": "Sales", "fmt": "currency"},
{"id": "margin", "title": "Margin", "type": "heatmap", "fmt": "pct"},
{"id": "trend", "title": "Trend", "type": "sparkline", "sparkType": "line"}
],
"data": [
{"product": "Widget", "category": "Electronics", "sales": 125000, "margin": 0.85, "trend": [85, 92, 88, 95, 102, 125]}
]
}
Anulaciones a nivel de celda: Usa {"value": "text", "bold": true} para anular los valores predeterminados de la columna.
Mapa de calor: Aplica un degradado de color de valores bajos a altos. El texto cambia automáticamente a blanco sobre fondos oscuros.
Tipos de sparkline: line, bar, area, pct_bar (barra de progreso), dumbbell (comparación antes/después)
Ordenar y filtrar:
| Campo | Valores | Predeterminado | Efecto |
|---|---|---|---|
sortable | true / false | true | Haz clic en un encabezado de columna para ordenar. Cicla asc → desc → off. Las columnas numéricas se ordenan por valor sin procesar. |
filter | true / false | false | Cuando es true, renderiza una entrada de búsqueda "Filtrar por cualquier valor…" sobre la tabla. Las filas se filtran en vivo mediante coincidencia de mayúsculas y minúsculas en todas las celdas. |
Ejemplo: {"type": "table", "filter": true, "columns": [...], "data": [...]}
Tipos de notas
Las notas admiten tres niveles de gravedad a través de noteType:
| Tipo | Color del borde | Uso |
|---|---|---|
default | Rojo | Avisos importantes (predeterminado) |
warning | Amarillo | Precaución, datos preliminares |
tip | Verde | Mejores prácticas, consejos profesionales |
Las notas también admiten un label opcional para texto de prefijo en negrita:
{"type": "note", "label": "Consejo profesional:", "content": "Usa atajos de teclado para una navegación más rápida.", "noteType": "tip"}
Ejemplos de gráficos especializados
big_value - Métricas principales con visualización grande:
{"type": "big_value", "value": 1250000, "label": "Revenue", "format": "currency0m"}
- Objeto
comparisonopcional:{"value": 10300, "format": "currency", "label": "vs last month"}muestra el cambio con flecha
dumbbell - Comparaciones antes/después con coloración direccional:
{
"type": "dumbbell",
"title": "ELO Changes",
"category": "team",
"start": "before",
"end": "after",
"startLabel": "Week 1",
"endLabel": "Week 2",
"higherIsBetter": true,
"data": [
{"team": "Chiefs", "before": 1650, "after": 1720},
{"team": "Bills", "before": 1600, "after": 1550}
]
}
- Verde = mejora, Rojo = declive, Gris = sin cambio
higherIsBetter: falsepara clasificaciones (menor = mejor)- Las etiquetas abrevia automáticamente números grandes (7450 → "7k")
delta - Métricas de cambio con coloración direccional:
{"type": "delta", "value": 0.15, "label": "MoM Growth", "format": "pct0"}
- Los valores positivos muestran verde con ▲, los negativos muestran rojo con ▼
- Objeto
comparisonopcional:{"value": 0.05, "label": "vs Target"}
area - Gráfico de líneas relleno para datos acumulativos/volumen:
{
"type": "area",
"title": "Daily Active Users",
"x": "date",
"y": "users",
"data": [{"date": "Mon", "users": 1200}, {"date": "Tue", "users": 1450}]
}
combo - Barras + líneas con doble eje Y:
{
"type": "combo",
"title": "Revenue vs Growth Rate",
"x": "quarter",
"y": ["revenue", "growth_rate"],
"data": [
{"quarter": "Q1", "revenue": 1000000, "growth_rate": 0.15},
{"quarter": "Q2", "revenue": 1200000, "growth_rate": 0.20}
]
}
- El primer campo y se renderiza como barras, el segundo como líneas
- Ejes Y duales con escalas independientes
heatmap - Visualización de matriz 2D:
{
"type": "heatmap",
"title": "Activity by Hour",
"xCategories": ["Mon", "Tue", "Wed", "Thu", "Fri"],
"yCategories": ["9am", "12pm", "3pm", "6pm"],
"format": "num0",
"data": [[0, 0, 85], [1, 0, 90], [2, 0, 72]]
}
- La opción
formatse aplica a las etiquetas de celda (por ejemplo,num0k,currency0k,pct)
funnel - Flujos de conversión o eliminación:
{
"type": "funnel",
"title": "Sales Pipeline",
"format": "num0",
"data": [
{"stage": "Leads", "value": 1000},
{"stage": "Qualified", "value": 600},
{"stage": "Proposal", "value": 300},
{"stage": "Closed", "value": 100}
]
}
- La opción
formatse aplica a etiquetas/información sobre herramientas (por ejemplo,currency_auto,pct,num0)
waterfall - Visualización de cambio acumulativo:
{
"type": "waterfall",
"title": "Revenue Bridge",
"x": "item",
"y": "value",
"data": [
{"item": "Start", "value": 1000, "isTotal": true},
{"item": "Growth", "value": 200},
{"item": "Churn", "value": -50},
{"item": "End", "value": 1150, "isTotal": true}
]
}
bubble - Dispersión con dimensión de tamaño. Admite series para agrupación de colores y showLabels para etiquetas en los puntos.