De Todo App a B2B SaaS con Next.js y Clerk

Rate this content
Bookmark

Si eres como yo, probablemente tengas un millón de ideas para proyectos secundarios, algunas de las cuales incluso podrían hacerte ganar dinero como un micro SaaS, o podrían resultar ser la próxima startup de mil millones de dólares. Pero, ¿cómo sabes cuáles? ¿Cómo pasas de una idea a un producto funcional que puede ser puesto en manos de clientes que pagan sin renunciar a tu trabajo e invirtiendo todo tu tiempo y dinero en ello? ¿Cómo pueden competir tus proyectos secundarios en solitario con las aplicaciones construidas por enormes equipos y grandes empresas?


Construir productos SaaS ricos viene con desafíos técnicos como infraestructura, escalabilidad, disponibilidad, seguridad y subsistemas complicados como autenticación y pagos. Por eso, a menudo son los gigantes tecnológicos ya establecidos quienes pueden construir y operar productos de este tipo de manera razonable. Sin embargo, una nueva generación de devtools está permitiendo a los desarrolladores construir fácilmente soluciones completas que aprovechan la mejor infraestructura en la nube disponible, y ofrecen una experiencia que te permite iterar rápidamente en tus ideas por un bajo costo de $0. Se llevan todos los desafíos técnicos de construir y operar productos de software para que solo tengas que pasar tu tiempo construyendo las características que tus usuarios quieren, dándote una oportunidad razonable de competir contra el mercado al mantenerte increíblemente ágil y receptivo a las necesidades de los usuarios.


En esta masterclass de 3 horas comenzarás con una simple aplicación de gestión de tareas construida con React y Next.js y la convertirás en un producto SaaS completamente funcional y escalable integrando una base de datos escalable (PlanetScale), autenticación multi-tenant (Clerk), y pagos basados en suscripción (Stripe). También aprenderás cómo los principios del desarrollo de software ágil y el diseño impulsado por el dominio pueden ayudarte a construir productos rápidamente y de manera rentable, y competir con las soluciones existentes.

Dev Agrawal
Dev Agrawal
153 min
09 Nov, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

La masterclass se centra en la construcción de una aplicación básica de Todo y su transformación en un producto SaaS completamente funcional utilizando herramientas modernas de desarrollo. Herramientas de desarrollo como Next.js, Vercel, Clerk, PlanetScale y Stripe se utilizan para simplificar el proceso de desarrollo. La masterclass cubre temas como la solución de problemas, la adición de interactividad e integración de bases de datos, la implementación de autenticación y pago, la personalización de los componentes de Clerk, la adición de planes de pago premium con integración de Stripe y la implementación de características multi-tenant. Se anima a los participantes a proporcionar comentarios y compartir sus proyectos construidos con Clerk.

Available in English

1. Introducción a la Masterclass

Short description:

Gracias a todos por estar aquí. La masterclass se llama De una TodoApp a una Aplicación SaaS B2B. Vamos a comenzar con una aplicación muy básica de Next.js que es una aplicación Todo. Y al final de esta masterclass, queremos llegar a un producto SaaS completamente funcional que podamos desplegar y tener usuarios para él. A lo largo de nuestro tiempo como desarrolladores de software, a menudo tenemos ideas o proyectos que enfrentan fricción al intentar construir un software funcional. Las preocupaciones adyacentes, como el despliegue, las bases de datos, la autenticación y los pagos, a menudo se interponen. Sin embargo, hay una nueva generación de herramientas de desarrollo que está cambiando esto. Estas herramientas aprovechan la nube, son confiables y escalables, y optimizan la experiencia del desarrollador.

Gracias a todos por estar aquí. Permítanme compartir rápidamente mi pantalla para que podamos comenzar esta fiesta. La masterclass se llama De una TodoApp a una Aplicación SaaS B2B. Oh, ¿qué está pasando allí? Genial. Permítanme asegurarme de tener el chat aquí. Obviamente hay un código QR aquí, pero realmente no podemos usar códigos QR. No es la mejor opción para transmitir o, digamos, en Zoom. Permítanme copiar y pegar este enlace para el kit de inicio de la masterclass, o el repositorio de inicio de la masterclass aquí en el chat.

Así que básicamente la idea de la masterclass es que vamos a comenzar con una aplicación muy básica de Next.js que es una aplicación Todo. Ni siquiera funciona. Es una aplicación Todo que no funciona. Y al final de esta masterclass, queremos llegar a un producto SaaS completamente funcional que podamos desplegar y tener usuarios para él, incluso miles o millones de usuarios. Esa es la idea que queremos conseguir para la masterclass de hoy. De nuevo, es una masterclass muy práctica. Les animo encarecidamente a que sigan el ritmo. Y la mejor manera de seguir el ritmo es a través del repositorio de inicio. Y antes del repositorio de inicio, asegúrense de tener estas cosas instaladas. Obviamente, si han hecho algún tipo de desarrollo con JavaScript React antes, probablemente ya tengan Git y node.js instalados. Pero lo que sería realmente útil es tener instalado el CLI de Stripe. También voy a mostrar rápidamente cómo se ve el repositorio. Se ve algo así. Permítanme comprobar si pueden ver esto. Sí. Así que, este es el repositorio de GitHub que deberían poder ver desde la aplicación Todo hasta la SaaS B2B. Y esto les muestra cómo clonarlo, entrar en él, y luego. Así que, específicamente voy a estar usando BUN a veces. Es simplemente un reemplazo para npm. Así que, cada vez que vean algo como BUN install, o si me ven escribiendo BUN dev o BUN run un script, simplemente podemos reemplazar eso con npm. De hecho, podría hacerlo con npm. Y realmente asegúrense de que pueden ir a los servicios que vamos a estar usando a lo largo de esta masterclass, y pueden crear una cuenta allí. Y la parte más importante es que asegúrense de tener instalado el CLI de Stripe, porque vamos a estar usando el CLI de Stripe un par de veces a lo largo de esta masterclass. Ahora antes de realmente entrar en la parte práctica, y en este punto voy a cambiar de diapositivas. Así que, asegúrense de tener abierto el repositorio, tienen todo lo que necesitan, o pueden empezar a instalar y configurar el repositorio al lado. Mientras yo rápidamente me presento. Soy dev. Ese es mi nombre. También soy un dev. He estado escribiendo aplicaciones de JavaScript de pila completa durante unos siete años ahora, y actualmente trabajo como defensor del desarrollador en Clerc, que es un patrocinador de React Summit, y Clerc es una solución de gestión de usuarios para React, como vamos a ver pronto en esta masterclass. Y antes de realmente entrar en, como, la parte práctica, quiero transmitir el punto de lo que estamos tratando de lograr hoy. ¿Alguna vez, como desarrollador de software, has tenido esos momentos en los que alguien se acerca con ideas para una nueva aplicación? O, digamos, hey, los tableros Kanban realmente apestan. Quiero algo más sencillo. Quiero una forma más sencilla de hacer la gestión de proyectos. O si tienes tus propias ideas de cómo podría ser una mejor aplicación de planificación de viajes, o ya estás en camino de incluso construir una startup a partir de tu idea, o tal vez incluso has contratado a un equipo y asegurado un poco de financiación, y estás bien encaminado para cambiar el mundo con la mejor aplicación de gestión de tareas que el mundo ha visto, o la próxima generación de plataforma de medios sociales descentralizada, o recién salida de San Francisco, esto es cómo la IA cambiará tu producto de vida. Básicamente, la idea es, ¿alguna vez has tenido, como, muchas de estas grandes ideas de aplicaciones que deseas que existan y que quieres construir? ¿Cuántas de estas ideas llegan a producción? ¿Qué tal un prototipo? ¿Qué tal solo una demo? Tal vez algo que armamos durante el fin de semana, tal vez algo que conseguimos con amigos para el fin de semana, o tal vez vamos a hackatones, y allí estamos tratando de construir algunas cosas. Así que lo que quiero que, lo que quiero que todos piensen es, a lo largo de nuestro tiempo como desarrollador de software, ¿cuántas veces ha pasado eso? Cuando tenemos ideas, o tenemos, o tal vez incluso tenemos proyectos, tenemos startups, pero entonces hay esta especie de fricción inevitable que surge cada vez que intentamos impulsar esto hacia adelante y construir un software funcional a partir de él. Porque a medida que pasamos de la fase de ideación a la izquierda a una fase de software funcional a la derecha, hay muchas cosas como, okay, ¿dónde despliego esto? ¿Cómo despliego esto? Necesito conseguir una base de datos, ¿necesito Docker? La gente está hablando de Lambdas. Todo el mundo está volviendo a Postgres. ¿Cómo añado Authon a esto? Acabo de hackear un tablero de control. No quiero construir perfiles de usuario, invitaciones de organización, integrar con servicios de correo electrónico, asegurarme de que todo esté seguro. Probablemente también vas a estar almacenando algunos datos sensibles. Y si alguna vez quieres cobrar a tus usuarios, ¿cómo gestionas los pagos? ¿Vas a tratar ahora con números de tarjetas de crédito? Hemos oído hablar de algo llamado Stripe. ¿Cómo funciona eso? Así que estas son las ideas de lo que entra en esta sección roja, que son las preocupaciones adyacentes. Estas no son realmente cosas que están relacionadas con la idea, la cosa que realmente quieres construir, pero estas cosas inevitablemente se interponen. Y empiezan a ocupar más y más de nuestro esfuerzo, de nuestro esfuerzo de ingeniería, y eso es lo que realmente hace que ir de la idea a las aplicaciones de trabajo, sea un proceso doloroso. Y por eso a menudo vemos, o a menudo vemos, grandes equipos, grandes empresas que ya tienen un montón de recursos, un montón de expertos en ingeniería, un montón de infraestructura existente. Y porque tienen todo eso, pueden simplemente iniciar una nueva cosa y empezar una nueva aplicación, empezar un nuevo proyecto. Y por eso tenemos grandes empresas que constantemente prueban cosas nuevas. Y se mantienen constantemente en el mercado porque están constantemente experimentando con nuevas ideas con su infraestructura existente. Esto también es por qué no funciona realmente para equipos pequeños. Como si yo y mi amigo nos juntáramos para construir algo, realísticamente, ¿qué tipo de aplicación podemos realmente construir antes de que ahora tengamos que contratar a un montón de más gente para cuidar de estas preocupaciones adyacentes para que podamos convertirlo en un negocio real? Y estas son cosas que a menudo nos impiden ir hasta el final con nuestras ideas y construir aplicaciones reales. Pero de lo que estoy aquí para hablar hoy es de cómo eso ha cambiado, o al menos cómo está cambiando. Porque hay una nueva generación de herramientas de desarrollo que están haciendo esto posible. Estas herramientas tienen algunas características muy únicas. En primer lugar, aprovechan completamente lo que la nube tiene para ofrecer, lo que significa que son confiables, escalables y baratas. Así que no te preocupas por la infraestructura. La segunda cosa es que estas herramientas optimizan para la experiencia del desarrollador, lo que significa que el objetivo es darnos a nosotros como desarrolladores de software capacidades poderosas con una buena experiencia de desarrollador. Así que tienes todo el poder y todos estos sistemas e infraestructuras complejas preconstruidas para ti. Pero no solo te dan capacidades, puedes integrarte con ellos sin problemas y seguir trabajando en tu competencia central. Tu competencia central es la aplicación que estás tratando de construir. Es tu aplicación de planificación de viajes, es tu aplicación de IA, es tu aplicación de gestión de proyectos de próxima generación.

2. Introducción a las Herramientas de Desarrollo y Configuración

Short description:

La nueva generación de herramientas de desarrollo elimina el esfuerzo y el espacio mental dedicado a las preocupaciones adyacentes, permitiendo a los equipos centrarse en su competencia principal. Con estas herramientas, los equipos pequeños pueden construir y operar aplicaciones que sirven a miles o millones de usuarios. Las excusas como la falta de conocimientos o las preocupaciones sobre la escalabilidad ya no son válidas. En esta masterclass, construiremos una aplicación SaaS utilizando Next.js, Vercel, Clerc, PlanetScale y Stripe. Comencemos clonando el repositorio de GitHub e instalando las dependencias.

Esa es tu competencia principal que quieres construir, no lidiar con Kubernetes, estos archivos YAML o configuraciones de webpack o estas APIs REST con horrible documentation. Dedica 10 minutos a ello y ya está, y nunca más pensarás en autenticación o vulnerabilidades o cumplimiento o ataques de bots. Esa es la mentalidad que estas herramientas pueden inculcar. Y veo que la gente sigue llegando. Gracias a todos por asistir. Repositorio de GitHub que hemos mostrado aquí. También está enlazado en el chat. Puedes registrarte para obtener una cuenta para estos. Y también asegúrate de tener node.js y tener instalado el CLI de Stripe.

Bien, entonces, lo que sucede con la nueva generación de herramientas de desarrollo es que realmente eliminan el esfuerzo y el espacio mental que tenemos que dedicar a estas preocupaciones adyacentes. Esto significa que realmente lo único en lo que estás pensando es en tu competencia principal. Es tu idea aquí, es lo que está en verde. Así que lo que eso significa es que los equipos no necesitan ser enormes. No necesitas tener mucha infraestructura existente para empezar a construir aplicaciones reales con este conjunto de herramientas. Puedes tener simplemente un equipo pequeño de tres a cinco personas o incluso 10 personas, 20 personas que pueden construir, operar y soportar un software, una aplicación que potencialmente está sirviendo a miles o millones de usuarios. Y esa es una expectativa completamente realista de tener con estas herramientas porque eso es lo que mucha gente está haciendo hoy en día. De nuevo, la mentalidad en la que esto nos pone es lo que me gusta llamar sin más excusas. Es decir, cuando tengo una idea sólida que creo que realmente va a funcionar o que quiero experimentar con ella, no tengo estas excusas de, bueno, realmente no conozco las bases de datos o sé que esto nunca va a escalar, nunca podré hacerlo escalar, o nunca podré hacer esto lo suficientemente seguro. Si esta es una aplicación de IA que estoy construyendo, tal vez tenga miedo de los bots. Tal vez tenga miedo de que los bots vengan, entren, abusen de tus servicios para obtener créditos gratis. Pero, estas ya no son excusas que tengo porque estas herramientas, esto completamente elimina eso de mí. Así que eso es lo que vamos a hacer hoy. Construyamos una aplicación SaaS con estas herramientas. Vamos a usar Next.js como nuestro framework, vamos a usar Vercel como el host. Vamos a usar Clerc para la gestión de usuarios y autenticación. Vamos a usar PlanetScale para la database y vamos a usar Stripe para todo nuestro flujo de pagos. Y, realmente, eso es todo lo que tengo para las diapositivas de hoy. Y, en este punto, podemos pasar a la parte práctica.

Bien, así que lo que tenemos aquí es el repositorio de GitHub. Vale, tengo preguntas. ¿Necesitaré una cuenta de Stripe y PlanetScale? Definitivamente necesitarás una cuenta de Stripe. El paso de PlanetScale, si quieres, estamos empezando con una database SQLite, así que si quieres seguir con eso durante la duración de la masterclass, puedes hacerlo. Pero una vez que lleguemos al paso de PlanetScale, en esta masterclass, repasaré el paso de crear realmente la cuenta. Así que no necesariamente tienes que crear todas estas cuentas ahora mismo. Ahora mismo, lo más importante es que puedas clonar el repositorio y luego puedes ejecutar NPM install y entonces todos los repositorios deberían estar, todas las dependencias deberían estar disponibles para ti. Necesitarás una cuenta de Stripe porque estamos integrando pagos y puedes tener una cuenta de PlanetScale si quieres conectarte con bases de datos en vivo. Bien, así que mientras se terminan de instalar las dependencias, vamos a familiarizarnos un poco con este código base. Obviamente todo lo importante está dentro de nuestra carpeta SRC. Publica el enlace de Git. Sí, dame un segundo. Aquí. Así que este es el enlace para el repositorio de GitHub. Asegúrate de clonarlo e instalar las dependencias. Y nuestras dependencias están instaladas. Ahora podemos ejecutar NPM run dev y deberíamos ver nuestra aplicación de tareas aquí en la pantalla en un momento. Pero hasta entonces, veamos nuestra aplicación. Tenemos nuestra carpeta SRC y creo que mi ordenador puede estar luchando por recursos en este punto, pero seguiremos adelante. Y dentro de aquí, tenemos una página de inicio y tenemos una página de panel de control. Así que puedes pensar en esta página de inicio como una especie de página de aterrizaje. Estás obteniendo este error, se requiere la URL de la database. Así que lo que puedes hacer en ese caso es que puedes ir a tu archivo dot env. Deberías tener una URL de database por defecto en tu env. Bien, así que en tu archivo dot env, podemos deshacernos de estos dos, pero puedes tener una URL de database igual a esta cadena aquí. Así que file colon db.sqlite. Así que si estás obteniendo el error de que te falta la URL de la database, solo asegúrate de que esto se añade en tu archivo dot env. Voy a pegar eso en el chat. Gracias por señalar eso. Básicamente solo necesitamos apuntar la aplicación hacia el archivo SQLite que se va a utilizar como database. Así que estamos empezando con solo una database SQLite de demostración aquí y puedes ignorar todo lo demás en el entorno por ahora. Así que ahora deberías tener la aplicación funcionando. Avísame si todos han llegado hasta este punto. Y nuestra página de inicio es básicamente como, así que si vas a tu archivo de diseño aquí, tu archivo de diseño en src app layout. Ahora esto tiene algunas cosas que, en cierto sentido, no deberían estar allí. Así que podemos deshacernos de esto rápidamente. Si ves este import de clerk-nextjs, puedes deshacerte de eso. Puedes deshacerte de clerk-provider y user-button de la sección. Vamos a añadir estos de nuevo más tarde, pero ahora mismo si solo estás construyendo nuestra aplicación de tareas no necesitamos eso. Pero lo que sí necesitamos es si vamos a nuestra página de panel de control, en nuestra página principal aquí, tenemos un enlace para ir al panel de control. Y si hacemos clic en él, deberíamos ver, ¿qué está pasando aquí? Dame un segundo. Oh, estoy silenciado.

