Tabla de contenidos
- Stack tecnológico
- Requisitos previos
- Configuración e instalación
- Construcción de la función de tarjetas didácticas
- Añadiendo gamificación básica
- Añadiendo un sistema de XP
- Añadiendo clasificaciones
- Añadiendo un sistema de energía
- El resultado
Stack tecnológico
- NextJS 15 (React 19)
- Shadcn/Ui
- Lucide para iconografía
- Motion para animaciones
- HTML5 Audio API para efectos de sonido
- Trophy para gamificación
Requisitos previos
- Una cuenta de Trophy (no te preocupes, la configuraremos sobre la marcha…)
Configuración e instalación
Primero necesitamos crear un nuevo proyecto NextJS:npm:
--force, pero debes elegir la configuración que consideres más adecuada para tus requisitos.
Construcción de la Función de Tarjetas de Estudio
Configuración de Datos de Tarjetas de Estudio
Para los propósitos de este tutorial, vamos a usar algunos tipos simples con un almacén de datos en memoria. En una aplicación de producción probablemente querrás considerar almacenar esta información en una base de datos. Aquí tendremos un tipo muy simple que almacena información sobre cada tarjeta de estudio donde usaremos la propiedadfront para almacenar las preguntas cuyas respuestas el estudiante quiere aprender, y la propiedad back para almacenar las respuestas a cada pregunta:
src/types/flashcard.ts
src/data.ts
Diseño Básico de Tarjetas de Estudio
Con algunos datos básicos configurados, necesitamos agregar una forma para que los usuarios puedan recorrer sus tarjetas de estudio. Para esto usaremos los componentescarousel e card de shadcn/ui, por lo que necesitamos agregarlos a nuestro proyecto:
<Flashcards /> que combina estos elementos en una solución funcional, especificando que podemos pasar cualquier lista de objetos IFlashcard como props
src/app/flashcards.tsx
page.tsx para mostrar nuestro componente <Flashcards />, pasando nuestros datos de tarjetas de estudio de ejemplo:
src/app/page.tsx
Voltear Tarjetas de Estudio
Ahora esto está genial, pero no es muy útil como aplicación de estudio en este momento ya que no hay forma de ver si obtuviste la respuesta correcta. Necesitamos agregar una manera de voltear las tarjetas y verificar nuestra respuesta… Para simplificar esto, primero crearemos un componente<Flashcard /> que será responsable de toda la lógica para cada tarjeta de estudio:
src/app/flashcard.tsx
<Flashcards /> para que en su lugar simplemente renderice una lista de los componentes individuales <Flashcard />:
src/app/flashcards.tsx
- Primero, agregaremos una variable de estado
sideque contendrá el lado actual de la tarjeta que se está mostrando. - A continuación, agregaremos un callback
onClick()al componente<Card />que actualizará el estadosideabackcuando se haga clic si el frente de la tarjeta se está mostrando actualmente. - Finalmente, renderizaremos condicionalmente el texto en el
<Card />según el valor de la variable de estadoside.
src/app/flashcard.tsx
<motion.div /> con una animación de resorte ligera en el eje y para crear el efecto:
src/app/flashcard.tsx
- Asegúrate de que cuando un
<Card />se está volteando, la ‘cara trasera’ no sea visible durante la animación conbackface-visibility: hidden; - Como el componente
<Card />es un hijo del<motion.div />, normalmente aparecería plano cuando su padre rota en 3D. Agregartransform-style: preserve-3d;al<Card />asegura que mantenga su efecto 3D cuando su padre se anima.
src/app/flashcard.module.css
¡Un Error de Volteo!
¡Genial! Nuestro proyecto ahora está empezando a sentirse como una verdadera herramienta de estudio. Sin embargo, los observadores perspicaces (o tal vez no tanto…) notarán que hay un error importante aquí. Cuando volteamos una tarjeta, la respuesta en la parte trasera aparece invertida 😢…motion para literalmente voltear nuestra tarjeta en el eje Y, necesitamos asegurarnos de escribir nuestras respuestas al revés también.
Primero, agregaremos un pequeño fragmento de CSS para manejar la escritura de texto al revés:
src/app/flascard.module.css
src/app/flashcard.tsx
Seguimiento del Progreso
El siguiente paso es agregar interfaz de usuario para mostrar al usuario cuántas tarjetas de estudio ha revisado y cuántas le quedan en el conjunto. Usaremos una barra de progreso simple para lograr esto. Antes de poder comenzar a rastrear este nivel de información, necesitamos configurar el seguimiento de una nueva variable de estado que contenga el índice de la tarjeta que el usuario está viendo actualmente. Usaremos la API del carrusel para conectarnos a esta funcionalidad y mantener nuestra variable de estado actualizada:src/app/flashcards.tsx
progress de shadcn/ui a nuestro proyecto:
Agregando Gamificación Básica
En esta sección agregaremos los siguientes elementos de gamificación al proyecto de tarjetas:- Logros por completar:
- 10 tarjetas
- 50 tarjetas
- 100 tarjetas
- 250 tarjetas
- Racha diaria por completar al menos una tarjeta al día.
- Correos electrónicos automatizados para:
- Logro desbloqueado
- Resúmenes de progreso semanal
Cómo Funciona Trophy
Primero, necesitamos una nueva cuenta de Trophy. Luego podemos comenzar a ensamblar las diversas partes de nuestra experiencia de gamificación. En Trophy, las Métricas representan diferentes interacciones que los usuarios pueden realizar y pueden impulsar funcionalidades como Logros, Rachas y Correos electrónicos. En Trophy rastreamos las interacciones de los usuarios enviando Eventos desde nuestro código a Trophy contra una métrica específica. Cuando se registran eventos para un usuario específico, cualquier logro vinculado a la métrica especificada se desbloqueará si se cumplen los requisitos, las rachas diarias se calcularán automáticamente y se mantendrán actualizadas, se otorgan puntos y las clasificaciones se actualizan. Esto es lo que hace que construir experiencias gamificadas con Trophy sea tan fácil: hace todo el trabajo por ti detrás de escena. Registrar un evento contra una métrica para un usuario específico utiliza la API de eventos de métricas de Trophy, que en la práctica se ve así:Configuración de Trophy
Así es como configuraremos nuestra cuenta de Trophy para nuestra aplicación de estudio:- Primero, configuraremos una métrica Tarjetas Volteadas
- A continuación, configuraremos logros vinculados a esta métrica
- Luego, configuraremos una racha diaria vinculada a esta métrica
- Finalmente, configuraremos secuencias de correo electrónico automatizadas para esta métrica
Crear la métrica
Crear la métrica
Dirígete a la página de métricas de Trophy y crea una nueva métrica, asegurándote de especificar
flashcards-flipped como el key de la métrica. Esto es lo que usaremos para referenciar la métrica en nuestro código al enviar eventos.Crear logros
Crear logros
A continuación, crea un logro para cada uno de los siguientes hitos:
- 10 tarjetas (Elemental)
- 50 tarjetas (Principiante)
- 100 tarjetas (Erudito)
- 250 tarjetas (Experto)

