bitbeet

Yago López

Yo, hecho de cubos: pelo castaño, barba corta, sudadera clara y una remolacha en la mano.

Desarrollador y arquitecto de software en Tenerife

Diseño y construyo aplicaciones web y herramientas de servidor con TypeScript y Python, desde el esquema de la base de datos hasta el despliegue.

Ver proyectoshello@bitbeet.dev

Proyectos propios

Tres proyectos míos, contados paso a paso mientras bajas.

Código abierto · AGPL-3.0 · Python

Noust

Despliega aplicaciones web en tus propios servidores Linux y gestiona todos esos servidores desde una sola consola.

  1. Varios servidores, una consola

    Una central abre un túnel SSH hacia cada uno de tus servidores y los gobierna por su API, sin exponer puertos nuevos en ellos. Antes de lanzar una acción sobre varios ves el plan; el servidor canario va primero y, si falla, el resto no se toca.

    En la animación, una caja central se conecta por tres túneles con tres torres. Una torre, el canario, recibe la acción primero; cuando termina bien, las otras dos la reciben a la vez. En otra vuelta el canario falla y las otras dos quedan sin tocar.

  2. Construye aparte, sin root

    Cada versión se construye en su propio directorio, sin tocar la que sirve. En las aplicaciones nuevas, instalar y compilar corren como noust-build, una cuenta sin home ni shell, y si la prueba de aislamiento falla el build se detiene en vez de seguir como root.

    En la animación, la versión nueva se monta cubo a cubo dentro de un marco. Un script de una dependencia intenta llegar a tres cofres y rebota en el marco cada vez.

  3. Cambia sin cortar

    En modo blue/green, que es opcional, la versión nueva arranca junto a la anterior y recibe tráfico solo si pasa la comprobación de salud en su propio puerto. Entonces nginx valida la configuración y recarga, y la anterior termina sus peticiones antes de pararse.

    En la animación, la versión nueva responde a las comprobaciones, nginx pasa el tráfico a ella y la anterior se apaga cuando se vacía su barra de drenaje.

  4. Vuelta atrás

    Si la versión nueva no pasa la comprobación, la anterior se activa sola y el error trae las pruebas y el journal. Puedes volver a cualquiera de las que siguen en disco; Noust devuelve el código, nunca la base de datos, y pregunta antes de pasar por un cambio de esquema.

    En la animación, una flecha señala la versión activa en una estantería. Una versión nueva falla, desaparece y la flecha vuelve; después la flecha retrocede dos versiones y se detiene un instante ante una marca de cambio de esquema.

  5. Cambios que se deshacen solos

    Cada cambio de sshd o del cortafuegos que haces desde Noust arma un temporizador de systemd que lo deshace a los 300 segundos. Solo puedes conservarlo con un inicio de sesión SSH nuevo: una sesión que ya estaba abierta no demuestra nada.

    En la animación, un cambio cierra la puerta del servidor y arranca un temporizador. Si el acceso nuevo no entra, el temporizador acaba y la puerta se reabre; si entra, el cambio se conserva.

  6. Quién cambió qué

    Cada cambio se anota en un registro cuyas líneas se encadenan con HMAC-SHA256, así que alterar una se nota: noust audit verify señala la primera rota. Si activas las aprobaciones, los cambios equivalentes a root los decide una segunda persona, no quien los pidió.

    En la animación, una petición espera a que otra persona la apruebe, se ejecuta una vez y añade un bloque a una cadena. Después se altera un bloque y el verificador se detiene en él.

  • 85 versiones publicadas entre diciembre de 2025 y octubre de 2026, y casi 12.000 tests.
  • Paquetes deb y rpm para Ubuntu, Debian, Fedora y openSUSE, además de PyPI y una imagen de contenedor.
  • Consola y API con roles, passkeys, doble factor y un registro de auditoría encadenado con HMAC.
  • Edita la configuración de nginx y Apache sin perder comentarios ni formato.

Tecnologías: Python · React · systemd · nginx · Docker

Motor 3D experimental · C++20 · OpenGL 4.5

Prisvector