3. Solucionando Problemas y Añadiendo un Modelo Todo

Short description:

Para solucionar los problemas, crea una nueva rama llamada 'bare' y ejecuta 'npm install'. Luego, ejecuta 'npm run dev' para ver la aplicación básica de tareas. También queremos saber quién usa Next.js con componentes de servidor. Añadamos un modelo para las tareas en el archivo de esquema de Prisma.

Estás en lo correcto. Dame un segundo. Creo que lo que pasó es, sí, creo que lo que pasó fue que esta, la rama principal debía ser una configuración básica, pero terminó teniendo un montón de otras cosas también. Así que voy a crear una nueva rama ahora mismo que no tenga todos estos problemas y podemos cambiar a esa rama. Así que ahora, en tu pantalla de terminal, si puedes hacer git checkout origin/bare, esto debería darte la nueva rama, que ahora es una configuración realmente básica, en lugar de tener todas esas cosas que nos están dando todos estos problemas. Esto es lo que la rama principal debía ser. Pero parece que hubo algunos problemas allí durante la preparación. Pido disculpas por eso. Pero ahora si ejecuto npm install, vamos a intentar esto de nuevo. Y en este punto, no deberíamos tener nada extra. Deberíamos tener solo nuestra aplicación de tareas sin nada sofisticado que pueda romper cosas.

Bien, todavía rompe cosas. ¿Cuál es el problema aquí? Oh, no hay modelos aquí. Eso está bien. npm run db push. Y esto probablemente, mismo encabezado. Bien, eso está bien. Así que ahora tenemos una configuración mucho más básica. De nuevo, todo lo que tienes que hacer es git checkout origin/bare. También voy a poner esto en el chat aquí. Y asegúrate de que no tienes muchos otros cambios aquí. El middleware, sé que eliminar el middleware funciona, pero vamos a añadir el middleware de nuevo en algún momento una vez que empecemos a añadir authentication. Así que intentemos esto una vez más. Tenemos nuestro localhost, tenemos nuestra ruta de índice, que es básicamente nuestra página de inicio. Y luego cuando vamos al panel de control, tenemos una interfaz de usuario muy básica aquí. Así que voy a dar un par de minutos extra para que todos lleguen hasta este punto. Solo asegúrate de estar en la rama bare. Y de haber instalado las dependencias, y puedes ejecutar simplemente npm run dev. Y aquí deberías poder ver nuestra aplicación básica de tareas que no hace nada. Solo tenemos un array, un array de tareas codificado aquí, inicializar el proyecto y crear la aplicación de tareas. Luego tenemos nuestro componente añadir tarea, que es nuestro formulario aquí. Y simplemente estamos recorriendo el array de tareas y renderizando cada componente de tarea. Así que cosas muy familiares de React aquí. Y solo para comprobar, si nos deshacemos de esto, si tenemos un array vacío, deberíamos ver no se encontraron tareas y podemos verificar eso aquí. Genial. Tengo el chat abierto. Por favor, házmelo saber en el chat. ¿Ya lo has bifurcado? No, todavía tendrás bare. Oh, lo has bifurcado. No lo has clonado. Bien. Si lo has bifurcado, todavía puedes tener, creo que todavía puedes acceder a tus ramas. El comando antes de npm run dev es solo un npm install. Así que no necesitas ejecutar el db push. Npm install debería hacerlo automáticamente. Así que solo ejecuta npm install y luego puedes ejecutar npm run dev. Nirav, si todavía estás obteniendo variables de entorno inválidas, una vez más, asegúrate de que simplemente te deshaces de todos los cambios en tu git y estás en la rama bare. Si no estás en la rama bare, entonces podrías seguir teniendo esos problemas. Otra cosa que puedes hacer, si estás usando VS code, puedes hacer clic en este botón aquí que dice descartar todos los cambios. Y puedes descartar todos ellos y luego puedes hacer git checkout origin bare.

Bien. Mientras tenemos más gente intentando configurar esto, quiero saber de todos en el chat cuántas personas usan Next.js o más específicamente el enrutador de la aplicación con los componentes del servidor, porque también vamos a hacer un repaso muy rápido de cómo podemos ser realmente productivos con los componentes del servidor. ¿Next.js con componentes del servidor? Genial. Yo uso React. Next. No realmente. Bien, perfecto. Parece que tenemos un equilibrio decente de usuarios no Next y de componentes del servidor. Así que ahora que estamos en Next.js con Prisma y estamos en un entorno de pila completa, también tenemos una database con nosotros con Prisma. Así que lo primero que podemos hacer ahora mismo es añadir un modelo a nuestra database para nuestras tareas. Así que hagamos eso. Puedes encontrar el archivo de esquema de Prisma aquí en Prisma y schema.prisma. Y añadamos un modelo aquí para una tarea. Así es como añadimos modelos en Prisma. Vamos a tener un ID. Ahora Copilot está haciendo algo de trabajo por mí aquí. Obviamente puedes escribir todo esto o si también tienes Copilot, tienes este dulce autocompletado. Así que nuestras tareas tienen un ID, que es un entero, y podemos decirle a Prisma que es una clave primaria y darle un valor por defecto. También tenemos un título. Eso es un string.

4. Añadiendo Interactividad e Integración de Base de Datos

Short description:

Hemos añadido un nuevo modelo a la base de datos y ahora podemos obtener todos desde ella. Sin embargo, el componente Añadir Todo no tiene la lógica para añadir un todo a la base de datos. Podemos pasar la función Añadir Todo como una prop al componente y definirla en el lado del servidor para que actúe como otro punto final de la API. Esta función actúa como una solicitud de publicación al servidor y se cambia automáticamente a una función que hace el punto final de publicación cuando se pasa al componente React. Esto nos permite añadir todos a la base de datos.

Tenemos una bandera completada que puede ser booleana. Eso va a ser esta casilla de verificación aquí. Y luego podemos simplemente añadir, podemos establecer nuestro creado en y actualizado en que básicamente obtenemos gratis de Prisma. No vamos a utilizar estos dos campos a lo largo de la masterclass, así que puedes sentirte libre de saltártelos, pero los voy a añadir aquí.

Ahora voy a detener mi servidor. Voy a ejecutar npm run DB push. Lo que esto va a hacer es compilar el archivo de esquema, hacer cambios en mi database, mi SQLite database, y luego también tener el cliente TypeScript generado. Así que voy a ejecutar eso npm run DB push. Y una vez que esto esté completo, puedo volver a npm run dev, y tengo mi servidor funcionando. Así que voy a cerrar el archivo de esquema aquí. Voy a refrescar esto, y todo debería seguir funcionando como se esperaba. Realmente no hemos hecho ningún cambio en la aplicación. Sólo hemos añadido un nuevo modelo a la database.

Pero ahora lo que podemos hacer, es en lugar de este array, esta página aquí es algo que se llama un componente de servidor. Si no has utilizado componentes de servidor en ningún momento, puedes pensar en ellos como un punto final de obtención en tu servidor, lo que significa que este componente realmente se ejecuta sólo en el servidor y no en el cliente. Esto no se ejecuta en el navegador, lo que significa que podemos acceder directamente a nuestra database aquí. Podemos decir await DB.todo.findmany, y podemos hacer esto una función asíncrona. Así que ahora esta función se parece menos a un componente React y se parece más a un manejador de solicitudes en un punto final de express o un punto final de API de algún tipo. Sí. Así que puedes pensar en esto como la función que se ejecuta sólo en el servidor, por lo que podemos simplemente async await nuestros data de nuestra database aquí, y podemos renderizarlos como JSX. Así que ahora si lo guardo aquí, lo que va a pasar es que deberías ver no todos encontrados, porque ahora estamos realmente obteniendo estos todos de la database, pero no hay nada allí todavía, así que vemos no todos encontrados. Y esta es sólo una idea muy básica de los componentes del servidor aquí. Vamos a profundizar un poco más en esto. Ahora realmente no tendré alcance o tiempo para explicar muchas cosas de los componentes del servidor a lo largo de esta masterclass, así que muchas veces, si tienes preguntas, de nuevo, siéntete libre de ponerlo en el chat, pero realmente te animaría a que te aguantes, y tal vez podamos charlar sobre ellos después de la masterclass, o puedes visitar la documentación de NextJS.

Pero ahora vamos a añadir algo de interactividad. Ahora mismo si vamos aquí, esto no funciona. Así que si hago clic en añadir, no hace realmente nada. Si hago clic en refrescar, no hay todo, porque no tenemos la lógica para añadir un todo en la database. Así que vamos a nuestro componente Añadir Todo y veamos qué está pasando. Así que esto es un formulario, como se esperaba. Tenemos un campo de entrada aquí para esta entrada, y luego obviamente tenemos el botón que podemos hacer clic, o simplemente podemos pulsar enter. Pero en el manejador de envío, no estamos haciendo realmente nada. Sacamos el valor de los data del formulario. Llamamos a esta función Añadir Todo, pero todo lo que está haciendo es registrarla en la consola. Así que si abro la consola aquí, vamos a moverla a la parte inferior, y puedo añadir esto todo. Si presiono enter, sólo se está registrando en la consola. No está pasando nada más.

Y este componente aquí, porque hemos marcado este archivo como use client, lo que básicamente significa es que estos componentes React son los componentes React que conocemos y amamos. Tenemos hooks aquí. Tenemos manejadores de eventos. Así que estos no son componentes de servidor, son simplemente componentes regulares de React. Pero este archivo de página, este es un componente de servidor, por lo que podemos acceder a la database dentro de él. Así que para ese error, Nelly, asegúrate de que el int, la i se supone que es mayúscula, no minúscula. Así que todos los tipos en un esquema Prisma comienzan con una letra mayúscula. Genial. Bueno, así que este es un componente regular de React. ¿Cómo hacemos que añada algo a una database, nuestro componente Añadir Todo? Así que primero asegurémonos de que este componente Añadir Todo viene como props. Así que definamos algunas props aquí. Y digamos que Añadir Todo, el tipo de la prop Añadir Todo es que toma un string y devuelve una promesa de void. Lo que significa que esta función Añadir Todo, en lugar de ser definida aquí, es ahora algo que estamos pasando a este componente Añadir Todo. Y podemos simplemente llamarlo aquí.

Bueno, así que ahora la función no necesita ser definida en un componente, ahora necesita ser pasada. ¿Cuál es el gran problema? Este componente cliente está siendo renderizado por un componente de servidor, lo que significa, de nuevo, ahora que estamos en la página, estamos en modo de servidor completo. Lo que significa que podemos darle esta función. La función Añadir Todo que acabamos de definir en el cliente, que este componente necesita esta entrada, necesita esta prop. Y podemos definirla en el lado del servidor para que actúe como otro punto final de la API. Así que aquí podemos decir, esperar db.todo.create con este título. Y necesitamos darle el valor por defecto completado de falso. Bueno, ¿qué está pasando aquí? Acabo de hablar de cómo los componentes de servidor pueden ser pensados como un punto final de obtención. Así que cuando haces una solicitud de obtención a un servidor, obtienes un montón de data, o obtienes una página HTML. De manera similar, un componente de servidor es lo que obtienes cuando haces una solicitud de obtención, obtienes alguna interfaz de usuario. Esta función aquí, que también se llama una acción, puedes pensar en ella como una solicitud de publicación al servidor. Ahora una cosa que necesitamos marcar aquí es, llámalo use server. Esta directiva aquí, similar a esta directiva use client, es obviamente para decirle al bundler que esta es una función especial que necesita ser tratada de manera especial. Pero también nos dice como desarrolladores que esta es una función que básicamente es un punto final de publicación en nuestro servidor. No tenemos que adjuntarlo explícitamente a una URL y añadir la solicitud de análisis y hacer todo el material de solicitud de respuesta. Pero ese es el modelo mental. Esta función aquí se va a llamar cuando alguien haga una solicitud de publicación a nuestro servidor. Y luego cuando esta función se pasa a nuestro componente React real, automáticamente va a ser cambiada a una función que hace el punto final de publicación en lugar de nosotros realmente enviando este código al cliente. De nuevo podemos entrar en muchos más detalles sobre esto, pero quiero mantener eso fuera del alcance de la masterclass.

5. Implementando las Funciones de Alternar y Eliminar

Short description:

Podemos crear un to do y revalidar la página del panel de control para actualizar la interfaz de usuario. La función de añadir to do realiza una solicitud HTTP al servidor, que crea el to do en la base de datos. Las funciones de alternar completado y eliminar to do se pueden utilizar para actualizar y eliminar to dos. El componente to do requiere las funciones de alternar completado y eliminar to do como props. La función de alternar completado actualiza el valor completado de un to do en la base de datos. La función de eliminar to do elimina un to do de la base de datos. Se aceptan preguntas en este punto.

Y una vez que la masterclass termine puedo hablar de estas cosas todo el día. Pero de nuevo, la idea aquí es que decimos use server y ahora podemos simplemente crear un to do. Y lo último que necesitamos hacer aquí es que queremos revalidar la ruta. Y vamos a decir panel de control. Esto básicamente le dice a NextJS que oye, toma la página del panel de control y básicamente refrescala o ejecuta el componente de servidor de nuevo, obtén todos los últimos data, y luego actualiza la interfaz de usuario. Así que veamos qué hace esto aquí. Quiero volver aquí. Me desharé de esto. Refrescaré para asegurarme de tener todo el código más reciente. ¿Y puedo añadir to dos? Y si presiono enter, puedo añadirlos. Y si lo refresco, el to do sigue ahí. Hola React Summit. Así que lo que está pasando aquí es que estamos enviando el formulario, que está llamando a esta función props.addToDo. Esta función de añadir to do hará una solicitud HTTP a nuestro servidor y luego nuestro servidor determinará que necesita llamar a esta función específica aquí. Y luego lo hará, lo que creará este to do en nuestra database. Y luego simplemente le decimos a NextJS que vuelva a buscar todos los data que se necesitan para un panel de control slash. Así que sirves en el medio del componente es solo propuesto actualizar eliminar. Correcto. Sí. Así que puedes tener estas funciones use server o estas acciones en tus componentes de servidor o también puedes importarlas en componentes de cliente. Eso es un tema completamente diferente. Y puedes usar estos para hacer cambios en tus data para acciones, para mutaciones. Así que ahora que tenemos añadir to dos, también queremos implementar el alternar y queremos implementar el eliminar. Así que rápidamente también hagamos esos para estos. Primero, tendremos que ir a nuestro componente to do porque así es como estamos renderizando cada una de estas filas individuales. Así que vayamos al componente to do y veamos qué está pasando. Bueno, tenemos una casilla de verificación y tenemos un botón siguiente y tenemos el título. Bastante sencillo. También tenemos estas dos funciones que no están haciendo nada. Así que también asegurémonos de que vienen de las props. Así que vamos a definir una función de alternar completado. Eso va a tomar un objeto to do y va a devolver una promesa de void. También tienes un eliminar to do que va a tomar un objeto to do y devolver una promesa de void. Así que estas son funciones que representan aquí, toma este to do alternar, el valor completado o toma este to do y simplemente elimínalo de la database. Y podemos deshacernos de la declaración. Y aquí podemos ser ya que estamos reestructurando las props, podemos añadir estas dos cosas en y luego todo lo demás, nuestra interfaz de usuario básicamente sigue siendo la misma. Ahora tenemos estas dos props que el componente to do requiere, el alternar completado y la función de eliminar to do. Y si volvemos a nuestra página, podemos hacer una configuración muy similar para pasar esas funciones. Así que bajemos aquí a nuestro componente to do estamos pasando en el objeto to do y la clave. Ahora, todo lo que necesitamos hacer es pasar el alternar completado y el eliminar completado. Sigue en la velocidad que estamos saltando entre los documentos de TypeScript. OK, así que voy a bajar la velocidad justo después de esta parte aquí y permitiré preguntas. Así que con la función de alternar completado de nuevo, solo necesita ser una función asíncrona que toma un objeto to do. Ups, dame un segundo. Y porque de nuevo, queremos tratar esto como un punto final del servidor. Podemos decir use server. Y aquí podemos decir esperar database.to do que actualice. En realidad voy a apagar el copiloto por un segundo por un tiempo que estás aquí. Eso es nuevo. No importa. Vamos a llamar a actualizar. Y vamos a decir donde el to do donde el ID del to do donde el ID del to do en la database es el mismo ID que nos pasaron. Vamos a establecer el completado al valor opuesto de completado. Así es como funciona Prisma. Si usas Prisma o cualquier ítem, esto debería ser relativamente familiar. Y luego una vez más, solo vamos a decir que busque todos los últimos data para el panel de control. De manera similar, en nuestro eliminar to do, podemos decir use server y luego podemos decir un servidor. Y luego podemos decir esperar DB.to do que elimine. ¿Dónde? Ups. Donde el ID del to do es este ID. También necesito asegurarme de que esto es una función asíncrona como esa, y la estamos cerrando y aquí podemos revalidar eso. Panel de control. Bueno, ahora voy a hacer una pausa aquí y dejar que cualquier pregunta, lo siento, dejar que cualquier pregunta fluya. Tenemos nuestro componente de añadir to do y le dimos esta acción que nos permite crear un nuevo to do en la database. Y para un componente regular de to do, le dimos una acción para alternar el valor completado y para eliminar un to do. ¿Y eso funciona? Bueno, sí, funciona. Podemos simplemente marcar aquí y esto se alterna. También puedo simplemente eliminar un to do aquí. También puedo hola mundo.

