Saltar al contenido
Caso · 04 / 15← Todos los trabajos

Paso

Una ticketera construida desde un handoff de diseño, con cada pantalla medida contra su mock.

Rol
Arquitectura frontend y desarrollo full-stack
Stack
Next.js + React, pnpm + Turborepo, Go, Postgres + Drizzle, Valkey, Playwright + Vitest
Página de evento
Página de eventoEl handoff de diseño como test, no como referencia
(01) El problema

Paso es una ticketera argentina para fans, organizadores, RRPP y gente de puerta. Lo que vende es confianza: cada cargo en su propia línea, un QR que la puerta valida sin internet, reventa oficial con tope y RRPP que cobran por lo que venden. El handoff de diseño tenía 66 artboards y 98 pantallas. Construirlas era la mitad del trabajo. La otra mitad era que siguieran fieles al diseño mientras el producto cambiaba por debajo.

Mi rolLo construí de punta a punta: las dos apps de Next.js, los paquetes compartidos, la API en Go y el pipeline de fidelidad que mide cada pantalla.
(02) ResultadosContados en el código
98pantallas comparadas píxel a píxel contra su mock
73pantallas a menos de 0,5% del diseño en la última corrida completa
32tests end-to-end en Playwright
(03) Arquitectura

Tres decisiones que lo definieron.

  1. 01

    El handoff de diseño como test, no como referencia

    Por qué. Un script corta cada artboard en paneles sueltos. Un manifiesto asocia cada panel con la ruta y el estado que lo implementan, con query strings que fijan cosas como un reloj corriendo. `pnpm visual` saca foto del mock y de la ruta real al ancho del artboard, corre pixelmatch y guarda mock, implementación y diff. Con menos de 0,5% de diferencia, la pantalla cuenta como verificada. Una pantalla sin ruta aparece como pendiente, así la lista no se desfasa.

    El costo. El diff de píxeles es estricto con cosas que nadie nota. Un breakpoint apenas por encima del ancho de un artboard movió cuatro pantallas entre 5% y 8%. Cuando el producto se aparta del mock a propósito, la pantalla queda marcada como decidida, con el motivo escrito, y se sigue midiendo.

  2. 02

    Las reglas de plata escritas dos veces, atadas con vectores dorados

    Por qué. El servicio es el 4% por entrada, con tope de $400. La pantalla lo calcula en un paquete de TypeScript puro. La API en Go calcula lo que se cobra de verdad. Un script genera vectores dorados desde las reglas de TypeScript, incluido el punto exacto donde el tope empieza a mandar, y los tests de Go leen el mismo archivo.

    El costo. Dos implementaciones de la misma cuenta. Los vectores detectan un desacuerdo sólo en los casos que listan, así que cada regla nueva pide vectores nuevos.

  3. 03

    Un QR que la puerta valida sin servidor

    Por qué. Los lugares pierden señal justo cuando la fila es más larga. Cada entrada lleva una firma Ed25519 y rota cada 30 segundos, así la app de puerta la valida en el teléfono. Las entradas escaneadas quedan en IndexedDB y se comparten entre pestañas por BroadcastChannel. Los teléfonos con señal intercambian sus escaneos cada 20 segundos.

    El costo. Dos puertas sin nada de señal pueden aceptar la misma entrada una vez cada una. Cerrar ese hueco pide Bluetooth entre teléfonos, que todavía no está hecho.

(04) GaleríaSeguí scrolleando →
Página de evento
Página de evento · La selección de entradas con el precio final a la vista. Verificada a 0,113% de su mock.
Liquidaciones
Liquidaciones · La liquidación del organizador, línea por línea: ventas, reventa, comisiones de RRPP y costo de cuotas.
Escáner de puerta
Escáner de puerta · La app de puerta, una PWA aparte que valida el QR firmado en el teléfono.
Diff de fidelidad
Diff de fidelidad · Mock, implementación y diff del panel del RRPP. El mock dice $186.500; los datos calculan 94 × $2.000 = $188.000. El diff muestra eso y nada más.
(05) Qué haría después
01Volver a correr la medición completa. El manifiesto ya marca 37 pantallas como decididas y el último reporte cuenta 23, así que los números publicados quedaron atrás del código.
02Construir el respaldo por Bluetooth para que dos puertas sin señal igual vean lo que escaneó la otra.
03Terminar de mudar los dominios que quedan en mock-api a la API en Go, para que Go sea lo único que habla con Postgres.
Próximo proyecto · 05 / 15
Reality Graph →Un grafo de conocimiento interactivo en 3D, en inglés y español
Caso · 04 / 15

