Cómo rediseñé mi Planning Poker en un fin de semana junto a mi amigo Claude.
Este fin de semana me aburría, sí, me aburría y se me ocurrió rediseñar mi Planning Poker, y de paso desplegarlo de nuevo, en realidad el que tenía antes no funcionaba muy bien.
Hace tiempo monté una aplicación de Planning Poker para estimar tareas en equipo. Funcionaba, pero tenía ese aspecto de proyecto personal hecho un domingo por la tarde: pantallas apretadas, scroll donde no tocaba y un par de detalles que me daban vergüenza cada vez que se la enseñaba a alguien.
Este fin de semana por fin le he dedicado tiempo y la he dejado como la imaginaba desde el principio.
Para quien no lo conozca: el Planning Poker es una forma de estimar el esfuerzo de una tarea sin que unas opiniones influyan en otras. Cada persona elige una carta a la vez, nadie ve el voto de los demás hasta que el administrador los destapa, y entonces se habla de las diferencias. La gracia está en que nadie se ancla al número que ha dicho el primero.
Qué he cambiado:
Lo primero es el diseño, y quería que fuera más moderno y más limpio. Para eso he usado Claude con su comando /design, y es la parte que más me ha gustado, tal vez me haya gustado más, porque si yo tuviera que ganarme la vida diseñando me moría de hambre.
Para el rediseño he usado Claude Code con el comando /design. La idea es trabajar primero en la dirección visual de una pantalla: le explicas qué aplicación tienes, quién la va a utilizar y qué quieres mejorar. A partir de ahí puedes revisar la propuesta, pedir cambios concretos y repetir el proceso hasta acercarte al resultado que buscas.
Lo que más me ha sorprendido no es que acierte a la primera, sino lo rápido que puedes probar alternativas y descartar las que no funcionan.
Así lancé yo el prompt. El primero fue más o menos este:
▎ /design Rediseña la pantalla de inicio de mi aplicación existente de▎ Planning Poker.▎▎ **Contexto:** es una herramienta para equipos que estiman tareas. Un usuario▎ crea una partida, comparte un enlace y los demás participantes se incorporan▎ introduciendo únicamente su nombre, sin necesidad de registrarse.▎▎ **Objetivo:** mejorar la experiencia de usuario y la jerarquía visual,▎ haciendo que crear una partida o unirse a una existente resulte inmediato.▎▎ **Dirección visual:** diseño moderno, limpio y minimalista, con suficiente▎ espacio en blanco, tipografía legible, tarjetas bien diferenciadas y una▎ jerarquía clara entre las acciones principales y secundarias. Evita▎ elementos decorativos que no aporten valor.▎▎ **Responsive:** prioriza el diseño móvil, con botones fáciles de pulsar,▎ formularios cómodos de utilizar y una distribución que se adapte también▎ a pantallas grandes.▎▎ **Restricciones:** respeta la funcionalidad existente y no añadas pasos▎ innecesarios al flujo de entrada. Antes de modificar el código de la▎ aplicación, quiero revisar y validar la propuesta visual.▎▎ Genera una propuesta que pueda iterar mediante instrucciones posteriores.
Este prompt está pensado para rediseñar una aplicación existente y se buscaba un rediseño, por lo que no sería el mas ajustado para un diseño de una nueva aplicación.
El prompt tiene tres cosas que creo que son las que marcan la diferencia: cuenta para qué es la aplicación y quién la usa, pide el tono con adjetivos concretos y menciona la versión móvil desde el principio.
A partir de ahí fui iterando con frases cortas, de una en una («menos elementos», «más espacio entre las tarjetas», «que el estado de cada jugador se vea de un vistazo»). Y fui pantalla a pantalla: cuando el inicio me convenció, lo usé de referencia para pedir la sala de juego con «mantén el mismo estilo que la pantalla de inicio».
- Empecé contando para qué es la aplicación y quién la va a usar, no cómo quiero que se vea. Yo le expliqué que es una herramienta para equipos, que se abre muchas veces desde el móvil con un enlace y que no hay registro. Con ese contexto, las decisiones de diseño ya salen con sentido.
- Pedí el tono con adjetivos concretos, como moderno, limpio y con mucho aire, y no con detalles sueltos. Es más fácil corregir una dirección general que mil píxeles.
- Fui pantalla a pantalla. Primero el inicio, luego la sala de juego. Si lo pides todo de golpe, el resultado es más genérico.
- Corregí con frases cortas y de una en una: «menos elementos», «más espacio entre las tarjetas», «que el estado de cada jugador se vea de un vistazo», «usa esta gama de colores #000000». Cada ronda es rápida, así que da igual iterar muchas veces.
- Pedí siempre la versión de móvil, y desde el principio. Es mucho más fácil pensarlo desde el principio que ajustarlo al final.
- Cuando descubrí una pantalla que me convenció, la tomé como referencia para las siguientes, y así toda la aplicación mantuvo el mismo estilo.
- Después, ese diseño lo llevé al código del proyecto con la ayuda de Claude, y ahí es donde vi el ahorro de tiempo: y ahí es donde realmente te das cuenta que llegas a la implementación de un diseño, sabiendo ya lo que quieres.
Stack tecnológico de la aplicación:
El proyecto tiene dos partes que se hablan entre sí.
El backend es una API en .NET 10. La he organizado por funcionalidades (cartas, partidas, usuarios y votos), y cada una tiene sus controladores, comandos, consultas y repositorios. Para separar lo que lee de lo que escribe uso MediatR, y para acceder a la base de datos uso Dapper, con SQL escrito a mano. No me hace falta un ORM grande para cuatro tablas.
Lo importante en tiempo real lo gestiona SignalR. Cuando alguien vota, se une o se va, el servidor avisa a todos los que están en esa partida a la vez. Así los chips de «ha votado» cambian en el momento y los votos se destapan para todos al mismo tiempo, sin que nadie tenga que refrescar nada.
El frontend es una aplicación en Vue 3, con Vuex para el estado, Vue Router para navegar y Axios para las llamadas normales a la API.
Cuando la conexión se cae debido a un despliegue u otro motivo, intenta reconectar con esperas cada vez más largas y, al volver, se une otra vez a la partida con el nombre y el identificador que guarda la sesión. Como los votos están en la base de datos, no se pierde nada por el camino.
Y tiene tests, que siempre se agradecen cuando tocas código con prisa: pruebas unitarias, de repositorios y de funcionalidad, e incluso de los eventos del hub de SignalR. Para que estos corran más rápido usan una base de datos SQLite en memoria.
El despliegue, la parte que más me ha enseñado:
Aquí es donde me llevé más sorpresas. Quería que fuera gratis, y eso condiciona mucho.
La web está en GitHub Pages: cada vez que fusiono un cambio en la rama principal, una acción de GitHub la compila y la publica sola.
La API la probé primero en Fly.io, pero la cuenta gratuita apaga la máquina a los pocos minutos, y con SignalR eso no sirve, porque corta la conexión a los jugadores a media partida. Así que la he movido a Render, en un contenedor Docker con el plan gratuito.
Render, en su versión gratuita tiene un problema: su disco es efímero, y una base de datos en un fichero SQLite se borraría con cada reinicio, que es lo que me sucedía antes. Por eso he cambiado de base de datos. Ahora la aplicación usa PostgreSQL alojado en Neon, también gratuito. El código elige solo el motor: si existe la variable DATABASE_URL usa Postgres, y si no, SQLite, que sigue siendo lo cómodo para desarrollar en local. Para probar en local con Postgres tengo un docker-compose.
Lo que todavía no es perfecto:
Seré sincero: nada es perfecto, y mucho menos esta aplicación, he desplegado la API en Render con el plan gratuito y se nota. Render duerme el servicio tras un rato sin tráfico, y la primera visita después de un parón puede tardar casi un minuto en responder. Para mitigarlo hay un endpoint llamado /health muy ligero que se puede consultar cada pocos minutos, y la web reintenta sola cuando el servidor está despertando. Si el servicio se reinicia a media partida, los jugadores ven el aviso de reconexión durante unos segundos y vuelven a su sitio con sus votos intactos.
Está todo en mi GitHub, con un README que explica cómo ejecutarlo en local. Si lo pruebas con tu equipo, cuéntame qué tal, y si algo no funciona, abre una PR y anímate a solucionarlo.
Os dejo por aquí la URL con el resultado. Espero que os guste!
https://cvigueras.github.io/planing-poker