6. Añadiendo Autenticación y Pago

Short description:

Todavía estamos utilizando React para todo y no hemos introducido ningún nuevo marco de trabajo o proveedores. Tenemos una aplicación de to-do de pila completa que se comunica con una base de datos. Ahora podemos pasar a la autenticación y el pago. Conectar a la base de datos en un componente es seguro ya que solo se ejecuta en el servidor. Si no has podido seguir el ritmo, puedes ponerte al día revisando el paso uno. Ahora añadiremos características más avanzadas y discutiremos las variables de entorno. Queremos desplegar y compartir la aplicación, pero también añadir autenticación. Utilizaremos Clerc para integrar rápidamente la autenticación y crear una lista de to-do privada para cada usuario.

Puedo simplemente añadir nuevos to-dos aquí. Y esto es solo y todavía estamos usando React para todo. Todavía no estamos usando nada, ningún nuevo marco de trabajo o proveedor diferente aquí. Obviamente estamos usando el enrutador de aplicaciones Next.js, pero no estamos usando ningún servicio cloud sofisticado bajo el capó. Esto es solo un servidor web.

Y, ya sabes, si tienen alguna pregunta hasta este punto, pueden hacerme saber. O si a lo largo de esto, a lo largo de añadir todas estas funcionalidades, si te has quedado atrás, puedes detener tu servidor y puedes hacer git checkout. Paso uno, creo. Paso uno, déjame comprobar rápidamente eso. Sí. Así que si haces git checkout paso uno, básicamente estarás al día hasta donde estamos ahora o donde hemos llegado ahora.

¿Necesitamos pasar completado falso? En realidad no. Eso es un buen punto, porque hemos definido que completado tiene el valor falso, un valor predeterminado falso en el esquema, podemos deshacernos de esto. Sí. Así que hemos añadido todas estas acciones. Tenemos una aplicación de to-do de pila completa que se comunica con una database. Y ahora podemos seguir adelante. Básicamente hemos llegado a un punto desde tener una interfaz de usuario básicamente no funcional a una UI que habla todo el camino hasta una database, una aplicación de pila completa. Y continuaremos añadiendo muchas más cosas a lo largo de la masterclass. Así que vamos a seguir adelante y saltar directamente a ello. Así que hablemos de authentication y pago. Y hablaremos de esto un poco más a lo largo de la masterclass. Especialmente se va a poner realmente loco cuando añadamos authentication y sistema de pago aquí.

¿Es seguro conectar a database en el componente? ¿Es seguro conectar a una database en un manejador de API express, porque eso es básicamente lo que es esto. De nuevo, este componente solo se ejecuta en el servidor. Nunca se envía al cliente. Así que si es una API express o una API FASTA, entonces es para un componente react tradicional que se ejecuta en el navegador que habla con el VDOM o tiene esto como básicamente está ejecutándose en el navegador. Pero este componente no se está ejecutando en el navegador. Solo se está ejecutando en el servidor, por eso puedes conectar a la database directamente con Prisma.

Bien, espero que algunos de ustedes estén siguiendo. Y una vez más, si no has podido seguir, puedes simplemente hacer git check out paso uno. Y todo lo que hemos hecho hasta este punto está básicamente completado. Así que tienes tu modelo de database, tienes todas tus acciones ya configuradas. Así que básicamente tienes puedes básicamente saltarte toda la porción de sillas siguientes que acabamos de pasar. Porque ahora podemos seguir adelante al siguiente paso. En realidad voy a hacer eso yo mismo. Vamos a hacer get. O no importa. No voy a correr ese riesgo de nuevo. Pero si alguno de ustedes está saltando al branch del paso uno en lugar de tratar de ponerse al día hasta aquí y si te encuentras con problemas, avísame para que podamos todos llegar al menos al punto del paso uno. Y desde ahí, podemos construir más. Porque si esto fue un poco confuso react next year stuff, ya terminó. No tenemos que lidiar con todo esto a lo largo de la masterclass porque ahora vamos a pasar a añadir cosas más sofisticadas.

Variables de entorno database URL requerida. Asegúrate de tener esta URL de database configurada en tu archivo dot ENV. Database URL equals file DB SQLite. Esto debería estar en tu archivo dot ENV en tu raíz.

Vale, así que ahora digamos que tenemos esta aplicación. Ahora digamos que tenemos esta aplicación. Habla todo el camino hasta la database. Queremos desplegarla. Queremos compartirla con amigos. Queremos pedir a la gente que la pruebe, que la use. Pero tal vez queremos al menos una capa de authentication detrás de ella. No queremos que todo el mundo simplemente lea y escriba desde la misma lista de to-do. Queremos que alguien pueda iniciar sesión y tener su propia lista de to-do privada y así sucesivamente. Así que veamos cuán rápido podemos hacer eso con Clerc. Lo primero que voy a hacer o lo primero que te pediré a todos que hagan es ir a clerc.com y registrarse. Actualmente ya estoy registrado. Así que solo dice panel de control. Pero si salgo de aquí y si vuelvo a clerc.com. Deberías ver iniciar sesión y registrarse así que puedes ir aquí. Puedes hacer clic en registrarte y vamos a integrar Clerc en básicamente ningún tiempo y vas a ver lo fácil que es realmente pasar del punto en el que estamos ahora a este futuro de podemos desplegar esto y podemos empezar a obtener usuarios reales para esto. Así que voy a iniciar sesión con mi cuenta de Google aquí. Voy a hacer clic en mi cuenta de Gmail y eso debería mostrarme este panel de control. Ahora ya tengo un montón de aplicaciones aquí. Pero si estás creando una cuenta nueva en Clerc, básicamente te llevará hacia este flujo de nueva aplicación. Así que aquí podemos darle a esta aplicación un nombre. Llamémosla Proyector para nuestros propósitos hoy porque realmente me gustan las aplicaciones de gestión de tareas y de proyectos. Y puedes ver que es un proyector muy simple.

7. Configurando la Autenticación de Clerc

Short description:

Puedes elegir tu propio nombre para la masterclass y seleccionar los factores de autenticación para tus usuarios. Copia las claves API del panel de control de Clerc y añádelas al archivo .env.local. Configura el middleware de Next.js copiando el código en un archivo middleware.ts e instalando el paquete de Clerc Next.js. Añadir este middleware agrega una capa de autenticación a tu aplicación de Next.js, redirigiendo a los usuarios a la página de inicio de sesión. Puedes definir rutas públicas para excluirlos de la capa de autenticación.

Puedes ver que he elegido este nombre para esta aplicación. De nuevo, siéntete libre de elegir tu propio nombre para la masterclass. A mí simplemente me gusta este nombre. Así que voy a seguir con Proyector. Y aquí puedes seleccionar qué tipo de factores o métodos de authentication quieres permitir a tus usuarios. Simplemente seleccionamos correo electrónico y Google por defecto. Obviamente, puedes desactivarlos si quieres. Si solo quieres Google o si solo quieres dirección de correo electrónico y no quieres lidiar con OAuth. Y vamos a seleccionar ambos por ahora. Pero de nuevo, hay 19 más. Siéntete libre de añadir tantos como quieras. Puedes habilitar todos ellos o puedes habilitar ninguno de ellos. Al menos necesitas uno de ellos, ¿verdad? Y vamos a crear la aplicación.

Entonces, una vez que hayas creado nuestra aplicación en Clerc, vas a estar en esta página donde puedes seleccionar qué marco de trabajo estás utilizando. Next.js está seleccionado por defecto. Y podemos simplemente copiar nuestras claves API desde aquí. Obtendrás una clave publicable y una clave secreta. Oh sí, Clerc.com. Lo siento, debería haber compartido eso. gtps Clerc.com. Ese es el enlace que necesitarás seguir, Clerc.com. Y puedes registrarte para la cuenta allí. Y voy a copiar estas variables desde aquí. Y estas necesitan ir en .env.local. Así que aquí está mi archivo .env.local. Voy a dejar de compartir rápidamente mi pantalla y publicar esos allí. O en realidad, creo que puedo hacerlo en vivo aquí. Eso no debería ser un problema demasiado grande. Así que tengo un montón de diferentes claves aquí. Tengo claves next. Puedes ignorar todo aquí por ahora. Pero voy a reemplazar estas con las claves que acabo de obtener del panel de control de Clerc. Y esas deberían ir en el env.local. También pueden ir en el archivo .env. No importa demasiado. Es más una cuestión de preferencia personal y las convenciones del equipo a las que estás acostumbrado. Bueno, ahora que tenemos nuestro... Ahora que tenemos una instancia de Clerc, una aplicación de Clerc configurada y conectada con nuestra aplicación Next.js, o al menos tenemos las variables de entorno, voy a saltar rápidamente a la documentation para una cosa muy específica. Y es el middleware de Next.js. Ahora Next.js es un poco notorio por tener este tipo de patrón de coincidencia complejo para su middleware. Pero básicamente voy a copiar y pegar esto en el chat aquí. Realmente, todo lo que necesitamos hacer es copiar este pedazo de código. Y luego en nuestra aplicación, podemos ir en nuestra carpeta src, crear un archivo llamado middleware.ts, y simplemente volcar el código aquí. Eso es todo. Y una cosa más que podrías necesitar hacer es asegurarte de tener instalado el paquete Clerc Next.js. Es posible que ya esté instalado porque era parte del package JSON. Pero si no es así, simplemente ve a tu terminal y npm instala en clerc slash Next.js. Una vez más, voy a copiar esto y ponerlo en el chat. Así que asegúrate de haber ejecutado eso. Y una vez que lo hayas ejecutado, puedes hacer esto en tu middleware.

Bien, ¿qué hace añadir este middleware? Veamos. Así que voy a ejecutar npm run dev una vez más. Voy a ir a mi localhost. Y voy a, con un localhost 3000 aquí. Y veamos qué obtenemos aquí. Podríamos obtener algún tipo de error. Ahí vamos. Así que acabamos de ser redirigidos a una pantalla de inicio de sesión. Todo lo que hicimos fue añadir este middleware en con un patrón de coincidencia específico de Next.js. Y configuramos las variables de entorno. No ahí. Configuramos nuestras variables de entorno de Clerc. Podemos ignorar estas por ahora. Y básicamente, toda nuestra aplicación Next.js ahora está sentada detrás de una capa de authentication que está alimentada por este middleware. No importa a qué ruta trate de ir, siempre voy a ser lanzado a la página de inicio de sesión. Ese es el comportamiento predeterminado. Y la razón de eso es porque esta es básicamente una de las formas más rápidas de configurar Auth en tu aplicación. Podemos añadir... Obviamente, no queremos que toda tu aplicación esté siempre detrás de la capa de autenticación. Así que puedes definir rutas públicas aquí.

8. Implementando Autenticación y Gestión de Usuarios

Short description:

El middleware nos permite definir rutas públicas a las que se puede acceder incluso si el usuario no ha iniciado sesión. Esta es una forma rápida y conveniente de agregar autenticación a cualquier aplicación. Clerk realiza un seguimiento automático del destino previsto del usuario antes de ser redirigido a la página de inicio de sesión, lo que permite una experiencia de usuario fluida. Al envolver nuestra aplicación en el proveedor de Clerk y agregar el componente de botón de usuario, podemos integrar fácilmente las funciones de gestión de usuarios. Clerk se encarga de las mejores prácticas y la implementación amigable para el usuario de la autenticación, ahorrando tiempo y esfuerzo a los desarrolladores. Verifique su archivo .env para asegurarse de que la URL de la base de datos esté configurada correctamente y asegúrese de que su fuente de datos esté configurada para SQLite. El siguiente paso es implementar las funciones de gestión de usuarios y mejorar la funcionalidad de la aplicación.

Así que puedo decirle al middleware que la página slash, que va a ser nuestra página de inicio, es en realidad una ruta pública. Lo que significa que incluso si el usuario no ha iniciado sesión, podemos permitirle visitar la ruta pública. Así que voy a guardar eso. Y ahora voy a volver aquí y escribo localhost 3000. Esta vez, no seré llevado a la pantalla de inicio de sesión. Esta vez debería ver mi página de inicio aquí, lo cual hago. Pero si intento ir al tablero, si hago clic en ir al tablero, una vez más seré llevado a la pantalla de inicio de sesión. De nuevo, esta es legítimamente una de las formas más rápidas de agregar authentication a cualquier aplicación. Y si realmente solo quieres concentrarte en construir tu aplicación y no te importa demasiado como construir la mejor authentication y flujo de inicio de sesión y registro, entonces esta es una elección absolutamente válida para una clase de aplicaciones. ¿Es esta pequeña aplicación de la que podrías haber oído hablar, que se llama ChatGPT. Eso realmente utiliza este modelo. ChatGPT no tiene UI de inicio de sesión o registro propio. Solo redirige. Si vas a ChatGPT o chat.openai.com y si haces clic en iniciar sesión, hace básicamente lo mismo donde te redirige a una UI de inicio de sesión alojada o UI de autenticación alojada que está hecha por Auth0. Y aquí lo tenemos funcionando con Clerk. Eso estaba funcionando en, lo pusimos en marcha en cinco minutos. ¿Dónde se creó el archivo del middleware? Esto se creó en la carpeta SRC. Así que SRC y middleware TS, eso es todo. Genial, así que ahora vamos aquí y vamos a iniciar sesión con una cuenta. Tenemos Google habilitado, así que solo inicia sesión con cualquier cuenta de Google que quieras. Y ahora ves que en realidad volvimos al slash dashboard. Y ahora tenemos acceso a la aplicación de to-do, a la que no teníamos acceso cuando estábamos desconectados, simplemente fuimos llevados a la pantalla de inicio de sesión. Y también, en ningún momento, dijimos, no le dijimos a Clerk que, oh, cuando el usuario inicie sesión, envíalos al slash dashboard. No hicimos eso en ningún lugar. Clerk puede realizar un seguimiento automático de a dónde estabas tratando de ir antes de ser llevado a la página de inicio de sesión. Y luego una vez que termines de iniciar sesión, sabe a qué página redirigirte. Estos son pequeños pedazos de user experience que Clerk intenta encapsular e implementar todos estos sin que el desarrollador, sin que nosotros tengamos que pensar en ello. Así que puedes integrar Auth y no tienes que pensar en cuál es la forma más segura o más amigable para la user experience o amigable para el usuario de implementar Auth, porque todo eso es cuidado por Clerk. Y déjame mostrarte un gran ejemplo de eso. Así que vamos a nuestro archivo src app layout.tsx, donde verás el hola allí extraño. Esto es lo que estamos renderizando aquí. Así que este archivo es básicamente lo que tenemos para nuestro encabezado superior aquí. Y lo que podemos hacer, en primer lugar, necesitamos envolver este archivo de diseño raíz en nuestro proveedor de Clerk. Así es como podrías haberme visto quitar inicialmente de nuestra rama. Lo estoy consiguiendo. Prisma client no se inicializó aún, por favor ejecuta Prisma generate. Sí. Así que para eso, tendrás que salir y solo necesitas ejecutar npm run db push. Voy a copiar eso. Así que cada vez que hagas cualquier cambio en el esquema de Prisma, tienes que ejecutar este comando para asegurarte de que tu database y tu cliente están actualizados. Volviendo, volvemos a npm run dev. Y así que aquí simplemente envuelvo mi aplicación en un proveedor de Clerk y luego veamos algo de la verdadera magia de Clerk. Vamos a agregar un componente llamado botón de usuario. Solo, lo vamos a soltar aquí en una aplicación de react. Y esto va a ser importado de Clerk Next.js similar al proveedor de Clerk. Ahora, una vez más, ¿tienes un archivo.env en la raíz de tu proyecto donde tienes configurada la URL de la database? Esto es lo que necesitamos. Esto es lo que está buscando, la URL de la database aquí. Ahora, vamos a copiar eso. Así que acabamos de agregar este botón de usuario aquí. Y vamos a refrescar esta página y ver cómo se ve ahora. Vale. Tienes eso ahí y todavía estás obteniendo el encabezado. Oh, espera. Probablemente, podrías no estar, Oh, si te adelantaste a la rama del paso uno, asegúrate de que tu data source DB dice como SQLite y la URL es esta. Así que asegúrate de que tu data source está de vuelta a SQLite. No debería decir MySQL, debería decir SQLite. Todavía no hemos configurado ninguna base de datos MySQL. Eso lo arregló. Genial. Genial. Así que el siguiente paso que estamos tratando de conseguir aquí es que estamos tratando de implementar tanto del usuario. Estamos tratando de agregar tantos de las características de gestión de usuarios como podamos para que podamos deshacernos de. Renombra env ejemplo. Sí. Así que eso es básicamente lo mismo, que es asegurarte de que tu archivo.env tiene esta URL de la database. Pero también necesitas asegurarte de que si estás en una rama diferente, asegúrate de que tu data source realmente dice SQLite y no MySQL. Y no tienes nada más aquí en tu definición de data source. Veamos qué añadió el botón de usuario aquí. Lo estoy ejecutando en Chrome, así que probablemente puedes ver la influencia aquí. Mucha de nuestra, algo de nuestra UI está ciertamente inspirada en Google porque ese es el tipo de calidad que estamos tratando de lograr y entregar a los desarrolladores.