Paso

Una ticketera construida desde un handoff de diseño, con cada pantalla medida contra su mock.

Rol
Arquitectura frontend y desarrollo full-stack
Stack
Next.js + React, pnpm + Turborepo, Go, Postgres + Drizzle, Valkey, Playwright + Vitest
Paso
(01) El problema

Paso es una ticketera argentina para fans, organizadores, RRPP y gente de puerta. Lo que vende es confianza: cada cargo en su propia línea, un QR que la puerta valida sin internet, reventa oficial con tope y RRPP que cobran por lo que venden. El handoff de diseño tenía 66 artboards y 98 pantallas. Construirlas era la mitad del trabajo. La otra mitad era que siguieran fieles al diseño mientras el producto cambiaba por debajo.

Mi rolLo construí de punta a punta: las dos apps de Next.js, los paquetes compartidos, la API en Go y el pipeline de fidelidad que mide cada pantalla.
(02) Resultados
98pantallas comparadas píxel a píxel contra su mock
73pantallas a menos de 0,5% del diseño en la última corrida completa
32tests end-to-end en Playwright
(03) Arquitectura

Tres decisiones que lo definieron.

01

El handoff de diseño como test, no como referencia

Por qué. Un script corta cada artboard en paneles sueltos. Un manifiesto asocia cada panel con la ruta y el estado que lo implementan, con query strings que fijan cosas como un reloj corriendo. `pnpm visual` saca foto del mock y de la ruta real al ancho del artboard, corre pixelmatch y guarda mock, implementación y diff. Con menos de 0,5% de diferencia, la pantalla cuenta como verificada. Una pantalla sin ruta aparece como pendiente, así la lista no se desfasa.

El costo. El diff de píxeles es estricto con cosas que nadie nota. Un breakpoint apenas por encima del ancho de un artboard movió cuatro pantallas entre 5% y 8%. Cuando el producto se aparta del mock a propósito, la pantalla queda marcada como decidida, con el motivo escrito, y se sigue midiendo.

02

Las reglas de plata escritas dos veces, atadas con vectores dorados

Por qué. El servicio es el 4% por entrada, con tope de $400. La pantalla lo calcula en un paquete de TypeScript puro. La API en Go calcula lo que se cobra de verdad. Un script genera vectores dorados desde las reglas de TypeScript, incluido el punto exacto donde el tope empieza a mandar, y los tests de Go leen el mismo archivo.

El costo. Dos implementaciones de la misma cuenta. Los vectores detectan un desacuerdo sólo en los casos que listan, así que cada regla nueva pide vectores nuevos.

03

Un QR que la puerta valida sin servidor

Por qué. Los lugares pierden señal justo cuando la fila es más larga. Cada entrada lleva una firma Ed25519 y rota cada 30 segundos, así la app de puerta la valida en el teléfono. Las entradas escaneadas quedan en IndexedDB y se comparten entre pestañas por BroadcastChannel. Los teléfonos con señal intercambian sus escaneos cada 20 segundos.

El costo. Dos puertas sin nada de señal pueden aceptar la misma entrada una vez cada una. Cerrar ese hueco pide Bluetooth entre teléfonos, que todavía no está hecho.

(04) Galería
Página de evento
Página de evento · La selección de entradas con el precio final a la vista. Verificada a 0,113% de su mock.
Liquidaciones
Liquidaciones · La liquidación del organizador, línea por línea: ventas, reventa, comisiones de RRPP y costo de cuotas.
Escáner de puerta
Escáner de puerta · La app de puerta, una PWA aparte que valida el QR firmado en el teléfono.
Diff de fidelidad
Diff de fidelidad · Mock, implementación y diff del panel del RRPP. El mock dice $186.500; los datos calculan 94 × $2.000 = $188.000. El diff muestra eso y nada más.
(05) Qué haría después
01Volver a correr la medición completa. El manifiesto ya marca 37 pantallas como decididas y el último reporte cuenta 23, así que los números publicados quedaron atrás del código.
02Construir el respaldo por Bluetooth para que dos puertas sin señal igual vean lo que escaneó la otra.
03Terminar de mudar los dominios que quedan en mock-api a la API en Go, para que Go sea lo único que habla con Postgres.
Próximo proyectoReality Graph →
Nahuel SantillánES