Un motor 3D con render diferido, sombras en cascada, entidades sobre EnTT y un editor propio.

  1. Pasada de geometría

    Cada objeto se dibuja una vez y escribe en cuatro texturas a la vez: posición y profundidad, normal y metalicidad, color y rugosidad, emisión y oclusión.

    En la animación, el personaje se dibuja una sola vez y aparece a la vez en cuatro imágenes: posición y profundidad, normales, color y oclusión.

  2. Luces que se suman

    Una sola pasada a pantalla completa lee las cuatro texturas y suma la luz de cada foco con un modelo PBR de Cook-Torrance: caben 4 direccionales, 256 puntuales y 64 focos. El resultado queda en HDR y un tone mapping ACES lo lleva a pantalla.

    En la animación, tres luces de colores giran alrededor del personaje; cada una ilumina su propia imagen y las tres se suman en la imagen final. Después, un divisor muestra la imagen sin tone mapping y con ACES.

  3. Cuatro cascadas

    La sombra del sol se reparte en cuatro cascadas: cuatro trozos del campo de visión, cada uno con su caja ortográfica y su propio mapa de 2.048 × 2.048. Los cortes mezclan una escala logarítmica y otra lineal (λ = 0,75), así que cerca de la cámara cada texel cubre menos terreno.

    En la animación, el campo de visión de la cámara, visto desde arriba, se corta en cuatro trozos de 13, 15, 32 y 140 metros. Cada trozo recibe una caja ortográfica y un mapa de profundidad del mismo tamaño, así que el primero es el más nítido.

  4. Atlas de focos

    Hasta 16 focos con sombra comparten una textura de 4.096 × 4.096 dividida en 64 teselas de 512. Cuando ninguna está libre, el motor reutiliza la que lleva más tiempo sin usarse.

    En la animación, cuatro focos piden una tesela por fotograma y la rejilla de 8 por 8 se va llenando en orden. Al llenarse, cada petición nueva sobrescribe la tesela más antigua.

  5. Editor propio

    Paneles acoplables con Dear ImGui, gizmos de ImGuizmo para mover, girar y escalar, y un inspector que edita materiales y luces en vivo. El visor muestra la salida real del motor y hay vistas de depuración del G-buffer y de las cascadas.

    En la animación, seis paneles se acoplan alrededor de un visor; un clic selecciona al personaje, un gizmo lo mueve y lo gira, y la exposición cambia el brillo de la imagen.

Esta demostración la dibuja tu navegador con WebGL 2: reproduce la disposición de las cuatro texturas y los cálculos de las cascadas y del atlas, pero es una explicación, no una captura del motor.

  • Unas 12.900 líneas de C++20 y 970 de GLSL, sin contar líneas en blanco ni comentarios.
  • Un editor con siete ventanas de Dear ImGui y vistas de depuración del G-buffer y de las cascadas.

Tecnologías: C++20 · OpenGL 4.5 · GLSL · EnTT · Dear ImGui · GLFW

Bot experimental · Rust

Ironflow

Bot de arbitraje para mercados de predicción. Un «sí» y un «no» del mismo mercado valen 1 USD juntos cuando el mercado se resuelve; si se pueden comprar por menos, la diferencia es margen.

  1. Un carril por tarea

    Cada pieza es una tarea de Tokio con su propio carril. El libro, las ejecuciones y las órdenes hablan con el motor por colas acotadas; la fusión, el cobro y la conciliación se despiertan con un temporizador.

    Seis carriles horizontales. Por tres de ellos viajan mensajes entre el mercado y el motor: el libro y las ejecuciones entran, las órdenes salen. Los otros tres, fusión, cobro y conciliación, marcan el paso con un temporizador y consultan el inventario.

  2. Libro incremental

    Una captura inicial y luego solo diferencias: cada nivel de precio se inserta o se borra en un árbol ordenado, con decimales exactos. Si el «sí» y el «no» mejores suman menos de 1 USD, hay margen.

    En la animación, una diferencia borra el mejor «sí» (0,46 USD): el siguiente cuesta 0,50 y, con el «no» a 0,50, la suma llega a 1,00 y desaparece el margen. Otra diferencia inserta un «no» a 0,48: suman 0,98, por debajo de 1 USD. Si la conexión cae, el libro se reconstruye con una captura nueva.

  3. La pareja, o ninguna

    Envía a la vez dos órdenes pasivas con la misma cantidad, una por lado y un tick por debajo del mejor precio de venta. Si el mercado rechaza una, cancela la otra.

    Una señal amarilla baja por tres filtros y se divide en dos órdenes del mismo tamaño, una verde y otra roja, que se colocan un tick por debajo del mejor precio. En el segundo ciclo el mercado rechaza la roja y la verde se cancela: no queda ninguna.

  4. Cada ejecución, una vez

    El mercado avisa de cada ejecución hasta tres veces; el bot la apunta una sola, y solo la parte que es suya. Cada 15 s contrasta el inventario con los saldos de la cadena de bloques.

    La ejecución del «sí» llega tres veces con el mismo identificador: la primera entra en el inventario y las otras dos se descartan. La del «no» llega mezclada con las de otros participantes y solo entra la parte del bot. Después una barra compara el inventario con la cadena y lo corrige si no coincide.

  5. Si solo se llena un lado

    A los 90 segundos de colocar el par, cancela lo que siga abierto. Y si en un mercado la diferencia entre «sí» y «no» pasa de 3 fichas, no envía más pares a ese mercado.

    Se ejecuta el «sí» y el inventario queda con cinco fichas más de «sí» que de «no»: una balanza supera el tope de 3 y cierra el paso a nuevos pares. Junto a la orden del «no», un temporizador de doce cubos se llena (los 90 segundos) y la orden se cancela.

  6. Fusiona sin duplicar

    Con 10 pares completos, comprueba cuántos hay en la cadena y los fusiona en 1 USD cada uno; el resto se cobra al resolverse el mercado. Si la respuesta de una transacción se pierde, confirma su hash en otro nodo en vez de reenviarla.

    Diez pares completos pasan una revisión contra la cadena; una losa con un nonce nuevo viaja al nodo principal y los pares se convierten en diez monedas de 1 USD. En el segundo ciclo el nodo principal no responde: la losa no se reenvía, un hash se comprueba en el nodo de respaldo y las monedas aparecen una sola vez.