9. Perfil de Usuario de Clerk y Funcionalidad Preconstruida

Short description:

El componente de perfil de usuario en Clerk proporciona una interfaz preconstruida altamente detallada para la gestión de cuentas de usuario. Simplemente agregando el componente de botón de usuario, los desarrolladores pueden dar a los usuarios acceso a todo su perfil, incluyendo la capacidad de cambiar su nombre, imagen, direcciones de correo electrónico, cuentas conectadas, contraseñas y ver dispositivos activos. La funcionalidad preconstruida de Clerk permite a los desarrolladores centrarse en su competencia principal, construir la aplicación To-Do.

Pero si hago clic aquí, verás que hay una opción de gestionar cuenta y una de cerrar sesión. Y gestionar cuenta, básicamente abre uno de nuestros componentes preconstruidos altamente detallados, que es este perfil de usuario. Todo lo que tuve que hacer como desarrollador fue agregar este único componente aquí, el botón de usuario. Y el usuario ahora tiene acceso a todo su perfil. Pueden cambiar su nombre, cambiar su imagen. Pueden cambiar sus direcciones de correo electrónico. Pueden agregar más cuentas conectadas. Pueden cambiar sus contraseñas desde aquí. E incluso puedo ver desde qué dispositivos he iniciado sesión. Así que ahora mismo, este es el único dispositivo desde el que he iniciado sesión. Pero si he iniciado sesión en esta cuenta en esta aplicación desde varios dispositivos diferentes, vería todos ellos aquí en mis dispositivos activos, y puedo cerrar sesión en ellos de forma remota en cualquier momento. También puedo simplemente eliminar mi cuenta desde aquí. Y básicamente, toda esta funcionalidad estaba disponible para el usuario sin que el desarrollador tuviera que hacer nada, sin que nosotros como desarrolladores hiciéramos nada más que agregar este único botón aquí. Y verás que esto es un patrón siempre que estés usando Clerk, donde mucha de la funcionalidad de authentication o interfaz que necesitas ya está ahí, completamente preconstruida para ti, para que puedas pasar a construir tu competencia principal, que en este caso es la aplicación To-Do. Así que volvamos a la aplicación To-Do.

10. Implementando Autenticación y Autorización

Short description:

Necesitamos solucionar el problema de tener la misma lista de To-Do para todos los usuarios e implementar una autenticación y autorización adecuadas en nuestras aplicaciones. Para hacer esto, añadiremos un campo de ID de usuario al modelo To-Do en nuestro esquema. También actualizaremos la función Añadir To-Do para incluir el ID de usuario del usuario que ha iniciado sesión actualmente. Esto se puede hacer utilizando la función Auth de clerk-next.js. Al implementar estos cambios, nos aseguraremos de que cada usuario tenga su propia lista de To-Do única.

Ahora mismo, tenemos exactamente la misma lista de To-Do's que estamos mostrando a todos. Si cierro sesión aquí, y si inicio sesión con una cuenta diferente, digamos que voy a iniciar sesión con mi cuenta de Clerk esta vez. Ahora la foto de perfil de esas dos cuentas es la misma, por lo que podría ser un poco confuso. Pero si ahora, ahora si voy a un tablero, y si digo, hola desde Clerk, es la misma lista de To-Do a la que todos estamos añadiendo. Incluso puedo alternar y eliminar To-Do's que no creé, que fueron creados con una cuenta diferente. Así que vamos a solucionar eso. Asegurémonos de tener una adecuada authentication y autorización en nuestras aplicaciones.

Entonces, la forma de hacer eso es, primero intentemos llevar un registro de qué ID de usuario está creando un To-Do. Así que volvamos a nuestro esquema. Tenemos nuestro modelo To-Do aquí. Es todo lo mismo que acabamos de añadirle, pero ahora también necesitamos añadir un ID de usuario. Así que este es el usuario que creó este To-Do. Esto va a ser String, y podemos hacer esto opcional por ahora. Así que hemos añadido este campo a nuestro esquema, y ahora vamos a necesitar cerrar nuestro servidor, npm run db push, para asegurarnos de que las actualizaciones del esquema se propaguen, y podemos ejecutar npm run dev de nuevo.

Entonces, lo que eso nos permitió hacer, hasta ahora es que nuestra gente se puso al día. Añadimos nuestro componente de botón de usuario aquí. Espero que hayas podido añadir el botón de usuario y el middleware también, y añadimos este ID de usuario al modelo. Bien, entonces lo próximo que vamos a hacer aquí es que ahora que podemos añadir un ID de usuario cuando creamos un To-Do, podemos especificarlo aquí. Así que tenemos una función Añadir To-Do donde estamos añadiendo una nueva entrada a una database, y ahora necesitamos de alguna manera obtener el usuario, obtener el ID del usuario que ha iniciado sesión actualmente en este momento, ¿verdad? Entonces, ¿cómo hacemos eso? Bueno, esta es una función de uso del servidor, lo que básicamente significa que es como el endpoint de post. Y siempre que tenemos un endpoint en el servidor, ese endpoint es responsable de hacer su authentication, averiguar cuál es el ID de usuario del usuario que ha iniciado sesión actualmente. Y la forma en que podemos hacer esto aquí, solo queremos obtener el ID de usuario de algo llamado Auth, y eso es literalmente tan fácil como parece. Importamos la función Auth de clerk-next.js. Solo vamos a llamarla, y nos va a dar el sujeto que tiene el ID de usuario, y luego podemos pasar eso cuando estamos creando nuestro To-Do. Eso es prácticamente todo.

11. Personalizando los Componentes de Clerk

Short description:

Los componentes de Clerk son altamente personalizables, permitiéndote modificar elementos, estilos, variables y más. Puedes usar CSS, CSS personalizado, soluciones CSS y JS, o clases tailwind. Clerk proporciona componentes preconstruidos y una interfaz de usuario alojada para una configuración rápida, pero también permite una personalización extensa. Hay documentación dedicada disponible para construir tus propios componentes de flujo de autenticación utilizando los hooks de Clerk.

Tengo una pregunta sobre cuán personalizables son esos componentes de Clerk. Son muy personalizables. Así que gracias por hacer esta pregunta porque olvidé mencionarlo. Con estos componentes de Clerk, puedes modificar muchas cosas. Puedes seleccionar tipos individuales de elementos y darles un estilo personalizado. Puedes cambiar cualquiera de estas variables. Puedes tener CSS, puedes tener un CSS personalizado o soluciones CSS y JS, o puedes usar clases tailwind. Así que hay muchas formas diferentes de personalizar estos componentes. Y también tenemos documentation dedicada sobre cómo puedes construir tus propios componentes de flujo de autenticación a partir de nuestros hooks. Así que, Clerk tiene todo el espectro de opciones allí. Tenemos los componentes preconstruidos. Tenemos la interfaz de usuario alojada. Así que si quieres empezar a funcionar y realmente, en este momento, te importa mucho el aspecto y la sensación de tu aplicación. Si te importan más las características, puedes empezar con el portal de cuentas, la interfaz de usuario alojada y simplemente construir tus características. Pero tan pronto como tengas que empezar a pensar en el aspecto general y la sensación de tu aplicación, puedes empezar a personalizar o puedes empezar a crear la tuya propia.

12. Añadiendo un Plan de Pago Premium

Short description:

Ahora estamos completamente autenticados con Clerk, permitiendo que cada usuario tenga su propia lista de tareas pendientes. Las APIs son seguras, y los usuarios solo pueden alternar y eliminar sus propias tareas pendientes. El precio de Clerk es generoso, con un nivel gratuito que soporta hasta 5.000 usuarios activos mensuales. Ahora estamos listos para pasar a añadir un plan de pago premium para nuestra aplicación.

Ya no estamos pasando fallas completadas. De nuevo, como puedo pasar eso. Básicamente, como puedes pasar, ups, puedes pasar eso si quieres. Realmente no hace nada porque el esquema hace exactamente lo mismo. Así que por simplicidad, no voy a pasar eso aquí, pero puedo pasar el ID del usuario. Así que vamos a pasar el cursor sobre el ID del usuario y podemos ver que puede ser una cadena o puede ser nulo. Una cadena significa que, sí, el usuario está conectado. Aquí está el ID. Nulo básicamente significa que el usuario no está conectado. Así que deberíamos tener una comprobación aquí que diga si el ID del usuario no existe, solo queremos, vamos a lanzar un error. Lanza un nuevo error debe estar conectado. Ahora estoy lanzando un error aquí por simplicidad. Si estás construyendo, si idealmente quieres un manejo de errores mucho mejor, quieres un mejor feedback de la interfaz de usuario, pero de nuevo, por ahora solo voy a lanzar un error aquí y voy a confiar en que cuando ustedes tomen esta masterclass para aplicaciones reales, pueden implementar un poco de lógica de manejo de errores. Así que volvamos aquí y digamos en realidad hola desde Clerk. Así que ahora estamos añadiendo esto después. Así que ahora que hemos actualizado nuestra lógica para también tener en cuenta el ID del usuario, podemos decir en realidad hola desde Clerk. Puede que necesite refrescar esto. Dame un segundo. Bien. Deshagámonos de ambos. Y así ahora nuestra tarea está completamente vacía. Hola desde Clerk de nuevo. Así que esta es una tarea que he añadido con mi cuenta de Clerk, devatclerk.dev. Así que ahora vamos a cerrar sesión. Y ahora voy a iniciar sesión con mi cuenta de Gmail aquí. Y lo primero que voy a ver es esa misma tarea. Así que lo único que hemos hecho hasta ahora es que cuando creamos una tarea, tenemos en cuenta quién la creó, lo que significa que ahora es tan simple como añadir una cláusula where aquí que simplemente va a decir ID del usuario. En realidad, voy a copiar estas dos líneas de aquí, y voy a hacer esto. Así que verás que la función de autenticación funciona exactamente igual tanto en un componente de servidor como en una acción de servidor. Así que simplemente llamas a la función de autenticación y obtienes el ID del usuario que está actualmente conectado que está tratando de hacer esta solicitud o bien obtener data de un componente de servidor o desencadenar la acción del servidor para cambiar algo en la database. Así que cuando estamos renderizando esta página, simplemente vamos a comprobar el ID del usuario y vamos a pasar eso en nuestro find many. Así que si, ups, si guardo esto, debería ver esto desaparecer y puedo decir, hola desde dev. Y voy a ver esta tarea, pero ahora ya no estoy viendo la tarea que fue creada por el otro usuario. Ahora por un segundo, vamos a comentar esto y puedo ver esta tarea de nuevo, pero también puedo alternarla. No debería poder alternar estas tareas porque todos estos endpoints también deben estar protegidos por autenticación. Así que también vamos a añadir esta función aquí tanto en toggleCompleted como en deleteToDo. Y luego podemos simplemente añadir el ID del usuario en la cláusula where para ambas mutaciones. Así que voy a guardar esto. Y si vuelvo aquí de nuevo, si intento alternar esta tarea de Clerk, voy a ver un error y eso en realidad no va a suceder. Una vez más, tengo un manejo de errores terrible aquí, lo que significa que tengo un manejo de errores inexistente aquí. Pero si tuviéramos un mejor manejo de errores, esto resultaría en algún tipo de mensaje de la interfaz de usuario que dice que no estás autorizado para hacer eso. Así que ahora todas nuestras APIs están completamente seguras. Solo estamos permitidos para alternar las tareas que hemos creado. Y solo estamos permitidos para eliminar las tareas que hemos creado, como eso. Y finalmente, podemos descomentar esta parte para que solo estemos permitidos para ver las tareas que hemos creado. Hola, React Summit. Hola, la nación de IT. Así que creé estos con mi cuenta de Gmail, pero las otras tareas no son visibles para mí. Así que así, solo capturando el ID del usuario de la función de autenticación y asegurándonos de que es parte de nuestras consultas a la database, ahora tenemos una aplicación completamente autenticada donde cada usuario tiene su propia lista de tareas pendientes en las que pueden operar. Ya no tenemos una lista compartida. Tenemos authentication con Clerk. Así que tenemos todas las características. Tenemos inicio de sesión con Google, inicio de sesión con contraseña de correo electrónico. Puedes integrarte con SAML si quieres. Así que básicamente, nunca tienes que pensar en cómo implementar la gestión de usuarios y la authentication encima de ella. ¿Cómo es el precio en Clerk? Esa es una gran pregunta. Actualmente, obtienes alrededor de 5.000 usuarios, 5.000 usuarios activos mensuales en el nivel gratuito. Ese número va a subir muy pronto. Y una vez más, cada servicio del que estamos hablando en esta masterclass, tienen niveles gratuitos muy generosos porque la idea completa es que realmente no debería haber ninguna barrera entre pasar de una idea a un software funcional y con cientos o tal vez incluso miles de usuarios que están dispuestos a pagar por ese software, por lo que todo lo que hemos elegido hoy tiene un nivel gratuito muy generoso, incluyendo Clerk, incluyendo Vercel, incluyendo PlanetScale y todo lo demás. Pero por supuesto, si quieres más información allí, puedes consultar en nuestro sitio web, clerk.com, que tiene todos los detalles específicos sobre los precios. Pero una vez más, van a cambiar y bajar muy pronto. Así que espero que todos hayan llegado hasta este punto. Si no, como antes, creo que también tengo otra rama llamada Paso 2, que debería llevarte hasta este punto o tal vez incluso Paso 3. Dame un segundo y déjame verificar eso. Paso 3, bien. Así que de nuevo, si hasta este punto en cualquier momento has sido incapaz de seguir el ritmo y si te has perdido en algún momento, no dudes en consultar el Paso 3 y eso debería llevarte exactamente al mismo punto donde estoy yo ahora mismo. Y voy a dar a todos dos minutos más y luego vamos a pasar rápidamente a añadir un plan de pago premium para esto. Así que lo que vamos a hacer a continuación, ahora mismo, puedes crear tantas tareas pendientes aquí como quieras. Cualquier usuario puede iniciar sesión en esta aplicación y crear tantas tareas pendientes como quiera. Así que lo siguiente que queremos hacer es, digamos que mi idea de aplicación de tareas pendientes o cualquier idea de aplicación en la que esté trabajando se populariza y ahora quiero asegurarme de que puedo cobrar a los usuarios por ella y así poder construir tal vez un modelo de negocio sostenible o una empresa sostenible encima de ella.

13. Añadiendo Niveles Gratuitos y Pro con Integración de Stripe

Short description:

Para implementar un modelo de negocio donde los usuarios gratuitos pueden crear solo cinco tareas pendientes y los usuarios pagados pueden crear 10 tareas pendientes, necesitamos añadir un nivel gratuito y un nivel pro a nuestra aplicación de tareas pendientes. Utilizaremos Stripe CLI para recibir webhooks y manejar la información de pago. Incluso si no puedes instalar Stripe CLI, aún puedes seguir con la programación y la configuración. Ahora implementemos la lógica para verificar la suscripción de pago del usuario y el número de tareas pendientes que pueden crear. Al llamar a la función 'tareas pendientes restantes', podemos determinar si el usuario tiene suficientes créditos para añadir más tareas pendientes. Si no, se lanzará un error. La función también cuenta el número de tareas pendientes creadas por el usuario y lo resta del máximo permitido de tareas pendientes en el plan gratuito. Esto asegura que los usuarios estén restringidos a los límites especificados. Puedes ver las tareas pendientes restantes mostradas en la aplicación. Intenta añadir más tareas pendientes y observa el mensaje de error cuando se alcanza el límite.

O incluso si no es sostenible, solo quiero ver si la gente está dispuesta a pagar por ello ahora mismo para que pueda solicitar financiación o tener una mejor idea de lo que se supone que debo construir. Así que el próximo paso será añadir un nivel gratuito y un nivel pro a nuestra aplicación de tareas pendientes. Así que en el nivel gratuito, digamos que solo puedes crear cinco tareas pendientes y si quieres ir más allá de eso, puedes obtener el nivel pro y en el nivel pro, puedes crear 10 tareas pendientes. Obviamente, los números son muy poco realistas aquí porque el punto no es llegar a con un modelo de negocio de esta masterclass. El punto de esta masterclass es que una vez que tienes, una vez que puedes llegar a un modelo de negocio como ese, ¿cómo lo implementas? ¿Cómo implementas algo como solo cinco tareas pendientes para usuarios gratuitos y 10 tareas pendientes para usuarios pagados? Así que eso va a ser divertido de implementar. Así que estoy emocionado por esto. Espero que todos estén emocionados por esto y por eso quiero asegurarme de que todos están al día hasta este punto.

