Vale, tengo que ser honesto contigo desde el minuto uno. Este proyecto me está costando bastante más de lo que pensaba. Hytale ya ha salido, la gente está jugando, creando mods, subiendo contenido… y mi web sigue patas arriba.
Te voy a contar algo que no suelo contar. Estoy bastante desmotivado. La semana pasada intenté hacer un poco de promoción en Reddit, a ver si la idea tenía tracción, si a la gente le interesaba… y me borraron el post. Dos veces. En dos subreddits diferentes. Ni siquiera me dejaron validar la idea. Y lo entiendo, el mercado está absolutamente saturado. Hay webs de mods saliendo como setas, todo el mundo quiere ser el próximo CurseForge de Hytale. Pero me hace ilusión sacar esto adelante, así que aquí estamos. Segundo capítulo. Vamos al lío.
El Proyecto y Por Qué Lo Hago Público
Para los que llegáis nuevos a esta serie, os pongo en contexto rápido. Estoy creando desde cero una página web para la comunidad de Hytale. No una web cualquiera, sino una plataforma donde los creadores puedan subir sus mods, paquetes de texturas, mapas, herramientas… todo lo que se te ocurra relacionado con Hytale y encima que ganen dinero dependiendo del tráfico que generen. Si has jugado a Minecraft, es como un CurseForge o un Planet Minecraft (algunos muy viejos recordaréis Planet Minecraft). Pues eso, pero para Hytale.
Y lo estoy documentando todo aquí. ¿Por qué? Pues porque creo que hay muy poco contenido de gente mostrando el proceso REAL de crear un proyecto. No el resultado final bonito, no. Las tripas. Los errores. Las decisiones técnicas. Las frustraciones. Todo. Espero que te sirva de inspiración y que aprendas conmigo en este camino. Porque yo también estoy aprendiendo, esto no es un tutorial donde yo ya sé todo. Es un “vamos a ver cómo sale esto”.
Lo Que Vamos a Ver Hoy
Dicho esto, ¿qué toca hoy? Pues hoy dejamos de pintar monas en el frontend y nos metemos en el barro de verdad. En el capítulo anterior nos peleamos con todo el tema del diseño… Hoy toca construir los cimientos.
Voy a explicarte cómo he diseñado y montado la base de datos con Prisma DB. Y no solo “he usado Prisma”, no. Te voy a enseñar el modelo entero, por qué he tomado cada decisión y cómo funciona esto por dentro. También he integrado logins personalizados con Google, Discord e incluso login por email, para que nadie tenga que recordar otra contraseña más. He puesto captcha porque como no lo ponga, el día que lance esto me van a reventar los bots. Y por último, backups automáticos de la base de datos, que es súper importante y mucha gente lo ignora.
La Base de Datos con Prisma
Empezamos por el corazón de cualquier aplicación: la base de datos. Y aquí he tomado una decisión que te quiero explicar bien. He decidido usar Prisma DB. ¿Qué es Prisma? Bueno, Prisma es lo que se llama un ORM, un Object-Relational Mapping. Pero tranquilo, que no te voy a soltar la chapa teórica. Básicamente, Prisma es una herramienta que nos facilita la vida una barbaridad a la hora de trabajar con bases de datos desde JavaScript o TypeScript.
¿Por qué digo que facilita la vida? Pues porque en lugar de escribir SQL a mano, que ya sabes lo divertido que es eso… defines tu modelo en un lenguaje súper sencillo, ejecutas un comando, y Prisma se encarga de crear las tablas, las relaciones, los tipos de TypeScript… todo. Magia.
Por Qué Prisma y No Otro ORM
Te preguntarás por qué Prisma y no Sequelize, TypeORM, o Drizzle que está tan de moda. Pues mira, te voy a dar mis razones. Primera: la integración con Next.js es brutal. Como estoy usando Next.js para el proyecto, Prisma encaja como un guante. No hay que hacer virguerías para que funcione. Segunda: el lenguaje del schema es súper legible. Ahora te lo enseño y verás que hasta tu abuela podría entender más o menos qué hace cada cosa. Tercera: los tipos automáticos de TypeScript. Esto es oro. Cada vez que cambias el modelo, Prisma te regenera los tipos y tu editor te avisa si estás haciendo algo mal. Adiós a los bugs tontos de “este campo no existe”. Y cuarta: Prisma Studio. Tiene una interfaz gráfica incluida para ver y editar los datos. No es que la use mucho, pero para debugear viene genial.
El Modelo de Base de Datos
Voy a contarte lo interesante. Mi modelo de base de datos me ha quedado bastante grande, más tocho de lo que esperaba inicialmente. Pero te lo voy a explicar a grandes rasgos porque quiero que entiendas la lógica.
La clave de todo este diseño es la tabla Content. He decidido crear una tabla genérica de contenido. ¿Por qué? Porque si piensas en lo que va a tener la web… tenemos mods, mapas, paquetes de texturas, herramientas, servidores… Son muchos tipos de contenido diferentes. La tentación inicial es crear una tabla para cada uno: tabla Mods, tabla Maps, tabla Textures… Pero eso es un infierno de mantener. Cada vez que quieras añadir un campo común, tienes que tocarlo en cinco sitios. Cada vez que quieras añadir un tipo nuevo, tienes que crear una tabla nueva, migrations nuevas…
Entonces, ¿qué he hecho? He creado una tabla padre llamada Content que tiene todos los campos comunes: título, descripción, autor, fecha de creación, número de descargas, valoración… Y luego tiene un campo type que indica si es un mod, un mapa, una textura o lo que sea.
Y de esta tabla Content cuelgan las tablas hijas. Por ejemplo, ContentVersion. Porque claro, un mod no tiene una sola versión. Un mod puede tener la versión 1.0, la 1.1, la 2.0… Y cada versión puede ser compatible con diferentes versiones de Hytale. Entonces tengo una tabla de versiones que está relacionada con el contenido padre.
Luego tengo ContentFile, que son los archivos descargables de cada versión. Porque una versión puede tener varios archivos: el mod en sí, un readme, un archivo de configuración… Tengo ContentImage para las capturas de pantalla y previews. Tengo ContentTag para las etiquetas y categorías. Y tengo ContentRating para las valoraciones de los usuarios.
Las Relaciones Entre Tablas
Y aquí viene lo interesante, las relaciones. Un Content pertenece a un User, que es el creador. Un User puede tener muchos Content. Eso es una relación uno-a-muchos clásica. Pero luego tengo cosas más complejas. Por ejemplo, los favoritos. Un usuario puede marcar como favorito muchos contenidos, y un contenido puede ser favorito de muchos usuarios. Eso es una relación muchos-a-muchos, y Prisma lo gestiona súper bien con una tabla intermedia. Lo mismo con los seguidores. Un usuario puede seguir a otros usuarios. Eso es una relación muchos-a-muchos reflexiva, o sea, de la tabla User consigo misma. Suena lioso pero en Prisma son cuatro líneas.
El Flujo de Trabajo con Prisma
Y esto es lo bonito de Prisma. Imagina que quiero añadir un campo nuevo. Por ejemplo, quiero que los contenidos tengan un campo de “licencia” para indicar si es Creative Commons, MIT, lo que sea. Pues simplemente voy al modelo Content, añado license String? (el interrogante significa que es opcional), y en la terminal ejecuto:
npx prisma db push
Y ya está. Prisma compara el schema con la base de datos, ve que hay un campo nuevo, y lo añade. Sin escribir SQL, sin crear migrations a mano, sin dolores de cabeza. Y automáticamente, el cliente de Prisma en mi código ya tiene el tipo actualizado. Si intento acceder a content.license, TypeScript ya sabe que existe y que es un string opcional. Brutal.
Autenticación con Logins Sociales
Siguiente tema: los usuarios y la autenticación. Y aquí quiero ser claro con algo. Sinceramente, odio registrarme en webs nuevas. De verdad. Cada vez que veo un formulario de registro con email y contraseña, me da una pereza brutal. ¿Otra contraseña más que recordar? ¿Otro email de confirmación? No, gracias. Entonces, si yo lo odio, ¿por qué voy a obligar a mis usuarios a hacerlo? No tiene sentido.
Por eso he implementado lo que se llaman “proveedores de autenticación”. Básicamente, en lugar de crear su propia cuenta, el usuario puede hacer login con una cuenta que ya tiene: Google, Discord, o si realmente quiere, email.
Por Qué Estos Tres Proveedores
Tenemos “Continuar con Google”, “Continuar con Discord”, “Continuar con Email”. ¿Por qué estos tres? Google porque todo el mundo tiene una cuenta de Google. Es el estándar. Discord porque la comunidad de Hytale está muy metida en Discord. Hay servidores de Discord de Hytale con miles de usuarios. Tiene sentido que puedan usar esa cuenta. Email como fallback para los cuatro locos que no quieran usar ninguna de las otras opciones. Pero no es el típico email con contraseña, es un “magic link”. Les llega un email con un enlace, hacen clic, y ya están dentro. Sin contraseñas.
Implementación con Auth.js
Para implementar esto estoy usando una librería que se llama Auth.js, antes conocida como NextAuth. Es el estándar de facto para autenticación en Next.js. Y la configuración es sorprendentemente sencilla. Defines los proveedores. Para Google, necesitas un Client ID y un Client Secret que consigues en la consola de Google Cloud. Para Discord, lo mismo pero en el portal de desarrolladores de Discord. Y para email, configuras un servidor SMTP. Luego Auth.js se encarga de todo el flujo: la redirección a Google, el callback cuando el usuario autoriza, crear la sesión, las cookies… Todo eso que si lo hicieras a mano te llevaría semanas, aquí son unas pocas líneas de configuración.
Y esto conecta con la base de datos, claro. En la tabla User tengo los campos típicos: id, email, nombre, imagen de avatar… Pero también tengo campos específicos para Auth.js: emailVerified para saber si el email está verificado, y la relación con Account que es donde se guardan las conexiones con los proveedores. Un usuario puede tener varias cuentas vinculadas. O sea, puede haber hecho login primero con Google, y luego vincular también su Discord. Así si un día hace login con uno u otro, accede al mismo perfil.
Seguridad con Captcha
Ahora vamos con un tema que mucha gente ignora cuando lanza un proyecto: la seguridad. Y concretamente, los captchas. A los bots de internet les da igual si eres una multinacional o un chaval con un proyecto de fin de semana. Si no tienes captcha, te van a encontrar y te van a spamear.
Entonces, ¿qué he hecho? He puesto captcha en todos los formularios críticos: el login, el registro, la subida de contenido, los comentarios… Estoy usando Cloudflare Turnstile, que es la alternativa de Cloudflare al típico reCAPTCHA de Google. ¿Por qué Turnstile y no reCAPTCHA? Pues porque Turnstile es más respetuoso con la privacidad, no trackea tanto al usuario, y además tiene un tier gratuito muy generoso. Para un proyecto que está empezando, perfecto.
La implementación es sencilla. Tienes un componente de React que renderiza el widget del captcha, y cuando el usuario lo completa, te da un token. Ese token lo envías al backend junto con el formulario, el backend lo verifica con la API de Cloudflare, y si es válido, procesas la petición. Si no, la rechazas. Parece mucho lío pero son literalmente 20 líneas de código. Y te ahorras disgustos.
Backups Automáticos - Lo Más Importante
Y ahora el tema más importante de todo. De verdad. Si solo te quedas con una cosa de hoy, que sea esta: haced backups. Los backups son tu seguro de vida. Si todo se va al garete, puedes recuperar los datos de ayer y seguir adelante. Sin backups, si pasa algo, estás muerto.
¿Qué he configurado yo? Backups automáticos diarios. Cada noche, a las 3 de la mañana cuando no hay casi tráfico, un script se ejecuta automáticamente, hace un dump de la base de datos, lo comprime, y lo sube a un bucket de almacenamiento en la nube. Guardo los últimos 30 días de backups. Así si me doy cuenta de que algo se rompió hace una semana, puedo ir atrás y recuperarlo.
Y lo mejor es que esto, una vez configurado, te olvidas. Se ejecuta solo. No tienes que acordarte de “ay, hoy toca hacer backup”. No. Es automático.
Y un consejo extra que te doy: prueba los backups de vez en cuando. No vale solo con hacerlos. Tienes que asegurarte de que funcionan. Cada mes más o menos, cojo un backup antiguo y lo restauro en un entorno de pruebas. Solo para confirmar que no está corrupto y que si algún día lo necesito de verdad, va a funcionar. Porque nada da más rabia que necesitar un backup y descubrir que estaba mal hecho.
Recapitulación
Bueno, pues así es como va el proyecto. Hoy hemos visto bastante chicha: hemos montado la base de datos con Prisma, con un modelo genérico de contenido que escala bien. Hemos implementado logins sociales para que la gente pueda entrar con Google o Discord sin fricción. Hemos añadido captchas para que los bots no nos revienten. Y hemos configurado backups automáticos para dormir tranquilos.
Y ahora, siendo honesto… ¿Va a triunfar esta web? Pues sinceramente, no lo sé. El mercado está muy saturado. Hay competencia fuerte. Me han baneado posts en Reddit. Pero oye, me hace ilusión terminar esto. Y me hace ilusión que veáis el proceso real. Que esto no es como los vídeos de “monté un SaaS en un fin de semana”. No. Esto lleva tiempo, hay frustración, hay días que no te apetece ni abrir el editor. Y espero que, si tienes tus propios proyectos, esto te sirva de algo. Para inspirarte, para copiar ideas, o simplemente para ver que no estás solo si tu proyecto se atasca.
Si te ha molado, ya sabes, deja un like que eso ayuda mucho. Si quieres seguir viendo cómo avanza el proyecto, suscríbete. Y si tienes ideas o sugerencias de qué le añadirías a una web de Hytale, déjamelo en los comentarios, que los leo todos.
Muchas gracias por estar ahí, dadle caña al código, y nos vemos en el próximo capítulo.



¿Qué te ha parecido?
Déjame tu opinión, pregunta o sugerencia. Los comentarios se sincronizan con GitHub Discussions .