Tarot Lune: la ingeniería adentro de una app de tarot

Por qué mi app de tarot y astrología tiene lecturas determinísticas que se comparten como URLs, 218 rutas prerenderizadas y un motor de astronomía clean-room. Un recorrido por las decisiones técnicas detrás de Tarot Lune.


Lancé una app de tarot. Tarot Lune es un sitio bilingüe (inglés y español) de tarot y astrología: lecturas de cartas con el mazo clásico de 1909 ilustrado por Pamela Colman Smith, una carta del día, carta natal, calendario lunar, lecciones para aprender las cartas, un diario, y lecturas para hacer de a dos.

No es el proyecto obvio para un desarrollador de TypeScript, y justo por eso fue divertido. La categoría está dominada por sitios que no cambian hace quince años y por wrappers de chat con IA detrás de un paywall. Construir algo bien hecho ahí terminó siendo más interesante a nivel ingeniería de lo que esperaba. Tres decisiones se destacan.

Las lecturas son URLs determinísticas

Una lectura en Tarot Lune no es una fila en una base de datos. Es un seed. La URL codifica el seed, la tirada y las cartas que elegiste, y el mezclado es una función determinística de ese seed. Abrí la misma URL dentro de diez años y vas a ver exactamente las mismas cartas en las mismas posiciones.

Esa sola decisión pagó por varias cosas. Compartir una lectura es compartir un link, sin guardar nada. La app no tiene forma de "remezclar" a escondidas para venderte algo, y en una categoría donde la confianza es el producto entero, eso importa. Y los tests se vuelven triviales, porque toda lectura es reproducible por construcción.

Astronomía sin la trampa de licencias

Una carta natal necesita posiciones planetarias reales, y la forma estándar de conseguirlas es Swiss Ephemeris, que tiene doble licencia: GPL o una licencia comercial paga. No quería ninguna de las dos restricciones, así que el paquete de astrología es clean-room: las posiciones salen de astronomy-engine (MIT), y los sistemas de casas y el cálculo de aspectos están implementados desde las fórmulas publicadas.

Swiss Ephemeris igual cumple un rol: es el oráculo de test de caja negra. Su salida alimenta un set de golden tests que la implementación clean-room tiene que igualar dentro de una tolerancia. Tenés la confianza de la implementación de referencia sin heredar una línea de su código ni su licencia.

El SEO como decisión de arquitectura

El tarot es una categoría que vive de las búsquedas, así que el sitio está construido tanto para los crawlers como para las personas. Todo se renderiza en el server con TanStack Start, y el build prerenderiza 218 rutas a HTML estático: cada significado de carta, cada lección, cada landing, en los dos idiomas. El inglés vive en la raíz y cada página tiene su gemela en español bajo /es, con hreflang recíproco para que Google entienda el par.

Lo pesado queda afuera del camino: three.js maneja el ritual de sacar cartas, pero solo se carga en esa ruta, así que las páginas que tienen que rankear se mantienen livianas.

Este esquema de URLs me gustó tanto que este blog ahora usa el mismo. Si querés ver la app, sacá una carta. Aunque el tarot no sea lo tuyo, la experiencia de lectura es la parte de la que más orgulloso estoy.