Stripe CLI sería muy útil para recibir webhooks o básicamente para que Stripe nos diga que hey, esta persona ha terminado su pago. Haz lo que quieras con eso. Como añadir el procesamiento adicional que queremos hacer. Podemos encargarnos de eso después de que Stripe nos dé esa información. Así que para eso, vamos a necesitar Stripe CLI. Literalmente puedes buscar Stripe CLI aquí y obtendrás instrucciones sobre cómo instalarlo. Si tienes brew, es muy fácil. Puedes simplemente instalar Stripe CLI con brew. Si estás en un entorno Linux, puedes instalarlo de nuevo a través de CLI. Y obviamente hay instrucciones para hacer todo lo demás aquí. Pero incluso si no puedes instalar Stripe CLI hoy, aún puedes seguir con toda la programación que estamos haciendo o toda la configuración que estamos haciendo para esto y eso todavía será muy valioso para ti, incluso si no puedes probarlo completamente en tu entorno local. Una vez más, las masterclasses están grabadas. Así que les animo a todos a repasarla de nuevo si es posible para que puedan seguir construyendo este tipo de aplicaciones. Natasha, muchas gracias por añadir ese enlace allí. La versión de Xcode del ordenador es demasiado antigua y el ordenador es demasiado antiguo para actualizar. Lamento oír eso. Así que veamos cómo se ve la integración de Stripe.

Lo primero que voy a hacer es digamos que podemos añadir una función aquí que diga función puede añadir tareas pendientes. Y dame un segundo para comprobar rápidamente algo al lado. Estoy totalmente haciendo trampa al tener una versión completamente construida de esta aplicación ya en mi segundo monitor. Bien, llamemos a esta función tareas pendientes restantes. Ahora esta es una función que digamos que vamos a llamar cuando estamos creando una nueva tarea pendiente. Así que esto solo va a devolver una promesa. Una promesa de número. Lo que significa que aquí vamos a const restantes igual a await tareas pendientes restantes. Y básicamente vamos a decir que si restantes es menor que uno o si es igual a cero entonces queremos lanzar un nuevo error. Has agotado tu límite o créditos. Ups, créditos. Así que básicamente cada vez que estás añadiendo un nuevo componente de tarea pendiente aquí, vamos a comprobar si tienes algún tipo de crédito o saldo para poder crear más tareas pendientes. Y si no, vamos a lanzar un error. Así que esta función es básicamente donde nuestra lógica para comprobar la suscripción de pago o cuántas tareas pendientes ya tienen y cuántas más están permitidas para crear va a entrar. Así que averigüemos quién es el usuario actual por ahora. Así que de nuevo, vamos a llamar a auth y vamos a obtener el ID del usuario. Luego vamos a obtener el recuento de tareas pendientes que va a, necesito asegurarme de que esta es una función async. Vaya, mi ordenador está lento hoy. Así que esta es una función async tareas pendientes restantes. Vamos a decir await db.to-do.count. Y vamos a contar todas las tareas pendientes que han sido creadas por este ID de usuario. Y digamos que en el plan gratuito, solo queremos que la gente cree cinco tareas pendientes. Así que vamos a devolver cinco menos el recuento de tareas pendientes. Así que si no tengo ninguna tarea pendiente en la database, esto va a ser cero y la salida de esta función va a ser cinco. Incluso puedo deshacerme de esta anotación de aquí. Así que veamos cómo funciona esto. Voy a entrar aquí, añadir uno. Oh, necesito ejecutar esto aquí, npm run dev. Y ahora puedo refrescar esto. Ahí vamos. Vamos a añadir un uno, dos, y un tres. Así que ahora tengo cinco tareas pendientes aquí. Si intento añadir una más, vamos a recibir un error. Así que en realidad no tenemos más formas. No es posible añadir una sexta tarea pendiente en esta aplicación. Así que ahora he sido restringido a solo ser capaz de crear cinco tareas pendientes. Y podemos hacer esta información un poco más clara añadiendo algún mensaje aquí. Así que vamos a añadir un dev aquí. Y aquí, digamos await tareas pendientes restantes, y podemos decir tareas pendientes restantes. Y ahora deberíamos ver cero tareas pendientes restantes aquí. Si me deshago de esto, veo una tarea pendiente restante. O si me deshago de todas ellas, ahora tengo cinco tareas pendientes restantes. También voy a añadir un poco de padding a esto para que no se sienta tan claustrofóbico. Ahí. Un poco más en el eje X. Genial.

14. Configurando la Integración de Pagos con Stripe

Short description:

Para integrar el pago con Stripe, necesitamos crear una cuenta de Stripe y obtener las claves API. La clave publicable se puede enviar al cliente, mientras que la clave secreta debe permanecer confidencial. Después de configurar las variables de entorno, creamos un componente de botón de actualización y lo renderizamos en la página. Al hacer clic en el botón, se indicará la intención del usuario de actualizar al plan Pro y se le redirigirá a la interfaz de autenticación.

Vale. Lo siento. Las cosas con relleno me parecen un poco claustrofóbicas. ¿Cómo te deshaces de ellas? ¿Deshacerse de qué exactamente? ¿Las tareas pendientes? Nos deshacemos de ellas usando esta función de eliminar tareas pendientes, nuestra acción de eliminar tareas pendientes que ya hemos definido. Así que puedo añadir una, dos, tres, cuatro, y esto siempre me mostrará cuántas tareas pendientes me quedan porque está usando la misma función exacta. Así que ahora lo que necesitamos hacer aquí es de alguna manera averiguar si este usuario tiene un plan de pago, si han pagado por la aplicación para que tengan un nivel superior o deberían tener acceso a 10 tareas pendientes en lugar de cinco.

No veo una forma de eliminarlas en la interfaz de usuario. Solo tienes que pasar el ratón sobre ellas. Así que el botón X, tienes que pasar el ratón sobre ellas para que aparezca. Debería estar por aquí. Ese es el botón X. Sí. Entonces, ¿cómo averiguamos si este usuario ha pagado o no? Bueno, no tenemos ninguna integración de pago. Primero construyamos eso. Para esto, vamos a ir a stripe.com. Lo voy a conectar aquí. Y si ya tienes una cuenta, eso es genial. Si no, ahora es tu momento para crear una. Así que puedes entrar aquí. Yo ya tengo una. Voy a usar mis credenciales de cuenta existentes aquí. Voy a continuar. Una vez que estés allí, deberías ver este panel de control aquí. Estoy en modo de prueba aquí. Si quiero acceder a los datos en vivo, si quiero poner realmente algo en producción y ganar dinero con ello, necesitaré activar mi cuenta y proporcionar detalles de negocio. ¿Cuál es el nombre de mi empresa? ¿Cuál es mi cuenta bancaria? Cosas así. Pero para los propósitos de esta masterclass, queremos seguir estando en modo de prueba. Así que aquí podemos hacer clic, una vez que estés aquí, una vez que veas una pantalla como esta, puedes hacer clic en desarrolladores y podemos ir a las claves API. Así que voy a hacer una pausa aquí. Voy a dejar que todos se pongan al día con los desarrolladores de Stripe y las claves API. Házmelo saber dónde estáis, ¿ya habéis creado vuestra cuenta de Stripe o todavía estáis creando una? O básicamente, ¿tenéis acceso, vuestras claves API de aquí? Y verás que es la misma configuración de API. Tenemos una clave publicable y una clave secreta. Estas son las mismas dos cosas que teníamos con Slurk porque obviamente hay mucha influencia allí y puedes copiar estas y ponerlas en tu archivo env.local. Así que de la misma manera que tenemos la clave publicable de next public clerk, podemos tener una clave publicable de Stripe next public. Y esta va a ser nuestra clave publicable de aquí arriba. De nuevo, la clave publicable significa que esta clave se puede enviar al cliente. Está bien si los actores malintencionados tienen acceso a esta clave porque realmente no pueden hacer nada sensible con ella. Por eso tenemos la segunda cosa llamada clave secreta. Esta es la cosa que no debería filtrarse. Así que podemos añadir Stripe underscore secret underscore key. Y puedo revelar esto aquí, copiarlo, y luego pegarlo aquí. Y volveré a casa. Guardaré mi archivo env y volveré a mi página. Así que eso fue de nuevo, una configuración simple de una sola vez para Stripe que es simplemente creamos una cuenta aquí. Tomamos las claves API y las ponemos en nuestro archivo de entorno. ¿Cómo va todo el mundo hasta ahora? Aunque si estás avanzando hasta el paso tres, solo asegúrate de que también tienes que entrar en Clerk para crear una cuenta. Y desde tu panel de control de Clerk, puedes crear una aplicación y tendrás tus claves API aquí mismo. Oh, y también como cuando llegamos a casa, recibimos un poco de confeti diciendo que nuestra aplicación ahora tiene usuarios. Así que lo siguiente que vamos a hacer aquí, ahora que tenemos configuradas las variables de entorno de Stripe, es que vamos a crear un botón. Voy a tener que mantener eso abierto, pero junto con una tarea pendiente restante, quizás aquí podemos mostrar un botón para actualizar. Así que vamos aquí, vamos a crear un nuevo archivo. API slash Stripe slash, digamos botón o no botón, botón.tsx. Ahora esto va a ir a nuestra carpeta de aplicación. Así que SRC app, API, Stripe, botón.tsx. La razón por la que está dentro de una carpeta de API es porque muy pronto, vamos a tener que crear un punto final de webhook, pero vamos a ver eso muy pronto. Pero ahora mismo, todo lo que queremos es una función de exportación, llamémosla botón de actualización. Y todo lo que hace es devolver un botón que dice actualizar. Y luego en nuestra página.tsx, vamos a desplazarnos hasta el, esperar a las tareas pendientes restantes aquí. Y simplemente vamos a renderizar nuestro botón de actualización así. Guardémoslo y veamos cómo aparece. ¿Lo tengo en marcha? No lo tengo en marcha. Sigo olvidando la parte más importante, que es ejecutar el servidor real. Vamos a bajar aquí y refrescarlo. El botón.tsx, sí. Así que literalmente solo estamos devolviendo un botón con texto. No hemos añadido nada encima todavía. Pero la idea es que al hacer clic en este botón, lo que debería hacer es, que debería describir la intención de que, oh, este usuario quiere actualizar su plan al plan Pro, lo que significa que vamos a enviarlos a una página diferente, similar a lo que hicimos con Auth. Este botón de actualización es básicamente, en cierto sentido, el botón de inicio de sesión. El botón de inicio de sesión, lo que hace es que el usuario quiere iniciar sesión en la aplicación. Así que vamos a enviarlos a esta interfaz de autenticación.

15. Añadiendo el Botón de Actualización e Integración con Stripe

Short description:

Una vez que los usuarios han iniciado sesión, pueden actualizar su cuenta haciendo clic en el botón de actualización y completando el proceso de pago a través de Stripe. La función createStripeSession se utiliza para crear una sesión de pago con Stripe. La sesión incluye información sobre el método de pago, los artículos, la moneda, los datos del producto, el pago recurrente y la cantidad. También se puede añadir metadatos para almacenar información personalizada, como el ID del usuario.

Y una vez que han iniciado sesión, en la UI de authentication, pueden volver a la aplicación. Esa es la idea con el botón de actualización, es que una vez que hacen clic en el botón de actualización, van a ser enviados a este pago, esta interfaz de pago que es gestionada por Stripe. Y luego, una vez que han terminado de hacer su pago, ingresando los detalles de su tarjeta de crédito, pueden volver a nuestra aplicación, y ahora tienen una cuenta actualizada. Esa es más o menos la idea.

Voy a añadir... Vamos a añadir un poco de estilo a nuestro botón, sólo para asegurarnos de que se ve bien. Vamos a añadir... Ahora puedes añadirlo como quieras. A mí realmente me gusta Tailwind, por eso estoy haciendo cosas de Tailwind. Y le voy a dar un ligero fondo azul. Bueno, quizás 20 es demasiado. Mantengámoslo en ocho. Bueno, de nuevo, empezando con este inicio de sesión, el estilo no es una prioridad para esta masterclass, por eso estoy simplemente... También no soy realmente un buen diseñador. Así que los estilos que se me ocurren son absolutamente horribles, pero la idea, puedes entender la idea aquí, es que cuando tengo algunas tareas pendientes, puedo ver este botón de actualización, y al hacer clic en esto debería enviarme a la página de pago que necesitamos. Bien, ¿cómo lo hacemos?

Lo primero que necesitamos hacer aquí es que necesitamos crear una sesión de Stripe. Las sesiones son una especie de concepto de Stripe, el usuario dice que quiere comprar algo, vamos a crear una sesión de pago para ellos. Así que necesitamos una función. Va a ser una función asíncrona aquí, llamada createStripeSession. StripeSession. Ahora para esta función, vamos a cargar algunas bibliotecas, o realmente sólo una por ahora. Así que vamos a instalar Stripe con npm. Lo puse en el chat aquí. Así que vamos a instalar la biblioteca de Stripe con npm y veamos qué tenemos que hacer con la biblioteca en sí. Esto puede tardar un poco en cargar, así que voy a continuar con el código aquí. Voy a importar Stripe con S mayúscula de la biblioteca de Stripe que aún no se ha instalado. Luego voy a crear un Stripe con s minúscula. Y esto es, Stripe resulta ser una clase. Y lo que necesito pasar aquí, es process.env.stripe.secret.key. Así que esta es la clave secreta que obtuvimos del panel de control de Stripe y que acabamos de poner en nuestros archivos env locales. Esto está tardando un poco en instalarse porque mi ordenador está muy, muy lento ahora mismo. Pido disculpas por eso. Espero que lo estén pasando mejor que yo. Y lo otro que necesitamos pasar a esto es un objeto que contiene una versión de API. Ahora esta versión de API sólo necesita ser una fecha, lo que básicamente significa que dame la versión de API que era válida en esta fecha. Este es el día en que probé esto, así que podemos hacer eso. Voy a copiar todo este código, lo voy a poner en el chat para que puedas verificar si tienes todo funcionando correctamente. Esto está tardando demasiado. En realidad, sólo voy a reemplazar esto con bun install Stripe porque sé que bun es más rápido, pero por favor, siéntete libre de seguir usando NPM para esto. Bien. Así que ahora hemos importado la clase Stripe, la hemos instanciado aquí y ahora lo que podemos hacer en nuestra createStripe session es const session, y esto va a venir de stripe.checkout. Bueno, Copilot parece saber esto mejor que yo aparentemente. Y sólo necesitamos llamar a esta función aquí, stripe.checkout.sessions.create. Ahora vamos a necesitar pasar un montón de funciones aquí. También vas a ver que configurar y empezar con Stripe es un poco más difícil que algo como Clerk o algo como Planetscale porque creo que herramientas como Clerk, InverseL y Planetscale se alinean mucho más con el desarrollo de DX o developer experience encima de las APIs. Stripe, no tanto, por lo que configurar Stripe es un poco doloroso. Pero afortunadamente tenemos una hora para hacerlo. Lo primero que vamos a necesitar pasar a la sesión es el método de pago, ¿qué era payment method types?. Así que vamos a decir que vamos a aceptar el pago con tarjeta. Eso es lo primero que vamos a decirle a la sesión. También en este punto, vamos a añadir un signo de exclamación aquí para decirle a TypeScript que sí, hemos configurado esta variable de entorno, no tienes que preocuparte por ello. Lo siguiente que necesitamos decirle a Stripe son los artículos. Así que ¿qué es exactamente lo que el usuario está comprando aquí al hacer clic en este botón? Así que vamos a decir que el, así que básicamente podemos añadir más información sobre exactamente la cosa que el usuario está comprando aquí, el usuario está comprando en esta sesión de pago. Vamos a decir que la moneda es USD, dólares estadounidenses. Los datos del producto, podemos darle un nombre. Así que este es el nombre del producto. Podemos llamarlo el plan premium personal. La cantidad unitaria es cuánto cuesta esto en términos de centavos. Así que 100 significa $1, 1000 es $10. Así que de nuevo, para este ejemplo, vamos a ir con $10, lo que significa 1000 aquí. Luego necesitamos especificar si hay un pago recurrente. Así que vamos a decir que el intervalo recurrente es mes. Así que Stripe automáticamente sabe que este pago es algo que necesita obtener de la tarjeta de crédito cada mes hasta que obviamente el usuario cancele. Y finalmente, ¿cuál es la cantidad? Así que están comprando uno de estos productos. Así que todo esto es nuestro artículo. Estamos diciendo que este es el, esta es la información del precio o esta es la información del producto, el artículo que están comprando, y están comprando uno de estos. Necesitamos darle algunas cosas más en este punto. Así que después de los artículos, podemos darle algunos metadatos. Ahora un metadato es algo así como, los metadatos para cualquier sesión, la sesión de pago en este caso, es una especie de lugar para nosotros para almacenar información personalizada. Así que cuando le decimos a Stripe, oye, crea esta sesión de pago, los metadatos es algo que podemos usar para decirle a Stripe, oh, esta sesión de pago pertenece a este ID de usuario.

16. Creando la Sesión de Stripe y Configuración de ENV

Short description:

Cuando el usuario ha terminado de pagar, podemos mirar los metadatos para determinar el usuario asociado y otorgarles créditos adicionales. El ID del usuario proviene de la función de autenticación. También necesitamos agregar un modo de suscripción a la sesión, especificar las URL de éxito y cancelación, y devolver el ID de la sesión. La función de creación de la sesión de Stripe toma el ID del usuario y crea la sesión de Stripe. Comprobamos si el ID del usuario es nulo o indefinido y lanzamos un error si no están conectados. La sesión se configura para pagos con tarjeta en USD con un pago recurrente de $10 para el plan premium personal. Los metadatos incluyen el ID del usuario. El archivo ENV contiene la URL de la base de datos, la clave publicable de Clerk, la clave secreta de Clerk, la clave publicable de Stripe y la clave secreta de Stripe. Asegúrate de registrarte para las cuentas de Clerk y Stripe. Clerk está trabajando en automatizar el proceso de integración. Se requieren tanto Stripe como Clerk.