Configurar racha diaria
Configurar racha diaria
A continuación, dirígete a la página de rachas y configura una racha diaria.
Configurar correos electrónicos
Configurar correos electrónicos
Dirígete a la página de correos electrónicos y añade y activa plantillas para los dos tipos de correos que queremos.
- Correos de logro desbloqueado
- Correos de resumen (semanales)
Antes de poder comenzar a enviar correos, necesitarás configurar tu dirección de envío con Trophy. Pero esto puede hacerse más adelante si lo prefieres.
Integración del SDK de Trophy
Primero necesitamos obtener nuestra clave API de la página de integración de Trophy y añadirla como una variable de entorno exclusiva del servidor..env.local
src/app/actions.ts
src/app/flashcards.tsx

Agregando UX de Gamificación
La respuesta a la llamada API que hacemos para rastrear eventos en Trophy nos devuelve útilmente cualquier cambio en el progreso del usuario como resultado de ese evento:Response
- El array
achievementsque es una lista de logros recién desbloqueados como resultado del evento. - El objeto
currentStreakque contiene los datos de racha más actualizados del usuario después de que el evento haya tenido lugar.
- Mostrar una notificación emergente
- Reproducir un efecto de sonido
Notificaciones de Logro Desbloqueado
Primero, mostraremos una notificación cuando los usuarios desbloqueen nuevos logros. Para esto necesitamos agregar el componentesonner de shadcn/ui a nuestro proyecto:
<Toast /> que necesitamos para mostrar las notificaciones y una función de utilidad toast() para activarlas:
src/lib/toast.tsx
page.tsx con el componente principal <Toaster />. Este es el componente de sonner que se encarga de mostrar nuestras notificaciones en la pantalla cuando las activamos:
src/app/page.tsx
<img> simple y omite los patrones remotos.
next.config.ts
<Flashcards /> para leer la respuesta de Trophy y mostrar notificaciones para cualquier logro desbloqueado:
src/app/flashcards.tsx
Notificaciones de Racha Extendida
Usaremos los mismos métodos para mostrar notificaciones similares cuando un usuario extienda su racha. Como hemos configurado una racha diaria en Trophy, esto se activará la primera vez que un usuario vea una tarjeta de estudio cada día. Todo lo que necesitamos hacer es leer la propiedadcurrentStreak.extended de Trophy y manejar la visualización de otro toast con una nueva declaración if:
src/app/flashcards.tsx
Efectos de Sonido
La gamificación se trata, ante todo, de aumentar la retención de usuarios. La mejor manera de lograr esto es hacer que las funciones que construimos sean lo más atractivas posible. Una excelente manera de hacerlo que a menudo se pasa por alto es con efectos de sonido. Aquí agregaremos dos efectos de sonido distintos para cada caso donde mostramos un toast para involucrar aún más al usuario. Esto ayuda a distinguir los diferentes toasts y ayuda a los usuarios a desarrollar una expectativa de lo que significa cada sonido. Para esto utilizaremos la API de Audio HTML5 y usaremos sonidos de freesounds.org. Para cargar los archivos de sonido en nuestra aplicación, crearemos una referencia para cada uno, luego simplemente llamamos al métodoplay() en cada uno cuando queramos reproducir realmente el sonido:
src/app/flashcards.tsx
Mostrar el Progreso de Estudio
La última pieza de interfaz que agregaremos será un diálogo para mostrar el progreso de estudio del usuario, incluyendo su racha y cualquier logro que haya desbloqueado hasta ahora. Primero, agregaremos un par de nuevas acciones de servidor para obtener la racha y los logros del usuario desde Trophy. Como estamos usando una racha diaria aquí, obtendremos los últimos 14 días de datos de racha de Trophy para darnos suficiente información para trabajar en nuestra interfaz:src/app/actions.ts
src/app/page.tsx
<StudyJourney /> que reciba los datos de logros y rachas como props y los renderice de manera atractiva en un diálogo. Antes de añadir esto, necesitamos agregar el componente dialog de shadcn/ui a nuestro proyecto, y mientras lo hacemos, también añadiremos el componente seperator:
dayjs para ayudarnos a mostrar las fechas de manera agradable:
src/app/study-journey.tsx
src/app/page.tsx
Añadiendo un Sistema de XP
Ahora llevemos nuestra plataforma de estudio al siguiente nivel añadiendo un sistema de XP (puntos). Esto dará a los usuarios una sensación de progreso y los recompensará por su actividad de estudio.Configurando Puntos en Trophy
Primero, dirígete a la página de puntos de Trophy y crea un nuevo sistema de puntos. Llamaremos al nuestro “XP” con la clavepoints.
Integrando la API de Puntos
Añade nuevas acciones de servidor para obtener datos de puntos:src/app/actions.ts
Creando un Contexto de Puntos
Para gestionar el estado de puntos en toda la aplicación, crea un contexto de React:src/contexts/UserPointsContext.tsx
Construyendo la Interfaz del Centro de Puntos
Crea un componente de visualización de puntos que muestre la XP del usuario con una animación de números satisfactoria:src/app/user-center/points-center/points-center.tsx
Actualizar Puntos en la Vista de Tarjetas
Finalmente, vuelve a obtener los puntos cada vez que un usuario vea una tarjeta para mostrar actualizaciones de XP en tiempo real:src/app/flashcards.tsx
Agregar Clasificaciones
Nada impulsa el compromiso como una competencia amistosa. Agreguemos una clasificación para mostrar cómo se comparan los usuarios entre sí.Configurar Clasificaciones en Trophy
Ve a la página de clasificaciones de Trophy y crea una nueva clasificación. Crearemos una clasificación diaria con la clavedaily-champions que clasifica a los usuarios por tarjetas vistas.
Integración de API de Clasificación
Agrega acciones de servidor para obtener datos de la clasificación:src/app/actions.ts
Construir la Interfaz de Clasificación
Crea un componente de clasificación que muestre los rankings con paginación:src/app/leaderboard-center/leaderboard-center.tsx
Agregar un Sistema de Energía
Los sistemas de energía (o “vidas”) son una mecánica de retención probada que anima a los usuarios a regresar durante el día. Agreguemos uno a nuestra plataforma de estudio.Configurar Energía en Trophy
El sistema de puntos de Trophy es lo suficientemente flexible para manejar mecánicas de energía. Crea un nuevo sistema de puntos con la claveenergy y configúralo con:
- Un límite máximo (por ejemplo, 5 de energía)
- Reglas de regeneración automática
- Costos por acción (por ejemplo, -1 de energía por sesión de tarjeta)

Integración con la API de energía
Añade acciones de servidor para la gestión de energía:src/app/actions.ts
Crear un contexto de energía
De forma similar a los puntos, crea un contexto para gestionar el estado de energía:src/contexts/UserEnergyContext.tsx
Construir la interfaz de energía
Crea una visualización de energía que muestre la energía restante con indicadores visuales:src/app/energy-center/energy-center.tsx
El resultado
¡Felicidades! Si estás leyendo esto, llegaste al final del tutorial y construiste una plataforma de estudio completamente funcional. Por supuesto, hay mucho más que podríamos hacer con esto, así que aquí tienes algunas ideas:- Persistir las tarjetas de estudio en una base de datos
- Crear múltiples conjuntos de tarjetas para otros temas
- Añadir autenticación
- Permitir que los usuarios creen sus propios conjuntos de tarjetas