La versión en Rust está archivada y su repositorio es privado. Lo que más me enseñó: cuando solo se ejecuta una de las dos órdenes, quedarse con ese lado arriesga más que el margen del par; de ahí el límite de 90 segundos y el tope de desequilibrio por mercado. Y la pareja no es atómica: una orden puede ejecutarse antes de que llegue la cancelación de la otra.

  • Unas 10.700 líneas de Rust en un solo crate, con E/S asíncrona sobre Tokio.
  • Cada transacción pide antes un nonce nuevo, y un recibo ambiguo se confirma en un nodo de respaldo sin reenviar la transacción.
  • Reconexión con esperas crecientes, de 0,5 a 30 s, y el libro reconstruido desde una captura nueva.

Tecnologías: Rust · Tokio · WebSocket · rust_decimal · alloy

Trabajo

Productos de Arenna Labs y trabajo para clientes.

Proggest

ERP modular para gestionar personal y trabajo de campo, donde cada empresa activa lo que necesita: control horario, partes de trabajo y EPI, documentos con nóminas y firmas, y apoyo a centros especiales de empleo.

Producto de Arenna Labs, donde trabajo. Soy su desarrollador principal desde octubre de 2025 y lleva más de 100 versiones publicadas.

  • 140 modelos de datos, 747 endpoints y 119 migraciones.
  • Varias empresas en una sola instalación, cada una con sus módulos.
  • App Android con Capacitor sobre el mismo código, publicada en Google Play.

Tecnologías: TypeScript · NestJS · Next.js · Prisma · PostgreSQL · Redis · Capacitor

Attalaya

Vigila la Plataforma de Contratación del Sector Público y cada mañana envía a cada empresa las licitaciones que encajan con su territorio, su sector y su tamaño de contrato.

Producto de Arenna Labs. Lo construyo desde agosto de 2026 y está en producción.

  • A 25 de septiembre de 2026, unas 477.000 licitaciones en la base de datos, con unas 300 a 400 nuevas por día laborable.
  • Reglas fijas que explican cada decisión. La IA solo ayuda a leer los pliegos y nunca descarta un anuncio.
  • 2075 tests con Vitest y 259 de extremo a extremo con Playwright.

Tecnologías: TypeScript · Next.js · React · Drizzle · PostgreSQL · Redis

Despiece de ferralla

Software web para talleres de ferralla (las armaduras de acero del hormigón): editor de formas, planillas, etiquetas con QR, ficheros BVBS para la dobladora, plan de corte y planificador de taller.

  • El plan de corte y el planificador son deterministas: con la misma entrada dan el mismo resultado, byte a byte.
  • Las consultas sobre los datos de cada empresa se filtran por empresa en una capa común, y un modelo o una ruta nueva sin política de acceso hace fallar la integración continua.

Tecnologías: TypeScript · NestJS · Next.js · Prisma · PostgreSQL · Redis

Alquiler de coches por franquicias

Tres aplicaciones para una red de franquicias de alquiler de coches: reservas online con pago, panel de gestión y portal de afiliados.

Desarrollado en Arenna Labs.

  • El panel de gestión bloquea la fila del vehículo con SELECT … FOR UPDATE al crear, editar o intercambiar una reserva, para que dos peticiones simultáneas no reserven el mismo coche.
  • Cada cobro y cada devolución pasan por la pasarela de pago de la franquicia que gestiona la reserva.

Tecnologías: TypeScript · Next.js · React · Prisma · MySQL · BullMQ

Y muchos más.

Cómo trabajo

Pruebo contra sistemas reales
Attalaya tiene casi 600 tests que corren contra un PostgreSQL de verdad. El arnés de integración de Noust arranca systemd dentro de Docker.
Despliego para poder volver atrás
Noust deja construidas las versiones anteriores, así que volver a una es el mismo cambio al revés. Su relevo sin corte para Docker Compose salió de un despliegue real que dio unos quince segundos de errores 502.
Los tests hacen cumplir las reglas
En el software de ferralla, un modelo de datos o una ruta nueva sin política de acceso hace fallar la integración continua.
Controlo quién cambia qué
Noust encadena su registro de auditoría con HMAC, admite passkeys y puede exigir que una segunda persona apruebe los cambios delicados.

Herramientas

A diario: TypeScript, Python, PostgreSQL, Redis, NestJS, Next.js, React, Prisma, Linux, systemd, nginx y Docker.

Cuando hace falta: Rust y C++ con OpenGL.

Contacto

Trabajo en Arenna Labs, en La Laguna. Si tienes un proyecto en mente o quieres que te cuente más de alguno de estos, escríbeme.

hello@bitbeet.dev

La Laguna, Tenerife.