Cuando decidí construir mi portfolio, tenía una pregunta clara delante: ¿qué dice más de cómo piensas un desarrollador, un sitio con cards de proyectos o una terminal funcional que el visitante puede usar?
La respuesta fue obvia para el público que más me importaba: alguien técnico que revisa tu trabajo entiende perfectamente qué es una terminal. Si construyes una y funciona bien, ya has dicho algo antes de que lean una sola línea de texto.
DevConsole es ese portfolio. Un emulador de terminal web que hoy está en producción en console.leosoftware.dev. Este artículo no es una lista de características. Es la explicación de por qué está hecho así y no de otra manera.
La lógica separada de la pantalla
La decisión más importante fue separar completamente lo que hace la terminal de cómo se ve. Toda la inteligencia de la terminal —qué pasa cuando escribes un comando, cómo se abre un modal, cómo funciona el historial— vive en un único archivo: useTerminal.js.
El componente que renderiza la pantalla (TerminalWindow.vue) no sabe nada de comandos. Solo sabe pintar lo que le pasan. Esta separación tiene una consecuencia práctica concreta: si mañana decido construir otra interfaz encima de la misma lógica —en React, en una app móvil, en cualquier cosa— no tengo que reescribir nada del núcleo. Solo cambio la pantalla.
No es una decisión de diseño teórica. Es el resultado de preguntarse desde el principio qué parte del sistema tiene cada responsabilidad y no mezclarlas.
Sin tocar el HTML directamente desde la lógica
Un emulador de terminal tiene una tentación obvia: manipular el HTML de la página directamente cuando se ejecuta un comando. Es rápido de escribir y funciona al momento. También crea un problema: la lógica queda atada a la estructura visual de una manera que después es difícil de cambiar o probar.
En su lugar, el área de output de la terminal es un componente separado que expone dos operaciones: añadir contenido y limpiar. Cuando un comando se ejecuta, llama a esa operación. El componente de output decide cómo mostrarlo. La lógica de comandos solo sabe que existe un output en algún sitio.
El resultado: la lógica no depende de la estructura de la pantalla. Puedes cambiar cómo se ve el output sin tocar ningún comando.
Autocompletado mientras escribes
El autocompletado funciona como en los editores de código modernos: mientras escribes, aparece en texto tenue la continuación más probable del comando.
La implementación es deliberadamente simple. Hay una lista de todos los comandos disponibles. Mientras el usuario escribe, el sistema busca en esa lista el primer comando que empiece por lo que lleva escrito. Si lo encuentra, muestra el resto en gris tenue superpuesto al texto. Tab o flecha derecha completan el comando al instante.
Sin llamadas a ningún servicio externo, sin lógica compleja de espera. La lista tiene menos de veinte comandos. La simplicidad aquí era la decisión correcta.
Traducciones que no pesan desde el inicio
DevConsole funciona en inglés y español. La forma en que se implementan los idiomas tiene una consecuencia directa en cuánto tarda en cargarse la aplicación: si incluyes todas las traducciones dentro del código que el navegador descarga, el usuario recibe el texto de todos los idiomas aunque solo use uno.
La solución: las traducciones viven en un archivo separado que se descarga una sola vez al abrir la terminal. El idioma activo se guarda en el navegador. Si el usuario cambia de idioma con el comando lang en o lang es, los textos se actualizan al momento sin recargar la página.
Sin librerías externas de internacionalización, sin peso adicional en la carga inicial.
El fondo animado
El fondo de DevConsole es un canvas —una superficie de dibujo en el navegador— con partículas que se mueven guiadas por un campo de fuerzas generado matemáticamente. Cada partícula calcula su dirección a partir de su posición y el tiempo. Las partículas que pasan cerca del cursor se desvían.
Hay dos optimizaciones que importan en producción. Primera: el número de partículas se reduce automáticamente en móvil —en pantallas pequeñas hay un 30% de las partículas que habría en escritorio— para no sobrecargar el dispositivo. Segunda: la animación se pausa sola cuando la terminal no está visible en pantalla. No tiene sentido gastar recursos del dispositivo cuando el usuario está mirando otra cosa.
Lo que aprendí construyendo esto
La decisión más difícil no fue técnica. Fue resistir la tentación de añadir funcionalidades solo porque era posible añadirlas. Una terminal puede crecer indefinidamente: sistema de archivos, historial persistente, tuberías entre comandos. Nada de eso estaba en el objetivo.
El objetivo era construir algo que demostrara criterio —no cantidad de funciones. Cada decisión en DevConsole existe porque resuelve un problema real, no porque quedara bien en la descripción.
