Introducción
Cuando desarrollamos una aplicación web, una de las decisiones importantes es elegir cómo vamos a almacenar la información. Existen diferentes alternativas, pero no todas funcionan de la misma manera ni requieren la misma configuración.
En nuestro proyecto decidimos trabajar con una base de datos NoSQL, porque queríamos conocer cómo funciona el almacenamiento mediante documentos y cómo se puede conectar directamente con una aplicación moderna.
Para ponerlo en práctica desarrollamos TaskFlow, un sistema web para gestionar tareas personales utilizando React, Firebase Authentication y Cloud Firestore.
Nuestro objetivo no era solamente crear una interfaz que permitiera registrar actividades, sino implementar una solución que almacenara los datos en la nube, controlara el acceso de los usuarios y pudiera publicarse automáticamente utilizando GitHub Actions.
En este artículo explicaré cómo está organizada la aplicación, cómo funciona la base de datos NoSQL, qué mecanismos de seguridad utilizamos y cómo conseguimos automatizar su publicación.
1. ¿En qué consiste TaskFlow?
TaskFlow es una aplicación que permite administrar actividades personales desde un navegador.
Su funcionamiento es sencillo: el usuario se registra, inicia sesión y accede a un panel donde puede crear, consultar, modificar y eliminar sus tareas.
Cada tarea contiene información básica, como el título, descripción, fecha límite y estado.
También implementamos tres estados para organizar las actividades: pendiente, en proceso y completada.
Una característica importante es que cada tarea está asociada al usuario que la registró. Esto permite organizar la información sin mezclar las actividades de distintas cuentas.
[INSERTAR CAPTURA 1: Panel principal de TaskFlow]
2. Arquitectura de la aplicación
Para organizar TaskFlow utilizamos una arquitectura basada en servicios de Firebase.
La aplicación está dividida en tres componentes principales:
Frontend: desarrollado con React y Vite. Es la parte visual con la que interactúa el usuario.
Autenticación: implementada mediante Firebase Authentication, que permite registrar usuarios e iniciar sesión con correo y contraseña.
Base de datos: desarrollada con Cloud Firestore, encargada de almacenar y recuperar los documentos de las tareas.
El funcionamiento general puede representarse así:
USUARIO | v APLICACIÓN REACT | +--------+--------+ | | v v FIREBASE AUTH CLOUD FIRESTORE | | Verifica usuario Guarda y consulta | documentos NoSQL +--------+--------+ | v PANEL DE TAREAS Esta organización nos permitió desarrollar las funcionalidades del sistema sin necesidad de implementar un servidor backend tradicional.
En este caso, React utiliza directamente los SDK de Firebase para comunicarse con los servicios de autenticación y almacenamiento.
Sin embargo, eso no significa que la aplicación carezca de backend. Firebase proporciona los servicios backend administrados que necesitamos.
3. ¿Por qué elegimos Firebase Firestore?
Uno de los objetivos del proyecto era utilizar una base de datos NoSQL diferente de las tecnologías que normalmente se trabajan en aplicaciones tradicionales.
Por eso elegimos Cloud Firestore, una base de datos orientada a documentos.
En una base de datos relacional, como MySQL, normalmente definimos tablas y relaciones mediante un esquema estructurado.
En Firestore, en cambio, la información se organiza mediante colecciones y documentos.
Por ejemplo, para nuestro proyecto utilizamos la colección tareas.
Cada documento representa una tarea registrada.
Firestore | └── tareas | ├── tarea_001 | ├── titulo | ├── descripcion | ├── estado | ├── fecha | └── usuarioId | └── tarea_002 ├── titulo ├── descripcion ├── estado ├── fecha └── usuarioId Esto permitió almacenar las tareas mediante documentos identificados de forma independiente.
Además, Firestore permite trabajar con consultas y escuchar cambios en tiempo real, características que aprovechamos para mantener actualizado el listado de tareas.
4. Diseño de los documentos NoSQL
Aunque Firestore no exige una estructura rígida como una tabla relacional, consideramos importante mantener una organización consistente.
Por eso definimos campos comunes para todas las tareas.
Un documento de ejemplo tiene esta estructura:
{ "titulo": "Implementar base de datos NoSQL", "descripcion": "Conectar React con Firebase Firestore", "estado": "En proceso", "fecha": "2026-11-20", "creada": "2026-11-14T23:00:00.000Z", "usuarioId": "uid_del_usuario" } Cada campo cumple una función específica.
| Campo | Función |
|---|---|
| titulo | Identifica la actividad |
| descripcion | Explica qué debe realizarse |
| estado | Indica el progreso de la tarea |
| fecha | Establece una fecha límite |
| creada | Registra cuándo se creó |
| usuarioId | Identifica al propietario |
El campo usuarioId es especialmente importante, porque nos permite relacionar la información con Firebase Authentication.
[INSERTAR CAPTURA 2: Documento almacenado en Cloud Firestore]
5. Creación y conexión del proyecto
Para comenzar utilizamos Node.js, React y Vite.
Desde la terminal ejecutamos:
npm create vite@latest taskflow -- --template react Después instalamos las dependencias:
cd taskflow npm install Una vez creada la aplicación, incorporamos Firebase mediante:
npm install firebase Posteriormente configuramos el archivo firebase.js, donde inicializamos la aplicación y habilitamos los servicios necesarios.
import { initializeApp } from 'firebase/app'; import { getFirestore } from 'firebase/firestore'; import { getAuth } from 'firebase/auth'; // Configuración obtenida desde Firebase Console const firebaseConfig = { // Datos de configuración de nuestra aplicación }; const app = initializeApp(firebaseConfig); export const db = getFirestore(app); export const auth = getAuth(app); De esta manera, los componentes React pueden utilizar db para realizar operaciones con Firestore y auth para gestionar las sesiones.
6. Implementación de las operaciones CRUD
Una vez establecida la conexión, implementamos las operaciones principales de la aplicación.
CRUD significa crear, leer, actualizar y eliminar información.
Crear documentos
Para guardar una tarea utilizamos addDoc().
await addDoc(collection(db, 'tareas'), { titulo: formulario.titulo, descripcion: formulario.descripcion, estado: formulario.estado, fecha: formulario.fecha, usuarioId: usuario.uid, creada: new Date().toISOString() }); Firestore genera un identificador para el documento y almacena su información.
Consultar documentos
Para recuperar las tareas usamos una consulta filtrada por el identificador del usuario:
const consulta = query( collection(db, 'tareas'), where('usuarioId', '==', usuario.uid) ); También utilizamos onSnapshot() para actualizar el listado cuando Firestore notifica cambios en los documentos.
Actualizar documentos
Para modificar una tarea utilizamos:
await updateDoc(doc(db, 'tareas', id), { estado: 'Completada' }); La actualización modifica el documento existente sin generar otro.
Eliminar documentos
Finalmente, incorporamos:
await deleteDoc(doc(db, 'tareas', id)); Esta operación elimina el documento identificado.
Con estas cuatro funciones conseguimos implementar el CRUD utilizando directamente una base de datos NoSQL.
[INSERTAR CAPTURA 3: Una tarea registrada y su documento en Firestore]
7. Seguridad y autenticación
La seguridad fue uno de los aspectos que tuvimos que considerar al conectar React con Firestore.
Si una aplicación permite leer o modificar todos los documentos sin restricciones, otros usuarios podrían acceder a información que no les pertenece.
Para evitarlo utilizamos Firebase Authentication y reglas de seguridad.
Primero habilitamos el registro con correo electrónico y contraseña.
Cuando un usuario inicia sesión, Firebase proporciona un identificador único conocido como uid.
Ese identificador se almacena también dentro de cada tarea mediante el campo usuarioId.
Después configuramos reglas de Firestore que comprueban la propiedad del documento antes de permitir determinadas operaciones.
Por ejemplo:
allow read: if request.auth != null && resource.data.usuarioId == request.auth.uid; Esta regla permite leer documentos únicamente cuando el usuario está autenticado y su identificador coincide con el propietario de la tarea.
También configuramos reglas para controlar la creación, actualización y eliminación de documentos.
Un aspecto importante es que las reglas de Firestore no sustituyen los filtros de las consultas. Por eso, además de establecer las restricciones de seguridad, nuestra consulta utiliza where('usuarioId', '==', usuario.uid).
Esto nos permitió organizar el acceso a los datos de acuerdo con cada usuario.
[INSERTAR CAPTURA 4: Reglas de seguridad de Cloud Firestore]
8. Publicación del código en GitHub
Una vez implementadas las funcionalidades principales, utilizamos GitHub para almacenar el código fuente.
El repositorio contiene los componentes React, los estilos CSS, la conexión con Firebase y los archivos necesarios para instalar y compilar la aplicación.
Para registrar y publicar los cambios utilizamos Git:
git add . git commit -m "Implementar TaskFlow con Firebase" git push origin main De esta manera, mantenemos un historial de modificaciones y podemos trabajar en equipo utilizando un mismo repositorio.
También utilizamos un archivo .gitignore para evitar publicar dependencias y archivos privados innecesarios.
Repositorio público:
https://github.com/fm2021072628/taskflow-nosql-firebase
9. Implementación en Firebase Hosting
Después de desarrollar la aplicación, necesitábamos publicarla para que pudiera abrirse desde Internet.
Para ello utilizamos Firebase Hosting.
Primero compilamos la aplicación mediante Vite:
npm run build Este comando genera una carpeta llamada dist, que contiene los archivos necesarios para publicar la aplicación.
Posteriormente utilizamos Firebase CLI:
firebase deploy --only hosting Firebase confirmó que los archivos fueron cargados y que el sitio estaba disponible públicamente.
La aplicación puede consultarse en:
https://taskflow-nosql.web.app
Con esto conseguimos separar el entorno de desarrollo local del entorno donde los usuarios pueden utilizar el sistema.
[INSERTAR CAPTURA 5: Aplicación TaskFlow publicada en Firebase Hosting]
10. Automatización con GitHub Actions
Otro de los requisitos del proyecto era implementar una forma de automatizar el despliegue.
Para ello utilizamos GitHub Actions, una herramienta que permite ejecutar procesos cuando ocurren eventos dentro de un repositorio.
En nuestro caso configuramos un flujo relacionado con los cambios en la rama principal.
El procedimiento general es:
- Se modifica el código en Visual Studio Code.
- Se envían los cambios a GitHub.
- GitHub Actions ejecuta el flujo configurado.
- Se realizan las tareas de preparación y compilación.
- Se publica la aplicación en Firebase Hosting.
Para configurar la integración utilizamos:
firebase init hosting:github Firebase generó archivos YAML dentro de .github/workflows.
Estos archivos contienen las instrucciones del proceso de despliegue.
Durante la configuración surgió una dificultad relacionada con los permisos de una cuenta de servicio en Google Cloud.
Para resolverla revisamos la configuración de IAM y asignamos los permisos necesarios para Firebase Hosting.
Después de completar estos ajustes, conseguimos ejecutar el flujo de GitHub Actions correctamente.
La ejecución quedó registrada con una marca verde, indicando que el proceso había finalizado sin errores.
Automatización:
https://github.com/fm2021072628/taskflow-nosql-firebase/actions
[INSERTAR CAPTURA 6: Ejecución correcta de GitHub Actions]
11. Pruebas y resultados
Para comprobar el funcionamiento del proyecto realizamos diferentes pruebas sobre sus funcionalidades principales.
| Prueba | Resultado |
|---|---|
| Crear una tarea | Se observó un nuevo documento en Firestore |
| Consultar tareas | Se visualizaron los documentos registrados |
| Editar una tarea | Se actualizaron sus datos |
| Cambiar de estado | La interfaz reflejó el nuevo estado |
| Eliminar tareas | Se ejecutó la operación de eliminación |
| Compilar la aplicación | Vite generó los archivos de producción |
| Publicar en la nube | Firebase Hosting confirmó el despliegue |
| Automatización | GitHub Actions mostró una ejecución exitosa |
Las pruebas permitieron comprobar la conexión entre los distintos componentes del sistema.
También identificamos oportunidades de mejora relacionadas con las validaciones de seguridad, las pruebas entre múltiples usuarios y la optimización de los archivos JavaScript generados.
12. ¿Qué aprendimos durante el desarrollo?
Uno de los aprendizajes principales fue comprender cómo funciona una base de datos NoSQL orientada a documentos.
Aunque Firestore permite trabajar sin definir tablas relacionales, sigue siendo necesario organizar los datos de manera adecuada.
También comprobamos que la autenticación y la seguridad no son exactamente lo mismo.
Firebase Authentication identifica al usuario, mientras que las reglas de Firestore determinan a qué información puede acceder.
Otro aprendizaje importante fue la automatización. Configurar GitHub Actions nos permitió conocer cómo se relacionan el control de versiones y el despliegue de una aplicación web.
Además, durante el proceso aparecieron errores relacionados con la configuración de Firebase y los permisos de Google Cloud, lo que nos obligó a revisar las herramientas y comprender mejor su funcionamiento.
13. Posibles mejoras
Aunque TaskFlow cumple su objetivo principal, todavía podríamos implementar nuevas funcionalidades.
Entre ellas se encuentran la recuperación de contraseñas, las notificaciones de tareas próximas a vencer, la búsqueda de actividades y la clasificación por prioridad.
También sería conveniente incorporar pruebas automatizadas para comprobar las operaciones CRUD y las reglas de seguridad.
En cuanto a la arquitectura, podríamos optimizar la carga del frontend y mejorar las consultas cuando aumente la cantidad de documentos almacenados.
14. Conclusiones
Desarrollar TaskFlow nos permitió comprender cómo se pueden integrar diferentes servicios para construir una aplicación web funcional.
En particular, trabajar con Firebase Firestore nos ayudó a conocer una forma de almacenar información mediante documentos NoSQL, sin depender de una base de datos relacional tradicional.
También comprobamos la importancia de incorporar autenticación y reglas de seguridad desde las primeras etapas del desarrollo.
Por otra parte, Firebase Hosting nos permitió publicar la aplicación en Internet, mientras que GitHub Actions facilitó la automatización del proceso de despliegue.
Considero que uno de los aspectos más interesantes del proyecto fue entender cómo se relacionan estas herramientas. Aunque cada una cumple una función distinta, todas participan en el funcionamiento de una misma aplicación.
Finalmente, este trabajo nos permitió aplicar conocimientos de desarrollo web, bases de datos NoSQL, seguridad, servicios en la nube y automatización mediante un ejemplo práctico que puede continuar mejorándose.
Enlaces del proyecto
Código fuente en GitHub:
https://github.com/fm2021072628/taskflow-nosql-firebase
Aplicación publicada en Firebase Hosting:
https://taskflow-nosql.web.app
Automatización con GitHub Actions:
https://github.com/fm2021072628/taskflow-nosql-firebase/actions
Video demostrativo:
[PENDIENTE: agregar enlace del video público de máximo cinco minutos]
Referencias
- React: https://react.dev/
- Vite: https://vite.dev/
- Firebase Firestore: https://firebase.google.com/docs/firestore
- Firebase Authentication: https://firebase.google.com/docs/auth
- Firebase Security Rules: https://firebase.google.com/docs/firestore/security/get-started
- Firebase Hosting: https://firebase.google.com/docs/hosting
- GitHub Actions: https://docs.github.com/en/actions
