¿Qué hace stack-diagram?
Genera diagramas de arquitectura al estilo de dibujo de ingeniería: logotipos reales sobre mosaicos blancos, cajas de grupo etiquetadas (como diagramas VPC de proveedores de nube), flechas ortogonales con etiquetas monoespaciadas, sobre un fondo de papel cuadriculado. Un único archivo HTML autónomo es la fuente de verdad; los formatos PNG / TSX / artefacto se derivan de él.
Requisitos
- Python 3.9+ (solo librería estándar para
fetch_icons.py,build.pyyshare.py) - Acceso a red a las fuentes de iconos (svgl.app, raw.githubusercontent.com, cdn.jsdelivr.net, aws.amazon.com y d1.awsstatic.com para iconos AWS, services.google.com para iconos Google Cloud, learn.microsoft.com y arch-center.azureedge.net para iconos Azure, además del propio sitio o repositorio de la marca para
name=URL) al obtener iconos - Playwright + Chromium para
render_png.py:pip install playwright && python3 -m playwright install --with-deps chromium
Flujo de trabajo
- Acordar el contenido (nodos, grupos, bordes)
- Obtener iconos —
scripts/fetch_icons.py - Planificar coordenadas — leer
references/geometry.md - Construir el HTML a partir de
assets/template.html—scripts/build.py - Renderizar un PNG y revisarlo antes de entregar
- Entregar en los formatos solicitados
- Opcionalmente compartir en la galería pública
Paso 1 — Contenido
A partir de la lista de tecnologías/servicios del usuario, se decide:
- Nodos: cada tecnología = un nodo (nombre y un rol corto en minúsculas como
http server,sqlite db) - Grupos: dibujar un cuadro alrededor de cosas que comparten tiempo de ejecución, proveedor o repositorio (p.ej., una caja de proveedor de nube que contiene una caja de tiempo de ejecución; una caja de monorepo para herramientas). Anidar a un nivel de profundidad está bien; más allá se vuelve ruidoso. Escribir las etiquetas de grupo con la escritura mayúscula original de la marca (
GitHub,npm); la plantilla las muestra tal como se escriben. - Bordes, tres tipos:
- sólido con color de acento = el flujo primario de solicitudes/datos (un camino continuo se lee mejor)
- sólido neutro = conexiones secundarias internas
- discontinuo neutro = relaciones en tiempo de desarrollo/despliegue (CI, hooks de git, IaC deploy)
Si el usuario solo dio una lista plana de herramientas, inferir grupos y flujos sensatos según lo que son las herramientas — solo preguntar cuando una herramienta sea lo suficientemente ambigua como para que el diagrama esté mal de cualquier manera.
Paso 2 — Iconos
python3 scripts/fetch_icons.py <icons-dir> tanstack hono drizzle "betterauth:better-auth" "orpc=https://orpc.unnoq.com/logo.webp"
python3 scripts/fetch_icons.py <icons-dir> "aws:aws/AWS-Cloud-logo" "vpc:aws/vpc" "fargate:aws/fargate" "s3:aws/s3"
python3 scripts/fetch_icons.py <icons-dir> "gcp:google-cloud" "run:gcp/cloud-run" "lb:gcp/load-balancing" "sql:gcp/cloud-sql"
python3 scripts/fetch_icons.py <icons-dir> "azure:azure/Azure-A" "app:azure/app-service" "vnet:azure/vnet" "sql:azure/sql-database"
python3 scripts/fetch_icons.py <icons-dir> "k8s:kubernetes" "ing:k8s/ingress" "svc:k8s/service" "deploy:k8s/deployment" "pod:k8s/pod"
Formas de especificación: name (nombre usado como slug), name:slug (slug diferente), name=URL (URL explícita), name:aws/<Name> (icono oficial de AWS), name:gcp/<Product> (icono oficial de Google Cloud), name:azure/<Name> (icono oficial de Azure), name:k8s/<Resource> (icono oficial de Kubernetes). El script intenta, en orden: svgl → devicon → gilbarbara/logos, escribe archivos más manifest.json, y marca los iconos cuyo relleno es blanco. svgl (svgl.app) es el primero porque contiene las marcas oficiales actuales para marcas de desarrollo modernas (TanStack, Better Auth, Hono...). Cuando un logotipo tiene versiones clara/oscura, la clara se convierte en <name> (los mosaicos son blancos en ambos temas) y la oscura se guarda como <name>_dark para las etiquetas de grupo. svgl se empareja solo por título exacto, por lo que un fallo simplemente pasa. Su API también expone variantes wordmark — ocasionalmente útil para una etiqueta de grupo ancha, nunca para mosaicos.
Reglas que importan más que la mecánica:
- Nunca cambiar el color de un logotipo. Los usuarios lo notan. Si un logotipo es blanco o demasiado claro para un mosaico blanco, colocarlo en un mosaico oscuro (clase
tile dark) en lugar de tocar su relleno. La banderawhite_fillen el manifiesto es una heurística — un relleno blanco puede ser un detalle interno en una marca de color (tRPC, Ubuntu), por lo que se debe echar un vistazo al SVG antes de recurrir al mosaico oscuro. - Solo marcas oficiales. simple-icons no es una fuente deliberadamente: sus glifos son redes de dibujo monocromas, y los usuarios los llaman incorrectos a simple vista. Cuando todas las fuentes fallan (
FAIL), encontrar el archivo oficial y pasarlo comoname=URL— buscar en el repositorio del proyecto (raízlogo*.svg,docs/,assets/,public/) y en su sitio (/logo.svg,/favicon.svg,/images/logo.svg). Algunas marcas solo viven en el repositorio (la de Lefthook eslogo_sign.svgen la raíz deevilmartians/lefthook). - Los conceptos abstractos reciben pictogramas, no texto. Un nodo como "entorno de desarrollo", "cron", "cola", "caché" o "receptor de webhook" no tiene marca — recurrir a un icono de línea de Lucide mediante
name:lucide/<icon>(p.ej.,devenv:lucide/terminal,cron:lucide/clock; navegar en lucide.dev/icons). Sin texto en un mosaico, sin emoji. - Los subproductos de proveedores (Cloudflare D1/R2/KV...) generalmente no tienen un logotipo distinto: simplemente reutilizar el logotipo del proveedor en el mosaico y dejar que el nombre del nodo lleve la distinción ("Cloudflare D1" / "sqlite db").
- AWS usa sus propios iconos. Cada servicio tiene uno: obtenerlo con
name:aws/<Name>, leer del paquete oficial de iconos de AWS en tiempo de ejecución (p.ej.,lambda:aws/lambda,aws:aws/AWS-Cloud-logo,s3:aws/s3). El prefijoAWS-/Amazon-es opcional, los acrónimos comunes funcionan (s3,sqs,sns,ses,ecs,eks,ecr,elb,alb,nlb,iam,kms,msk,vpc), y un fallo imprime todos los nombres. Los slugsaws,amazonwebservicesyaws-*van al mismo paquete, y lo que no contieneFAILs en lugar de recurrir a una copia de terceros. Siempre escribir el prefijoaws/para un servicio: undynamodbdesnudo aún pasa por la cadena de terceros. Mantener el paquete y los archivos de iconos sueltos fuera de los repositorios: AWS permite los iconos en diagramas, y la redistribución no está confirmada. - El área de AWS sigue sus propias reglas de dibujo. Los iconos de servicio llevan su propio cuadrado y funcionan sobre fondos claros y oscuros, por lo que se usa
tile bare: un mosaico blanco solo duplica el marco. Las personas y nodos genéricos dentro de él usan los iconos generales de AWS (user:aws/General-User; tambiénGeneral-Users,General-Client,General-Internet,General-Server) entile bare rescon el parlt/dkde la plantilla. Los grupos usan elgroup awsde la plantilla para AWS Cloud (conaws:aws/AWS-Cloud-logoen la etiqueta), másregion,az,vpc,privateopublicpara el resto: esquinas cuadradas, solo contorno, etiqueta en tinta, sin tinte del proveedor, y un icono de 30px empotrado en la esquina en lugar del de 14px. Dentro de una VPC, mostrar subredes públicas y privadas cuando se conozca o se pueda inferir de forma segura la división (un balanceador de carga orientado a internet en público; servidores de aplicación y bases de datos en privado): una VPC plana es lo primero que notan los usuarios de AWS. Los bordes dentro de ella usan un color y un puntero de flecha abierto:<path class="aws" ... marker-end="url(#open)"/>,aws dashpara desarrollo/despliegue, etiquetas.elsimples, y sin leyenda para ellos. Nombrar los nodosAmazon S3/AWS Fargate, no un simpleS3/Fargate; una forma corta comoALBva en la línea de rol, debajo del nombre completo (Elastic Load Balancing). Los nombres pueden ocupar dos líneas, peroAmazon/AWSdebe permanecer en la línea de la primera palabra: si se dividiría justo después del prefijo, ensanchar ese nodo (left:<centerX-76>px; width:152px). - Google Cloud usa sus propios iconos. Obtenerlos con
name:gcp/<Product>, leer de los paquetes oficiales de Google en tiempo de ejecución (p.ej.,run:gcp/cloud-run,lb:gcp/load-balancing,memorystore:gcp/memorystore). Solo los productos principales tienen su propio icono (Cloud Run, Cloud SQL, Cloud Storage, BigQuery, GKE, Compute Engine, Vertex AI...). Cada otro producto usa el icono de su categoría, como especifica la guía de Google: Cloud Load Balancing y Cloud CDN obtienen Networking; Memorystore y Firestore obtienen Databases. Escribir el nombre del producto y el script elige el icono. El prefijoCloud/Googlees opcional, algunas formas cortas funcionan (vpc,iam,kms,iap,gce,gcs), y un fallo imprime todos los nombres.gcp/storagees la categoría Storage; Cloud Storage esgcp/cloud-storage. Los slugsgcp-*ygoogle-cloud-*van a los mismos paquetes, y lo que no contienenFAILs en lugar de recurrir a una copia de terceros: esas copias son los iconos hexagonales retirados, que Google dice que no se deben usar. Siempre escribir el prefijogcp/para un producto: unbigquerydesnudo aún pasa por la cadena de terceros.gcp:google-cloudes la marca de Google Cloud para la etiqueta de grupo. Gemini y Firebase no están en los paquetes: usar losgeminiyfirebasesimples. Mantener los paquetes y archivos de iconos sueltos fuera de los repositorios: Google ofrece los iconos para diagramas y documentación, y la redistribución no está confirmada. - Los diagramas de Google Cloud mantienen el estilo normal, con los grupos de Google. Los diagramas propios de Google (panel azul sólido, tarjetas horizontales) no se copian deliberadamente: los iconos van en el mosaico blanco normal, y los bordes y la leyenda se mantienen como siempre. Los grupos usan el
group gcpde la plantilla para Google Cloud (congcp:google-clouden la etiqueta), másvpc,region,subnetozone. Una VPC es global y una subred es regional, por lo que la región va dentro de la VPC, nunca la VPC dentro de una región. Los servicios globales y serverless (un balanceador de carga externo, Cloud Storage, Cloud Run) quedan fuera de la VPC. Debido a que los iconos se comparten, siempre escribir el nombre completo del producto (Cloud Load Balancing, noLB), y ensanchar un nodo cuyo nombre se dividiría (left:<centerX-76>px; width:152px). - Azure usa sus propios iconos de Microsoft. Cada servicio tiene uno: obtenerlo con
name:azure/<Name>, leer del paquete oficial de Microsoft en tiempo de ejecución (p.ej.,app:azure/app-service,azure:azure/Azure-A,vault:azure/key-vault). El prefijoAzure-/Microsoft-y unasplural son opcionales, las formas cortas comunes funcionan (aks,vm,vnet,nsg,waf,blob,cosmos,redis,postgres,functions,front-door,apim,ai-search), y un fallo imprime todos los nombres. Los slugsazure,microsoft-azureyazure-*van al mismo paquete, y lo que no contieneFAILs en lugar de recurrir a una copia de terceros. Siempre escribir el prefijoazure/para un servicio: uncosmosdesnudo aún pasa por la cadena de terceros. Microsoft Entra ID tiene un conjunto de iconos separado: pasar su archivo oficial comoname=URL. Microsoft permite estos iconos solo en diagramas de arquitectura, materiales de formación y documentación. Nunca recortar, voltear, rotar o reformar uno, usarlo solo para el servicio de Microsoft que representa, y mantener el paquete y los archivos de iconos sueltos fuera de los repositorios. - Los diagramas de Azure mantienen el estilo normal, con los colores de grupo de Microsoft. Los diagramas propios de Microsoft no se copian deliberadamente: los iconos van en el mosaico blanco normal, y los bordes y la leyenda se mantienen como siempre. Los grupos usan el
group azurede la plantilla para Azure (conazure:azure/Azure-Aen la etiqueta), másrg,region,vnet,subnetozone, y una etiquetavnetosubnetlleva su icono (vnet:azure/vnet,subnet:azure/subnet). Una VNet pertenece a una región, por lo que va dentro de la región. Los servicios globales como Front Door quedan fuera de la región. App Service queda fuera de la VNet a menos que se ejecute en un App Service Environment, y un servicio PaaS alcanzado a través de un punto final privado puede sentarse dentro de ella conprivate endpointcomo su rol. Microsoft solicita el nombre completo del servicio junto a cada icono (Azure SQL Database, noSQL), por lo que se debe ensanchar un nodo cuyo nombre se dividiría (left:<centerX-76>px; width:152px). - Kubernetes usa iconos oficiales de la comunidad. Obtenerlos con
name:k8s/<Resource>, leer del conjunto de iconos oficial de kubernetes/community (p.ej.,pod:k8s/pod,deploy:k8s/deployment,svc:k8s/service,ing:k8s/ingress,cm:k8s/configmap,secret:k8s/secret,node:k8s/node,api:k8s/kube-apiserver). Los iconos usan las variantes sin etiqueta para recursos e infraestructura para mantener los glifos limpios y sin desorden a escala de diagrama, y variantes etiquetadas para componentes del plano de control. Nombres cortos y plurales comunes funcionan (svc/service/services,deploy/deployment/deployments,po/pod/pods,cm/configmap/configmaps,sts/statefulset,ds/daemonset,node/nodes, etc.). Un fallo imprime los nombres disponibles. Los slugsk8s,kubernetes, yk8s/k8sproporcionan el logotipo oficial de la rueda de Kubernetes a través de la cadena. - Los diagramas de Kubernetes mantienen el estilo normal por defecto. Los iconos se colocan en el mosaico blanco normal, que los unifica con otras tecnologías en el stack (como NGINX, cert-manager, bases de datos externas o balanceadores de carga en la nube) y proporciona elevación y contraste consistentes sobre fondos de papel cuadriculado. Para glifos independientes mínimos,
tile baretambién es compatible. Los grupos usan grupos estándar (cluster,namespace,node,pod). Atribuir al Kubernetes Icons Set en el pie de página del diagrama. - Las reglas de un proveedor cubren solo su propia área. Las reglas de AWS, Google Cloud, Azure y Kubernetes se aplican solo dentro del grupo de ese proveedor, incluso cuando el diagrama no muestra nada más. Todo lo que está fuera de él, como un usuario al lado o un borde que cruza hacia él, mantiene los mosaicos, grupos, bordes y leyenda normales.
- Nodos sin marca (usuario, navegador, internet, dispositivos, servidor bare-metal): copiar un glifo de
assets/generic/al directorio de iconos bajo el nombre del nodo, o usarname:lucide/<icon>— no usar emoji. Estos no son logotipos de marca, por lo que teñirlos con el color de tinta del diagrama está bien (el script de obtención lo hace automáticamente para Lucide). - Los iconos de etiqueta de grupo se renderizan a 14px — necesitan un glifo cuadrado. Las marcas de texto y los logotipos anchos se vuelven ilegibles a ese tamaño; si el icono principal es una marca de texto, obtener el icono cuadrado de la marca por separado para la etiqueta (svgl generalmente lo tiene; de lo contrario, el icono del propio proyecto o archivo favicon).
- Las etiquetas de grupo se colocan sobre el color de fondo del grupo, no sobre un mosaico blanco, por lo que en el tema oscuro una marca con partes negras desaparece allí. Si
fetch_icons.pyguardó<name>_dark, usar el parlt/dkde la plantilla en la etiqueta; si no hay variante oscura y la marca tiene partes negras, agregar la claseplatea la etiqueta...