Si has navegado por este blog habrás notado que cada artículo tiene una imagen cuadrada diferente. Un patrón de cubos que parece un código QR pero no lo es. Colores que cambian de un post a otro. Y en el centro, siempre el mismo kanji: 忍.
Esas imágenes no fueron diseñadas manualmente. Fueron generadas por el contenido mismo de cada artículo.
Cómo funciona
Cuando publico un artículo el sistema toma dos datos: el título y la cantidad de caracteres del contenido. Con el título genera un hash criptográfico, una cadena única e irrepetible de caracteres. Ese hash se convierte en un mapa que decide qué cubos de una grilla de 32 por 32 se llenan y cuáles quedan vacíos. Es el mismo principio que usa un código QR real pero sin codificar ningún dato legible. Solo el ADN del texto convertido en forma visual.
La cantidad de caracteres determina el color accent de cada imagen:
Los artículos cortos son dorados. Los de longitud media pasan por azul frío y púrpura. Los más largos son terracota. Y si algún día escribo algo realmente extenso, será verde menta.
El resultado es que cada artículo tiene una huella visual única. Si cambio una sola palabra del título el patrón cambia completamente. Si el artículo crece o se reduce de categoría el color muta. La imagen está viva mientras el texto lo esté.
El kanji del centro
En el centro de cada imagen hay un espacio en blanco con el kanji 忍. Se lee shinobi en japonés. Significa perseverar en silencio, resistir con paciencia, moverse sin ser visto. Es el origen del nombre de este blog y el ancla visual que conecta todas las imágenes entre sí sin importar cuán diferentes sean sus patrones.
Por qué no usar imágenes normales
Podría haber usado fotografías de stock o imágenes generadas con Midjourney para cada post. Pero este blog habla sobre la intersección entre diseño y tecnología. Quería que hasta las imágenes reflejaran esa filosofía. Que no fueran decoración sino datos convertidos en forma. Que cada una contara algo sobre el artículo que representa sin necesidad de leerlo.
También hay una razón práctica. Este sistema es completamente automático. Cuando publico un artículo nuevo las imágenes para los tres idiomas se generan solas. No tengo que buscar fotos, no tengo que abrir Photoshop, no tengo que pensar en qué imagen poner. El contenido se ilustra a sí mismo.
Detalles técnicos
El sistema funciona con PHP y la librería GD. Sin APIs externas, sin JavaScript, sin proceso de build. Cuando se publica un artículo, la imagen se genera sola en milisegundos. Paso 1: Extraer el ADN Cada imagen parte de dos datos: el título del post y la cantidad de caracteres del contenido.$charCount = mb_strlen(strip_tags($content), 'UTF-8');
$titleHash = md5($title . $postId);
$contentHash = sha1($content . $postId);
El hash del título determina el patrón visual. El hash del contenido agrega entropía. La cantidad de caracteres define el color. Tres entradas, tres capas de identidad.
Paso 2: Mapear caracteres a color
La cantidad de caracteres ubica cada artículo en un espectro de color. Los artículos cortos son dorado cálido. Los más largos pasan por azul frío, púrpura y terracota. Cualquiera que supere los 9000 caracteres se vuelve verde menta.
$colors = [
[200, 170, 100], // dorado (menos de 3000 caracteres)
[100, 170, 200], // azul frío (3000-5000)
[170, 100, 200], // púrpura (5000-7000)
[200, 120, 100], // terracota (7000-9000)
[100, 200, 150], // verde menta (9000+)
];
$colorIndex = min(4, intdiv($charCount, 2000));
$accent = $colors[$colorIndex];
Esto significa que puedes adivinar la extensión de un artículo solo mirando su imagen. El color es información.
Paso 3: Expandir el hash en una grilla
Un hash MD5 tiene 32 caracteres. La grilla es de 32x32 = 1024 celdas. Para cubrir cada celda, el sistema encadena múltiples hashes:
$fullHash = $titleHash . $contentHash . md5($charCount . $postId);
$expandedHash = '';
for ($i = 0; $i < 20; $i++) {
$expandedHash .= md5($fullHash . $i);
}
Esto produce 640 caracteres hexadecimales, más que suficiente para mapear cada celda de la grilla. Cada carácter hexadecimal (0-F, valor 0-15) determina qué le pasa a esa celda.
Paso 4: Llenar la grilla
Cada celda lee un carácter del hash expandido y decide su destino:
for ($row = 0; $row < 32; $row++) {
for ($col = 0; $col < 32; $col++) {
$hashChar = $expandedHash[$hashIndex % strlen($expandedHash)];
$hashVal = hexdec($hashChar); // 0-15
$hashIndex++;
if ($hashVal >= 10) {
// Cubo oscuro (valores A-F)
$brightness = 20 + ($hashVal - 10) * 8;
// Rellenar con casi negro
} elseif ($hashVal >= 7) {
// Cubo con color accent (valores 7-9)
// Rellenar con el color determinado por la extensión
} elseif ($hashVal >= 5) {
// Cubo gris claro (valores 5-6)
}
// Valores 0-4: vacío (blanco)
}
}
La distribución es aproximadamente: 37% cubos oscuros, 19% cubos accent, 13% cubos grises, 31% vacíos. Esta proporción produce patrones lo suficientemente densos para parecer datos pero lo suficientemente abiertos para ser legibles.
Paso 5: Limpiar el centro
Una ventana de 6x6 celdas en el centro de la grilla se limpia. Esto crea respiro visual y deja espacio para el kanji:
$centerStart = (32 / 2) - 3;
$centerEnd = (32 / 2) + 3;
for ($row = $centerStart; $row < $centerEnd; $row++) {
for ($col = $centerStart; $col < $centerEnd; $col++) {
imagefilledrectangle($img, $x1, $y1, $x2, $y2, $whiteBg);
}
}
El kanji 忍 (shinobi, perseverar en silencio) se renderiza con la fuente Noto Sans CJK si está disponible en el servidor, teñido con el mismo color accent.
Paso 6: Guardar y servir
La imagen final es un PNG de 1200x1200 con compresión nivel 7. Cada post genera una imagen por idioma, almacenada como post-{id}-{lang}.png:
$filepath = "uploads/social/post-{$postId}-{$langCode}.png";
imagepng($img, $filepath, 7);
La misma imagen se reutiliza en tres contextos: como miniatura en la portada, como encabezado dentro del artículo, y como imagen Open Graph cuando alguien comparte el enlace en redes sociales.
El resultado
El sistema es determinista. Mismo contenido, misma imagen, siempre. Sin aleatoriedad, sin dependencias externas. Cambia una palabra en el título y el patrón completo se transforma. Agrega un párrafo y el color puede mutar.
Es diseño generativo en el sentido más literal: el contenido genera su propia identidad.
Impleméntalo tú mismo
El código fuente completo es un solo archivo PHP de menos de 250 líneas. Necesita PHP con GD habilitado y nada más. La lógica central (expansión de hash, mapeo de grilla, selección de color) se puede adaptar a cualquier lenguaje. El principio es simple: toma cualquier cadena única, expándela en suficiente entropía para llenar una grilla, y mapea rangos de valores a propiedades visuales.
Si eres desarrollador o diseñador y quieres implementar algo similar, el enfoque funciona para cualquier plataforma de contenido donde quieras visuales únicos, automáticos y deterministas sin depender de generación por IA ni fotografía de stock.