Entonces, al final, cuando el usuario ha terminado de pagar, y cuando Stripe vuelve a nosotros a través del webhook y nos dice que esta sesión de pago se ha completado, se ha pagado, podemos simplemente mirar los metadatos y averiguar qué usuario, a qué usuario estaba asociada esta sesión de pago para que podamos otorgarles créditos adicionales. Eso significa que el ID del usuario va a venir de auth como la mayoría de las otras funciones del servidor.

Ahí vamos. También necesitamos agregar un modo de suscripción a la sesión para que Stripe sepa que este es un pago basado en suscripción. También pueden decirle al usuario que esto es una suscripción. No es un producto único que están comprando. Y finalmente, necesitamos darle una URL de éxito y vamos a darle un nombre, una cadena por ahora. Y necesitamos darle una URL de cancelación, que también es una cadena. Así que aquí por ahora, podemos simplemente especificar que es ttt localhost 3000 slash dashboard. Así que una vez que hayan terminado con éxito su pago, vamos a decir, regresa al dashboard. O si cancelan su pago, lo mismo, simplemente regresen al dashboard. Ahora, de nuevo, idealmente, no querrías estar codificando en duro estos valores aquí. Querrías obtenerlos de las cabeceras de las solicitudes para averiguar dónde está desplegada la aplicación. Pero por el momento, voy a añadir localhost 3000 directamente aquí. Así que eso es todo lo que necesitamos hacer para crear una sesión de Stripe, al menos en el servidor. Y lo que podemos hacer ahora es devolver session.id.

Así que tenemos, un rápido repaso, tenemos una función de creación de la sesión de Stripe. En el servidor, tomamos el ID del usuario del usuario que actualmente ha iniciado sesión. Y en este punto probablemente también deberíamos comprobar si el ID del usuario es nulo o si es indefinido. Queremos lanzar un error diciendo que tienes que estar conectado para poder actualizar tu cuenta. Luego creamos la sesión de Stripe. Decimos que estamos aceptando pagos con tarjeta. Y en dólares, esto son $10. Se llama plan premium personal. Es un pago recurrente cada mes. Estás comprando uno de estos, y los metadatos son el ID del usuario. Eso es realmente todo lo más importante que hay que saber. ¿Cómo se siente todo el mundo hasta este punto? ¿Todo el mundo está al día? ¿Alguien tiene preguntas? Vale. El archivo ENV, sí. El archivo ENV, puedo deshacerme de ambos. Es solo la URL de la database para el archivo SQLite que tenemos localmente. Y en el archivo env.local, tengo la clave publicable de Clerk y la clave secreta de Clerk. Vaya. También tengo la clave publicable de Stripe y la clave secreta de Stripe. Ahora, tus claves obviamente deben venir de tus propias instancias de Clerk y Stripe. Así que asegúrate de estar registrado en clerk.com y estás registrado en stripe.com y necesitas hacer cuentas en ambos lugares. Clerk está trabajando activamente en hacer todo este proceso mucho más fácil. Así que en lugar de tener que integrar manualmente con Stripe y crear estas sesiones y crear oyentes de webhook, Clerk debería poder automatizar casi todo eso muy pronto. Y esa es una característica en la que estamos trabajando activamente. Pero por ahora, vamos a necesitar tanto Stripe como Clerk.

17. Conexión del Botón y Redirección al Pago

Short description:

Para conectar esto con el botón, hacemos una solicitud de API al servidor para crear una nueva sesión de Stripe. La función de sesión actúa como un punto final de API definido con 'use server'. Creamos un componente cliente llamado upgrade button client y pasamos la función como una prop. El componente cliente llama a la función como un punto final de API. Instalamos la biblioteca Stripe.js para la integración de Stripe en el lado del cliente. El componente de botón carga la biblioteca Stripe del lado del cliente usando loadstripe. Comprobamos si la biblioteca está cargada y lanzamos un error si no es así. Usamos Stripe client.redirectToCheckout para redirigir al usuario a la página de pago con el ID de la sesión.

Muy bien. Entonces, ¿estamos listos para pasar a la siguiente parte donde realmente conectamos esto con el botón? Esa es la parte emocionante. Entonces, lo que sucede en el clic del botón o en el front end ahora es que cuando hacemos clic en este botón, realmente necesitamos hacer una solicitud de API a nuestro servidor para ejecutar esta función, para crear esta nueva sesión de Stripe, lo que significa que esta función de sesión de Stripe es básicamente un punto final de API. ¿Y cómo definimos los puntos finales de API? Decimos use server. Y luego podemos simplemente pasar esta función a cualquier componente cliente que vaya a llamar a esto. Así que voy a crear un archivo adicional aquí con una API slash Stripe. Y voy a llamar a esto client.tsx. Puedes llamar a esto como quieras. El nombre del archivo no es importante aquí. Lo importante es que comenzamos este archivo con un use client. Ahora podemos exportar una función. Llamémosla client. O llamémosla upgrade button client. Así que este es el cliente donde, esta es la versión correspondiente del cliente de nuestro botón de actualización, o de nuestro botón de mejora que tenemos aquí. Así que vamos a poner lo mismo en realidad. Vamos a decir, simplemente devolver el mismo botón que estábamos devolviendo. Y de nuestra función de botón de mejora del servidor aquí, nos vamos a deshacer de esto. Y vamos a renderizar el botón del cliente que acabamos de definir en el otro lado. Ahora, si guardo todo, si vuelvo aquí y refresco, nada debería cambiar porque todo sigue igual. Oh, sigo apagando el servidor por alguna razón. Vale. Así que el servidor de desarrollo está en marcha. Y ahora deberíamos ver de nuevo nuestro panel de control aquí. Y el botón de mejora debería básicamente seguir igual. Lo único que hicimos fue que movimos este botón a un componente cliente para que podamos añadir adicional, podemos tener todo el tradicional React disponible para nosotros, lo que significa que tenemos un manejador de onClick. Y tenemos estado, tenemos useEffect, así que podemos hacer UI dinámica y cosas así. Pero realmente todo lo que necesitamos ahora es crear esa sesión de Stripe y luego necesitamos redirigir al usuario a la página de Stripe donde pueden terminar de hacer su pago. ¿Cómo hacemos eso? Bueno, tenemos una función createStripeSession aquí. Esto es algo que necesitamos pasar al cliente de botón de mejora. Así que vamos a decir, createStripeSession igual a createStripeSession. ¿Todos conmigo hasta aquí? Estamos tomando esta función que habíamos definido y la estamos pasando al componente cliente para que el cliente pueda llamar a esta función como un punto final de API, como un punto final de RPC. Y en nuestra función cliente, ahora podemos definir props y podemos decir que estamos esperando un createStripeSession. Y esto no va a tomar ningún argumento y simplemente va a devolver una cadena o una cadena dentro de una promesa. Así que aquí, podemos decir const sessionId igual a props.createStripeSession. Podemos poner un await aquí, lo que significa que esta función necesita ser asíncrona. Guardemos esto. Y veamos qué está rompiendo nuestra aplicación ahora mismo. Refresquemos. Vale, ahí vamos. Es solo inestable. Así que ahora este botón de mejora tiene un manejador de onClick adjunto a él. Y cuando hacemos clic en esto, va a hacer una solicitud a nuestro servidor, crear la sesión de Stripe y luego obtener el ID de la sesión. Pero, ¿qué podemos hacer con el ID de la sesión ahora? Bueno, este es un componente cliente, lo que significa que esto se está ejecutando en el navegador. Y si queremos hacer cosas de Stripe en el navegador, en realidad necesitamos otra biblioteca para trabajar con eso. Y para esta parte, vamos a instalar, eso es npm install, add Stripe slash Stripe.js. Ahora el Stripe, de nuevo, la historia de integración de Stripe ecosystem es un poco confusa. Hay un poco más de trabajo que hacer aquí en comparación con algo como Clerk, pero sinceramente vale completamente la pena. Así que acabamos de instalar, o instalé esa biblioteca? No sé si lo hice. Oh, Stripe.js. Vale, ahora voy a instalar Stripe.js. Parece que ya estaba casi instalado y puedo hacer npm run dev aquí. Así que ahora volvamos a nuestro componente de botón. Vamos a importar de esta nueva biblioteca que acabamos de instalar. Y vamos a importar loadstripe. Esto va a cargar la biblioteca de Stripe del lado del cliente para que podamos hacer cosas como, aquí, tenemos una nueva sesión. Redirigir al usuario a la sesión para que puedan terminar su pago. Eso es realmente lo más importante que necesitamos hacer en este punto. Así que veamos cómo podemos hacer eso. Vamos a decir const stripe client igual a await loadstripe. Y esto va a pedir la clave publicable que hemos puesto. Así que podemos decir process.env.next public Stripe publishable key. Esto debería ser exactamente lo mismo que hemos puesto en nuestro environment local, next public Stripe publishable key. Puedes simplemente copiar esto de aquí y puedes poner esto aquí y puedes poner un signo de exclamación para decirle a TypeScript que, sí, hemos añadido esta variable de entorno. Vale, así que tenemos la sesión ahora y tenemos la biblioteca de Stripe del lado del cliente. ¿Qué podemos hacer con estas dos cosas juntas? Bueno, primero necesitamos comprobar si esto existe porque podemos ver que Stripe client es del tipo de esta biblioteca o es nulo. Así que queremos asegurarnos de que si la biblioteca tiene problemas para cargar, si Stripe client no existe, entonces queremos lanzar un error diciendo que por alguna razón fallamos al cargar el cliente de Stripe. Tal vez la clave publicable que hemos configurado no es correcta. Y ahora simplemente podemos decir, await Stripe client dot redirect to checkout. Así que estamos pidiendo a Stripe que redirija al usuario actual a una página de pago donde pueden poner los detalles de su tarjeta de crédito. Y luego estamos pasando el ID de la sesión como parámetro porque el ID de la sesión es realmente lo que contiene qué está comprando el usuario, cuánto cuesta, cuáles son los métodos de pago, y todo eso.

18. Integrando Stripe Webhooks

Short description:

Cuando un usuario hace clic en el botón de actualización, va a la página de pago de Stripe, realiza su pago y luego regresa a nuestra aplicación. Necesitamos que nuestra aplicación sepa cuándo han terminado un pago en el sistema de Stripe, lo cual se hace a través de webhooks. En la misma carpeta de Stripe, agregamos un archivo route.ts que sirve como un punto final del webhook. El código verifica la autenticidad del webhook y procesa el objeto del evento. Nos enfocamos en el evento checkout.session.completed, que indica que se ha realizado un pago. Podemos extraer el ID del usuario del objeto de sesión de los metadatos.

Muy bien, veamos si esto funciona. Eso fue mucho código sin muchas pruebas. Entonces, volvamos aquí. Actualicemos esto. Y vamos a presionar ese botón de actualización y ver qué está haciendo. Y con suerte, todo está funcionando bien. ¿Cómo se siente todo el mundo? ¿Dónde está todo el mundo ahora? ¿Hasta dónde ha llegado todo el mundo? Hagamos clic en actualizar. Y ahí vamos. Ves, suscríbete al plan premium personal, $10 por mes. Tiene mi correo electrónico y los detalles de mi tarjeta de crédito ya guardados. Ahora, si estás aquí por primera vez, déjame ver, ¿puedo agregar un nuevo método de pago? Bueno, cuando estás en modo de prueba en Stripe, obviamente no necesitas llenar aquí los detalles reales de la tarjeta de crédito porque estamos en modo de prueba. Así que todo lo que tienes que hacer es agregar un montón de 42s a la información de la tarjeta, y luego puedes agregar, siempre y cuando las fechas sean válidas, puedes agregar los valores que quieras a todos los demás campos, y aún así deberías poder terminar el pago. Así que voy a bajar aquí y hacer clic en suscribirse. Y va a marcar este pago como exitoso. Como allí, había una marca de verificación verde, y ahora me redirigió de nuevo al panel de control. Así que añadimos esta función aquí para crear una sesión, y luego añadimos este manejador onclick aquí para redirigir a la persona, redirigir al usuario a la página de pago. Y así de simple, tenemos pagos, tenemos pagos básicamente integrados en nuestras aplicaciones. Aún no está completamente integrado porque la aplicación en sí, no tenemos ningún registro de qué plan de pago eligió el usuario, esa información está toda con Stripe, pero vamos a añadir un manejador de webhook para resolver ese problema muy pronto. ¿Quieres ver el botón TSX? Sí, por favor. Así que crea la sesión de Stripe. Voy a, una vez más, copiar esto en el chat. Si no quieres lidiar con copiar y pegar o copiarlo de la pantalla, simplemente siéntete libre de copiar esto del chat, y puedes profundizar en esto y realmente explorar la estructura tal vez después de la masterclass. Pero, ¿cómo se siente todo el mundo hasta ahora? Espero que todos, o al menos la mayoría de ustedes, estén en camino aquí para que podamos avanzar a las cosas más interesantes, que es donde integramos el pago con nuestro sistema de autenticación. Creo que estás motivado para construir un nuevo proyecto paralelo. Eso es genial. Eso es lo que me encanta escuchar. Genial. Entonces, lo que está pasando ahora es que cuando haces clic en el botón de actualización, cuando un usuario hace clic en el botón de actualización, van a la página de pago de Stripe, hacen su pago, y luego vuelven a nuestra aplicación. El problema es que hacen sus pagos con Stripe, no con nuestra aplicación. Así que necesitamos alguna forma de que nuestra aplicación sepa cuándo han terminado un pago en el extremo de Stripe, en el sistema de Stripe. Y esto se hace a través de algo llamado webhooks. ¿Cuántos de ustedes están familiarizados con los webhooks? Todo lo que vamos a hacer aquí es en la misma carpeta de Stripe, que sólo asegúrate de que está dentro de src app api stripe, vamos a añadir un route.ts. Otro concepto pero nunca implementado uno. Bueno, hoy es el día que va a cambiar. Ahora este archivo específicamente tiene que ser route.ts porque así es como Next.js interpreta las rutas de la API, lo que significa que podemos decir export function post. Y ahora esta es una función que será convertida en un punto final de post en slash API slash Stripe. Así que este es un punto final de webhook es básicamente un punto final de API en tu servidor que va a ser invocado por un backend separado, no un frontend separado o un usuario separado. Va a ser invocado por un backend. Esa es realmente la distinción clave entre los webhooks y tus rutas de API, tus rutas de API habituales. Ahora hay en realidad un montón de, desafortunadamente, hay un montón de código que entra en la construcción de este punto final de webhook y la mayoría de él no es realmente una preocupación para nosotros. Así que voy a, una vez más, copiar un trozo de código en el chat aquí y voy a copiar eso exactamente igual, pegar ese mismo código dentro del post. Y lo único que necesito es que necesito especificar que el parámetro a esta función post es esta cosa llamada solicitud. Y obviamente esta va a ser una función asíncrona y de nuestro button.tsx, podemos exportar Stripe de aquí porque estamos usando la misma biblioteca del lado del servidor para analizar los webhooks. Y ahora podemos importar Stripe del botón. También podemos importar next response de aquí. Y lo último que necesitamos es el secreto del webhook. Así que otra cosa que por ahora, sólo vamos a definirlo en línea aquí. Hagámoslo una función vacía porque una vez que ejecutamos stripe-cli, eso es lo que nos va a dar nuestro secreto de webhook. Así que lo que este trozo de código aquí está haciendo es básicamente verificando, es la forma de autenticación de webhook. Comprueba que si la cosa que está invocando tu webhook, ¿es eso legítimamente Stripe o es un actor malicioso pretendiendo ser Stripe para que puedan hackear tu sistema y decir que voy a conceder a mi usuario créditos ilimitados por alguna razón. Así que esas son las cosas que este sistema de autenticación previene. Pero de nuevo, mucho de esto es código en el que no tenemos que profundizar ahora mismo. Lo que realmente nos importa es este objeto de evento. Esto es realmente eso, el núcleo de lo que es el webhook. Es un evento. Así que algo sucedió dentro de Stripe y el objeto del evento representa lo que acaba de suceder. Y ahora estamos a cargo de procesar este evento. Y una forma muy sencilla de comprobar lo que pasó es una declaración de cambio. Así que vamos a decir event.type y vamos a decir que caso checkout.session.completed. Vamos a hacer algo o en el caso por defecto vamos a decir, oops, console.one. Tipo de evento no manejado. Bueno, lo que está pasando aquí es que el único evento que ahora nos preocupa que queremos procesar es este evento llamado checkout.session.completed. Si es cualquier otro evento, sólo vamos a registrar en la consola diciendo que, oh, tenemos un evento que no nos importa. Pero si tenemos un evento checkout.session.completed, ahora básicamente nos está diciendo que alguien ha hecho un pago hacia nuestras aplicaciones y ahora necesitamos procesar, necesitamos concederles créditos adicionales o lo que queramos hacer. Así que cuando obtenemos este evento, también vamos a obtener el objeto de sesión, el mismo objeto de sesión que creamos cuando el usuario hizo clic por primera vez en el botón de actualización.[

19. Almacenando el Plan de Pago en Clerk

Short description:

Debido a que el Webhook es invocado por Stripe y no por un usuario específico, necesitamos obtener el ID del usuario a través de los metadatos. Almacenamos el plan de pago del usuario en los metadatos públicos de Clerk actualizando el campo a 'pagado' una vez que el usuario ha pagado el plan premium a través de Stripe. El token de sesión, que es un token web JSON proporcionado por Clerk, puede personalizarse para incluir información adicional. Al agregar un campo de 'metadatos públicos' al token, podemos incluir todo el campo de metadatos de Clerk en un campo personalizado llamado 'metadatos públicos'. Luego podemos acceder a esta información en nuestro código para determinar el plan del usuario. El campo 'plan' en los 'metadatos públicos' puede ser 'gratis', 'pagado' o indefinido dependiendo del valor en los metadatos. Esta personalización del token de sesión nos permite agregar información extra al token y recuperarla cuando sea necesario.

Debido a que el Webhook es invocado por Stripe y no por un usuario específico. No tenemos acceso a nuestras funciones AuthUser aquí. Así que la única forma de obtener el ID del usuario es a través de los metadatos. Una vez más, si, ahora, si el ID del usuario no existe, vamos a lanzar un error de nuevo. Lanzar nuevo error, objeto de sesión inválido. Entonces, porque todas las creaciones de sesión, todas las solicitudes de sesión tienen que pasar por aquí, básicamente estamos garantizando que tienen que tener un ID de usuario. Y si no tienen un ID de usuario, fueron creados a través de algunas formas ilegales que no nos importan. Así que vamos a lanzar un error. Pero si hay un ID de usuario, ahora, finalmente, estamos en un punto donde necesitamos almacenar algunos datos en algún lugar que diga que este ID de usuario ha pagado por este plan. Y en realidad uno de los mejores lugares para almacenar eso es el propio Clerk. Clerk tiene esta cosa llamada, así que cada vez que quieras interactuar con las APIs de Clerk o los datos de Clerk, puedes importar Clerk Client desde Next.js. Lo que podemos hacer aquí es decir, clerk.users.updateUser. Vamos a pasar el ID del usuario aquí. Oh, en realidad lo que necesitamos hacer, lo siento, necesitamos hacer updateUserMetadata. Así que los metadatos del usuario dentro de Clerk es como esta pequeña base de datos mini que tenemos para cada usuario. Aquí es donde podemos almacenar cualquier información personalizada sobre el usuario, cualquier cosa importante para fines de autenticación. Y en esto, o fines de autorización, que en este caso, queremos almacenar qué plan de pago tiene actualmente el usuario. Así que tenemos dos cosas aquí, tenemos metadatos privados y metadatos públicos, vamos a usar metadatos públicos para este propósito. Vamos a decir que el plan es, están en un plan pagado ahora. Por defecto, deberían estar en el plan gratuito, pero ahora que han pagado el plan premium a través de Stripe, podemos actualizar el campo en los metadatos públicos a pagado. Ahora este es un campo completamente personalizado. La única razón por la que tengo este autocompletado aquí es porque tenemos, en nuestro proyecto, tenemos alguna definición personalizada de cómo se ve el metadato público del usuario. Por defecto, el metadato público del usuario se ve como un registro, no tiene ningún tipo concreto, no tiene plan, gratis o pagado, no tiene nada. Esto es algo que podemos definir encima de Clerk podemos decirle a Clerk en TypeScript que los metadatos públicos se supone que son un plan gratuito o un plan pagado. Y luego podemos establecer eso aquí. Bueno, vamos a hacer un rápido repaso de lo que pasó. Cuando enviamos al usuario a Stripe para hacer su pago, teníamos, creamos una sesión para ellos con metadatos personalizados para el ID del usuario. Así que según Stripe, los metadatos personalizados son el ID del usuario. Cuando obtenemos un punto final de webhook de vuelta de Stripe diciendo que este pago fue terminado y ahora puedes hacer un procesamiento adicional, agarramos ese ID de usuario, luego vamos a Clerk y decimos que aquí hay un usuario que acaba de terminar su pago y ahora los metadatos dentro de Clerk son las cosas de Stripe. Así que puedes ver cómo los metadatos de Stripe y los metadatos de Clerk se entrelazan entre sí para darnos esta experiencia. Vale. Ahora, lo último que necesitamos hacer aquí es volver a nuestro panel de Clerk y vamos a ir a la pestaña de sesiones aquí a la izquierda. ¿Cómo está siguiendo todo el mundo hasta ahora? Tenemos 50 minutos más. Creo que implementar este plan de sesión probablemente será el final de ello, pero podríamos tener un poco más de tiempo al final. Algo está mal con tu código de route.ts. Voy a copiar todo este código o puedo... Sí, voy a copiar todo este archivo y lo voy a poner... Oh, no puedo hacer eso. Así que voy a copiar uno hasta 30 y voy a copiar 31 hasta el final. Así que he dividido todo este archivo route.ts en dos partes diferentes. Si sólo quieres copiar y pegar y tratar de averiguar dónde estaba la diferencia, podemos trabajar hacia eso. Bien. Así que la última pieza que falta de todo esto es nuestro token de sesión. Ahora, si has estado alrededor de cualquier tipo de implementaciones de autenticación, si has hecho tu propia autenticación, probablemente has oído hablar de los tokens web JSON, ¿verdad? Estos son tokens que representan el estado de inicio de sesión de un usuario. Y obviamente, Clerk usa tokens web JSON. Cada vez que te registras en una aplicación con Clerk, vas a recibir un token que representa la sesión de inicio de sesión que tienes. Esta característica aquí nos permite personalizar ese token y agregar información adicional a él. Por defecto, ya hemos visto este token. Cada vez que llamamos a esta función de autenticación, básicamente obtenemos el resultado que obtenemos de vuelta es el propio token de sesión. Así que eso significa que el token de sesión tiene el ID del usuario y cualquier otra información accesible en él. Y a través de esta característica de Clerk, a través de la personalización de los tokens de sesión, podemos agregar información adicional que Clerk ahora está obligado a poner en el token de sesión. Y déjame demostrar rápidamente lo que eso significa. Así que voy a agregar un campo aquí llamado metadatos públicos. Y esto va a ser, también voy a encontrar aquí user.publicmetadata y hacer clic en él. Y esta es mi nueva plantilla para un token de sesión personalizado. Lo que significa que además de todo lo que Clerk ya está agregando a mi token, ahora también va a agregar todo el campo de metadatos en un campo personalizado en el token llamado metadatos públicos. Se va a aclarar más una vez que lo use. Así que vamos a guardarlo aquí y volvamos aquí. O volvamos a nuestra página. Aquí tenemos nuestra función de tareas pendientes, que estábamos usando para comprobar cuántas tareas puede crear aún el usuario. Saquemos un poco más de información del objeto de autenticación. Saquemos las reclamaciones de sesión. ¿Qué tenemos en las reclamaciones de sesión? Const algo o digamos que las reclamaciones de sesión punto, vamos a ver metadatos públicos aquí. Y si presionamos punto, vamos a ver el plan aquí. Así que digamos que el plan es igual a las reclamaciones de sesión punto metadatos públicos punto pla

20. Uso de Stripe CLI y actualización de metadatos de Clerk

Short description:

Podemos ignorar el material de la organización por ahora y operar sobre esto. Vamos a hacer un console.log del plan y verificar el flujo. Si no se define ningún plan, el predeterminado es el plan gratuito. Ahora, vamos a usar la CLI de Stripe. Si la tienes instalada, sigue los pasos para establecer el oyente de webhook. Agrega registros de consola para ver qué está sucediendo. Haz clic en actualizar, suscríbete al plan premium y verifica los registros. Actualizamos con éxito los metadatos de Clerk e los inyectamos en el token. La interfaz de usuario refleja el cambio. Podemos ocultar el botón de actualización si el usuario ya está en un plan de pago.

Podemos simplemente, podemos ignorar el material de la organización por ahora. Y vamos a operar sobre esto. Y cómo se llena fue la característica personalizada que acabamos de usar. Vamos a hacer un console.log del plan aquí y ver cómo está funcionando todo este flujo. Volvamos a nuestra aplicación. Y si no se define ningún plan, vamos a decir que por defecto, tendrás el plan gratuito. Porque si tenemos el plan de pago, esto debería ser anulado. Ahí vamos. El plan es gratuito. Y me queda una tarea por hacer porque estoy en el plan gratuito.

Y ahora estoy en el lado, voy a usar la CLI de Stripe. Así que voy, ahora si no tienes la CLI de Stripe instalada en este punto, este es quizás el tipo de punto que simplemente ya no puedes seguir. Pero si tienes la CLI de Stripe instalada, te animo mucho a que sigas estos pasos. Así que podemos escribir Stripe login, presionar enter en el navegador. Eso va a abrir, oops, lo siento. Esto va a abrir una pestaña del navegador. Vamos a autorizar a Stripe para que tenga acceso a nuestra CLI. Y ahora está hecho. Ahora todo lo que necesitamos hacer, si puedes ejecutar este comando, Stripe listen, dash dash four, word two, localhost 3000 slash API slash Stripe. Así que esto va a establecer ese oyente de webhook. Esto le va a decir a Stripe que todo lo que suceda dentro de Stripe, reenvíe esos webhooks a localhost 3000 API Stripe, lo que básicamente significa reenviarlos a esta ruta que acabamos de definir aquí. Y si lo ejecutas, vamos a recibir un secreto de webhook. Eso sólo va a funcionar para tu entorno localhost específico.

Ahora sé que esto fue mucho de configuración. Así que vamos a añadir algunos registros de consola más y ver qué está pasando. Vamos a añadir un registro de consola aquí y decir, la sesión de pago se completó. Y otro aquí, actualizado el usuario al plan de pago. Así que puedes añadir los registros de consola que quieras. Esto es, de nuevo, sólo estoy dejando que el copiloto haga la conducción en este punto. Genial. Ahora podemos colapsar esto y momento de la verdad. Veamos si esto funciona. Voy a deshacerme de esto y voy a volver a localhost y refrescar. Muy bien, hagamos clic en actualizar. Así que llegamos a la página de pago de Stripe, suscribirse al plan personal premium, $10 por mes. Todos los detalles de mi tarjeta de crédito ya están guardados. De nuevo, es una tarjeta falsa. No estoy pagando dinero real aquí. Así que si hago clic en suscribir, volvamos a nuestros registros y veamos qué está pasando. Así que vimos un montón de cosas allí. Estos son todos los eventos que están tratando de entrar desde Stripe. Vamos a ver un error 401 aquí porque en realidad nuestro middleware de Clerk está bloqueando todas estas solicitudes de API. Así que necesitamos decir, necesitamos decirle a Clerk que deje pasar API slash Stripe. Porque Clerk sólo es responsable de las cosas que exponemos a los usuarios. Pero esto no es algo que exponemos a los usuarios, esto es algo que estamos exponiendo a un servicio backend diferente. Y por eso, tenemos nuestras propias cosas de seguridad que hemos definido aquí. Así que no necesitamos que Clerk autentique las rutas de la API. Y ahora vamos a intentarlo de nuevo. Vamos a intentar actualizar. Vamos a ir aquí de nuevo. Vamos a hacer clic en suscribir y veamos qué pasa ahora. Vale. Así que conseguimos, ahí vamos. Conseguimos un plan de pago. Así que aunque tenemos algunos errores aquí, en realidad terminamos con un plan de pago en nuestra consola. Lo que significa que si volvemos a esto, la función de tareas pendientes, hemos actualizado con éxito los metadatos de Clerk para decir que el usuario ahora está en un plan de pago. Y luego hemos inyectado con éxito esos metadatos en el token, de modo que en nuestro código, ahora podemos ver si el usuario que ha iniciado sesión es un usuario de pago o un usuario gratuito. Lo que significa que ahora puedo decir const max equals $1. Si el plan es igual a pago, entonces esto es 10. O si no, esto es cinco. Y aquí puedo decir max menos el recuento de tareas pendientes. Y volvamos aquí y veamos cómo cambia la interfaz de usuario. Ahora me quedan seis tareas pendientes. Pasé de una tarea pendiente a seis tareas pendientes porque estoy en el plan de pago. Deshagámonos de esto. Y veamos también rápidamente cómo podemos hacer que nuestra interfaz de usuario refleje esto. Así que vamos a añadir reclamaciones de sesión aquí. Vamos a copiar este código de aquí arriba a aquí abajo en nuestro componente de servidor. Así que ahora sabemos si el usuario está en un plan gratuito o en un plan de pago en nuestro componente. Lo que significa que simplemente podemos ocultar el botón de actualización si ya están en un plan de pago.

21. Añadiendo características de multi-tenencia

Short description:

No es necesario mostrar el botón de actualización si ya están en un plan de pago. En su lugar, podemos mostrar 'pro' o incluso tener un botón para degradar. Aunque no implementaremos la funcionalidad de degradación o cancelación de suscripción en esta masterclass, puedes imaginar añadir un botón de degradación para los usuarios en un plan de pago. El botón de actualización actualiza con éxito Clerk, Stripe y nuestra aplicación, permitiéndonos crear más de cinco tareas pendientes. Una vez que los pagos están integrados, puedes construir rápidamente características adicionales sobre la funcionalidad existente. Por ejemplo, puedes tener varias listas de tareas pendientes para cada usuario, diferentes niveles para usuarios gratuitos y de pago, y más. Clerk facilita la adición de características de multi-tenencia, como organizaciones, equipos, invitaciones y planes de organización. Al habilitar las organizaciones en el panel de Clerk, puedes cambiar entre tu cuenta personal y cualquier organización que crees. El componente de conmutador de organización te permite gestionar usuarios y roles dentro de cada organización.

No necesitas mostrarles el botón de actualización si ya están en un plan de pago. Así que si el plan es igual a gratuito, entonces les mostramos el botón de actualización. Esto debería ser un signo de interrogación. O simplemente les mostramos que están en un plan pro. O en realidad, digamos simplemente pro. Así que en lugar de actualizar, ahora deberíamos ver pro. Está estilizado horriblemente. No me gusta eso, pero lo voy a dejar así por ahora. O tal vez podemos cambiar esto a un botón que diga degradar. No vamos a implementar la degradación o como la funcionalidad de cancelación de suscripción en esta masterclass, pero puedes imaginar que si ya están en un plan de pago, querrás mostrar un botón de degradación aquí en lugar de un botón de actualización. Pero por ahora, tener ese botón de actualización, actualizó Clerk, actualizó Stripe, y actualizó nuestra propia aplicación para que ahora podamos crear más de cinco tareas pendientes. Así que puedo ir cuatro, cinco, seis, siete, y puedes ver que mi límite ha sido automáticamente aumentado. Así que eso fue un poco de un desvío, ¿no es así? Hubo mucha implementación y muy pronto en el futuro, todo esto se va a simplificar mucho más porque estamos integrando los pagos en Clerk. Pero por ahora, aunque eso tomó un tiempo, realmente, una vez que te haces una idea de estos, de hacer esto, básicamente puedes poner todo esto en marcha en menos de una hora. Y luego una vez más, el punto era que puedes volver rápidamente a construir tus proyectos. Así que una vez que tienes pagos como estos, rápidamente integrados, puedes seguir construyendo características encima de él. Puedes tener más tareas pendientes, puedes tener diferentes, como por ejemplo, podemos exagerar aquí y podemos tener varias listas de tareas pendientes para cada usuario donde cada uno, digamos que los usuarios gratuitos pueden tener tres listas, los usuarios de pago no pueden tener 10 listas, lo que sea, como quieras estructurar el negocio de esta aplicación, eso depende de ti. Pero todas las herramientas para que hagas eso están aquí. Entonces, ¿cómo se sienten hasta ahora? ¿Alguien en el chat? No dudes en preguntar, lanzar preguntas o si, una vez más, si te has perdido en algún punto, podemos ponernos al día. Nos quedan 30 minutos más. Podemos pasar los 30 minutos completos preguntando o respondiendo preguntas o poniendo al día a la gente. O si simplemente están disfrutando viendo y siguiendo, podemos añadir algunas características de multi-tenencia porque ahora mismo podemos tener usuarios individuales que tienen su lista de tareas pendientes y que podrían actualizar al plan pro para niveles superiores. Pero también podemos tener organizaciones y equipos e invitaciones y planes de organización. Y una vez más, Clerk hace que sea realmente fácil añadir todas esas cosas a nuestra aplicación. Vamos a cerrar algunas de estas pestañas abiertas. Y si no veo muchas preguntas, voy a pasar a lo siguiente mejor, que es la multi-tenencia. ¿Cuántos de ustedes saben qué es la multi-tenencia? ¿Cómo definirías la multi-tenencia? ¿Quién ha construido una aplicación multi-tenant? Eso es una de esas cosas muy divertidas de construir de vez en cuando. Nunca lo había oído. Genial. Así que la idea de la multi-tenencia es simplemente que hay varios grupos de usuarios usando tu aplicación y todos tienen este estado compartido. Así que incluso ahora, en cierto sentido, nuestra aplicación es multi-tenant porque cada usuario tiene su propia lista privada de tareas pendientes. Pero generalmente lo que significa multi-tenant es que tenemos una organización o tenemos un espacio de trabajo o tenemos un equipo y ese equipo o esa organización tiene un grupo de usuarios. En realidad, sabes qué, simplemente te lo voy a mostrar. Vamos a nuestro archivo de diseño aquí donde tenemos nuestro botón de usuario aquí. Y vamos a añadir un nuevo componente aquí llamado el conmutador de organización. Una vez más, este componente simplemente viene preconstruido en FromClerk Next.js. Solo tienes que soltarlo así. Voy a guardar eso y volver aquí y ver qué pasa. También necesito asegurarme de que está funcionando. ¿Puedes refrescar? Puede que necesite refrescar. ¿Por qué no estoy viendo el conmutador de organización? Interesante. ¿Está este diseño en caché de alguna manera? No, no lo está. Bueno, vamos a agarrar ambos de estos y asignar en componente. Eso podría haber sido. Hmm, eso suele aparecer. No estoy seguro de cuál es el problema. Voy a probar el perfil de la organización. Bueno, el perfil de la organización no puede renderizar. Pero el conmutador de organización debería ser algo que podemos renderizar aquí. Debería desactivar o activar UR write, ¿sabes qué? Tienes toda la razón. Esto es algo que no hago con suficiente frecuencia porque simplemente lo hago una vez y me olvido completamente de ello que tenemos que habilitar las organizaciones. Así que sí, en tu panel, ve a organizaciones y habilita las organizaciones así. Ahora, si vuelvo aquí y refresco, ahí vamos. Muchas gracias, Joachim. Aparentemente sabes, Clerk mejor que yo. Es genial ver eso. Genial, así que de nuevo, puedo deshacerme de la sesión iniciada aquí. Añadí este componente de conmutador de organización. Eso es realmente todo lo que hice. Y habilité un interruptor desde el panel de Clerk. Y lo que esto habilita en mi aplicación es básicamente la multi-tenencia. Tengo mi cuenta personal y puedo simplemente crear una nueva organización. Puedo llamar a esto, digamos React Summit NYC. Y esta es simplemente una nueva organización que existe en Clerk. Puedo invitar a gente a ella. Puedo dar a la gente el rol de administrador o miembro o puedo saltarme esto por ahora. Pero ahora estoy en esta organización. Puedo cambiar a mi cuenta personal o puedo cambiar a esta organización cuando quiera. Y una vez más, puedes ir a gestionar la organización, al igual que gestionar el usuario, o al igual que el perfil de usuario, tenemos el perfil de la organización. Puedes gestionar, puedes ver toda la lista de usuarios que están en la organización.

22. Implementando listas de tareas pendientes multi-inquilino

Short description:

Ahora puedes tener diferentes versiones de listas de tareas pendientes para usuarios y organizaciones. Al filtrar las tareas pendientes en función del ID de la organización, puedes mostrar la lista de tareas pendientes para toda la organización si el usuario se encuentra en una cuenta de organización. Si el usuario está en una cuenta personal, verá su lista personal de tareas pendientes. El ID de la organización se utiliza para rastrear bajo qué organización se creó una tarea pendiente. El componente de tareas pendientes se actualiza para incluir el ID de la organización al crear una nueva tarea pendiente. El esquema de la base de datos también se actualiza para incluir el campo ID de la organización en el modelo de tareas pendientes. Al buscar las tareas pendientes en función del ID de la organización, puedes asegurarte de que cada organización tiene su propia lista de tareas pendientes. Los usuarios de una organización pueden ver todas las tareas pendientes creadas por otros miembros de la organización. Esto permite la creación de una aplicación multi-inquilino con listas de tareas pendientes separadas para cada organización. El tiempo de implementación de esta característica es mínimo, tardando solo de cinco a diez minutos en configurarse. Al replicar el procesamiento de Stripe, se pueden añadir planes de organización encima de la funcionalidad existente.

Puedes ver una lista de invitaciones. Puedes invitar a nuevas personas. Y si fueras un administrador, puedes cambiar los roles. Así que de nuevo, todo completamente preconstruido. Como desarrollador, no tuve que hacer nada de eso. Todo lo que tuve que hacer fue añadir este conmutador de organización. Pero ahora puedo tener diferentes versiones de estas listas no solo para los usuarios, sino también para las organizaciones.

Así que veamos rápidamente cómo se ve eso. Volvamos a nuestra aplicación de tareas pendientes, que significa nuestro tablero. Y tratemos de averiguar, bien, ¿cómo sabemos a qué organización pertenece el usuario o incluso el usuario ha seleccionado actualmente? Bueno, tenemos nuestro token, ¿verdad? Así que simplemente tomemos el ID de la organización del auth. Y podemos ver que el ID de la organización es una cadena o nulo o indefinido. Si es una cadena, eso significa que el usuario ha iniciado sesión y ha seleccionado una organización. Así que simplemente voy a hacer un console.log del ID de la organización para que podamos ver qué está pasando en cada caso diferente. Aquí vas a ver que el ID de la organización es una cadena real. Es el ID de la organización en la que estoy. Si vuelvo a la cuenta personal, ahora verás que el ID de la organización es indefinido. Así que este ID de la organización no solo nos dice si el usuario que ha iniciado sesión actualmente está en una cuenta personal, sino también qué organización han seleccionado actualmente.

Entonces, ¿qué podemos hacer con esta información? Digamos que si estás en una cuenta personal, vas a ver tu lista personal de tareas pendientes. Pero si estás en una cuenta de organización, vas a ver la lista de tareas pendientes de toda esa organización, lo que significa incluso las tareas pendientes que otras personas han añadido a esa organización, deberías poder ver. Así que añadamos este filtro aquí. Vamos a decir que si existe el ID de la organización, estamos buscando todas las tareas pendientes que tienen el ID de la organización igual a este. Esto también significa que necesitamos actualizar nuestro esquema de database, que probablemente deberíamos hacer ahora mismo. Vamos a rastrear bajo qué organización se creó una tarea pendiente. Esto puede ser opcional porque digamos que si creaste una tarea pendiente para tu espacio de trabajo personal, para tu cuenta personal, el ID de la organización simplemente va a ser nulo. Pero si creaste una tarea pendiente en una organización, el ID del usuario seguirá siendo tú, pero también tendrás el ID de la organización que será el ID de la organización, en este caso, React Summit NYC. Oopsie. Ahí vamos. Así que hemos añadido un nuevo campo a nuestro modelo de tareas pendientes. Podemos volver aquí. Podemos decir npm run db push para asegurarnos de que los cambios del esquema se propagan. Y ahora podemos ejecutar npm run dev de nuevo.

Así que también obtengamos el ID de la organización cuando estemos creando una nueva tarea pendiente y asegurémonos de que se incluye aquí. Y esto es realmente todo lo que necesitamos hacer porque si el ID de la organización es indefinido, simplemente no se va a establecer en la database, lo que por defecto significa que va a la cuenta personal. Pero si el usuario tiene seleccionada una organización, vamos a crear la tarea pendiente con ese ID. Así que automáticamente sabemos que se creó bajo esa organización. Así que todo lo que necesitábamos hacer era tomar el ID de la organización del auth y pasarlo aquí. Podemos hacer exactamente lo mismo en todas partes. Podemos añadirlo en la cláusula where aquí. Y aquí y aquí. Y cuando estamos buscando una lista de tareas pendientes, ahora aquí está la cosa, aquí es donde se complica un poco más. Estamos comprobando si existe el ID de la organización, lo que significa que el usuario está actualmente en una organización. Y en ese caso, vamos a buscar una lista de todas las tareas pendientes en esa organización. Si no, voy a buscar una lista de todas las tareas pendientes creadas por este usuario, pero también donde el ID de la organización es ninguno. Así que básicamente nos aseguramos de que estamos buscando, estamos buscando los elementos del espacio de trabajo personal y no estamos sacando accidentalmente ninguna tarea pendiente que el usuario actual también podría haber creado en otras organizaciones. Así que veamos cómo se ve esto. Voy a refrescar esto. Tarda un poco porque mi computadora está muy, muy lenta hoy. Pido disculpas por eso. Ahí vamos. Bueno, estamos en React Summit NYC y no encontramos tareas pendientes. Añadamos algo de código. Aquí estamos en React Summit. Veamos, añadamos algo aquí, entregar la masterclass, ir a la fiesta posterior, charlar con... Oh, y ahora está jugando con nuestra lógica de tareas pendientes restantes. Así que aquí también, podemos simplemente comprobar el ID de la organización. Y si existe el ID de la organización, simplemente vamos a, digamos que nos salimos de aquí. Así que básicamente estamos permitiendo a las organizaciones crear tareas pendientes ilimitadas. Porque si añadimos una nueva tarea pendiente aquí, esto permanece en 10. Idealmente, lo que podrías querer hacer es básicamente hacer todo el Stripe, tener otro plan de Stripe, otro botón de pago de Stripe, pero para organizaciones en lugar de solo para usuarios. Pero para el propósito de la masterclass, podemos simplemente salirnos de aquí. Y decimos que las organizaciones pueden hacer tareas pendientes ilimitadas ahora mismo. Justo como antes de añadir Stripe, los usuarios podían hacer tareas pendientes ilimitadas. Pero el punto aquí es que si vuelvo a mi cuenta personal, solo veo las tareas pendientes que creé para la cuenta personal. No veo las tareas pendientes que acabo de crear para la organización. Así que ahora cada organización tenía su propia lista de tareas pendientes. Y si invito a alguien a esta organización, van a ver esta misma lista de tareas pendientes que estoy viendo debido a cómo estamos buscando las tareas pendientes en nuestra database. Así que eso fue, pasamos de una aplicación completamente basada en el usuario a una aplicación multi-inquilino. ¿Y cuánto tiempo llevó eso? Quizás de cinco a diez minutos. Eso no llevó mucho tiempo en absoluto. Y si podemos simplemente ir, si podemos simplemente replicar todo el procesamiento de Stripe que hicimos, todo el programación de Stripe que hicimos, ahora podemos tener planes de organización encima de esto.

23. Finalizando la Masterclass y Comentarios

Short description:

Voy a terminar la masterclass aquí por ahora. Siéntete libre de ver la grabación y proporcionar comentarios. La rama completada incluye todas las características que hemos construido, incluyendo planes para organizaciones. La interfaz de usuario se ve más agradable con planes gratuitos y pro para usuarios y organizaciones. Puedes agregar páginas personalizadas dentro de los componentes preconstruidos de Clerk. Puedes construir aplicaciones que manejen la diferenciación de usuarios y organizaciones sin problemas. También puedes agregar interfaz de usuario para usuarios y organizaciones dentro de la interfaz de usuario de Clerk. Ya no hay más excusas para construir aplicaciones que puedan escalar a miles de usuarios. Gracias a todos por ser un público increíble. Por favor, déjame saber tus comentarios y comparte lo que construyas con Clerk.

Y voy a terminar las demostraciones aquí por ahora, o voy a terminar la masterclass aquí por ahora. No pude escribir e iniciar sesión en las cuentas al mismo tiempo después de un rato. Bueno, por eso tenemos la grabación disponible. Así que siéntete libre de ir y seguir con la grabación. Y probablemente, si estás viendo esta grabación ahora mismo, por favor contáctame en Twitter, en YouTube, en Discord, donde puedas, y déjame saber qué te pareció la masterclass hasta ahora, y si ha sido de alguna ayuda en absoluto.

Tenemos 20 minutos más y voy a dejar eso para un montón de preguntas. Si también estás en el repositorio de GitHub, también puedes explorar esta rama completada. Esto es lo que he estado usando como mi trampa al lado. La rama completada básicamente tiene todo lo que hemos hecho hasta ahora, pero también tiene planes para organizaciones. Así que déjame demostrar eso muy rápidamente ahora que hemos terminado con la masterclass en sí. Voy a salir de eso, salir de eso. Voy a descartar todo lo que hemos hecho hasta ahora. Gracias a todos por los comentarios, realmente los aprecio. Y voy a revisar lo completado. Voy a instalar todo lo que se necesita. Y voy a ejecutar el servidor de desarrollo. Así que veamos qué, porque hay un par de pasos que no llegué a hacer durante esta masterclass. Veamos cómo se ven. Así que voy a refrescar. Una vez más, esta es tu oportunidad de hacer preguntas. Así que por favor aprovecha este tiempo. Estoy tomando notas allí. Oh, mi vaso de agua se ha ido, o no hay más agua en él. Estoy leyendo propiedades. No puedo leer propiedades. Esto está sucediendo aquí. Oh, porque esto puede ser... Solo voy a decir que pueden ser objetos vacíos inicialmente. Ahí vamos. Así que esta es la versión completada que tenía. Puedes ver que la interfaz de usuario se ve un poco más agradable. Hay una versión gratuita aquí, y puedes ver que quedan ocho tareas pendientes para la organización. Y puedo agregar un montón más aquí, y una vez que llego a uno o una vez que llego a cero, no puedo crear más tareas pendientes para la organización. Si vuelvo a mi cuenta personal, en la cuenta personal, estoy en el plan pro, así que puedo crear en realidad 10 tareas pendientes. Así que puedo subir hasta 10. Puedo deshacerme de eso. Pero si agrego algo más, no puedo. Y puedes ver aquí en la consola, has alcanzado tu límite de tareas pendientes. Puedo seguir eliminando estas, y entonces obviamente podré agregar más. Así que en la rama completada, en realidad tengo un plan gratuito y un plan pro tanto para usuarios como para organizaciones. Y hay un truco realmente agradable aquí, es que puedes agregar páginas personalizadas dentro de estos componentes preconstruidos. Así que este es el componente de perfil de organización que acabamos de saltar, o como incrustado en, que es soltado desde la biblioteca de Clerk. Pero este plan es una página completamente personalizada que he añadido aquí. Y puedes ver que muestra toda la información sobre cómo la organización está actualmente en el plan gratuito, y puedo actualizar al plan pro por $50 al mes. Y lo mismo si voy a mi perfil de usuario, veo un plan, y dice que actualmente estoy en el plan pro para la suscripción personal, y puedo degradar. Así que no solo puedes construir todas estas aplicaciones donde los usuarios y las organizaciones son tratados de manera diferente, y tu aplicación maneja todo eso sin problemas, también puedes agregar toda esa interfaz de usuario, agregar interfaz de usuario extra que concierne a usuarios y organizaciones, justo dentro de la interfaz de usuario de Clerk. Así que ni siquiera necesitas tener tus propias páginas personalizadas, completamente construidas para todas estas cosas. Y todas estas contribuyen a este valor al que estaba tratando de llegar inicialmente, donde realmente no tengo más excusas. Si tengo una idea que podría funcionar, puedo simplemente construirla, y puedo construir una aplicación a partir de ella, o puedes construir una aplicación a partir de ella que puede llegar hasta miles de usuarios de forma gratuita, o por muy poco cargo de suscripción por los servicios que hemos utilizado durante la masterclass. Y espero que esto haya sido valioso para todos ustedes. Leyendo del chat, parece que lo ha sido. Gracias a todos por estar aquí. Esta ha sido una increíble masterclass. Ustedes han sido un público increíble, y realmente espero ver lo que ustedes construyen con esto. Diré al final, déjame conectar rápidamente mi Twitter aquí, y también Clerk. Así que este es mi Twitter. Una vez más, si encontraste esta masterclass útil, por favor déjame saber, y déjame saber si construyes algo genial con esto. También déjanos saber. Si construyes algo genial con Clerk, nos encantaría hablar más sobre ello y compartirlo. Nos encanta absolutamente cuando la gente construye cosas geniales con Clerk. Así que si puedes hacer eso, espero que ustedes tengan un gran día. Así que si puedes hacer eso, me encantaría ver eso. Por favor contáctame y déjame saber cómo fue la masterclass. Y sé que también hay un formulario de comentarios anónimo que va a los organizadores. Así que por favor envía eso también, pero también siéntete completamente libre de simplemente entrar en mis DMs y hablar conmigo sobre Clerk, o sobre la construcción de aplicaciones SaaS, o simplemente sobre web development en general. Lo que ustedes quieran. Sobre lo que quieran charlar. Que tengas un buen día también. Muchas gracias por estar aquí. Gracias por la ayuda.

24. Construyendo con Clerk y Planes Futuros

Short description:

He utilizado Clerk durante unos seis meses antes de unirme como defensor del desarrollador. Construí una startup dirigida a agencias gubernamentales, pero no creció mucho. Otro proyecto fue una aplicación para asistentes a conferencias con un par de cientos de usuarios. Personalmente, no he tenido la oportunidad de construir muchas cosas grandes con Clerk, pero estoy trabajando activamente hacia ello. Gracias por la pregunta.

¿Cuál es la cuenta de sitio web más grande que alguna vez construiste con Clerk? Así que tuve la oportunidad de usar Clerk durante unos seis meses más o menos antes de unirme a Clerk como defensor del desarrollador. Estábamos tratando de construir una startup que se dirigiera a, digamos, agencias gubernamentales. Realmente no creció mucho. Y la segunda cosa que construí con Clerk, que fue una aplicación para conferencias, así que una aplicación para asistentes a conferencias. Así que cuando vas a una conferencia, puedes mirar esta aplicación. Tiene toda la agenda para la conferencia. Puedes guardar cosas. Y tenía como, qué, alrededor de un par de cientos de personas usándola el día de la conferencia. Así que personalmente para mí, ese ha sido más o menos el límite, pero eso es realmente solo porque no tengo la oportunidad de construir muchas cosas geniales con Clerk. Tengo la oportunidad de construir cosas pequeñas como esta demostración, pero no muchas cosas grandes. Y eso es algo hacia lo que estoy trabajando activamente. Excelente pregunta. Muchas gracias. Gracias por preguntar. Y de nuevo, si tienes más preguntas como estas, eso es exactamente para lo que es mi Twitter. Bueno, voy a pulsar ese botón de finalizar ahora. Muchas gracias a todos. Y espero ver a algunos de ustedes en mis DMs o en Twitter o en persona.