Biblioteca VirtualTrabajo final / Taller de Programación I
Universidad del Caribe / Mayo 2026
Biblioteca Virtual.
Una plataforma web completa para gestionar el catálogo, los préstamos y las reservas
de una biblioteca universitaria. Desarrollada como trabajo final del Taller de
Programación I.
.NET 10ReactPostgreSQLCloudflare Tunnel
Maestro / Victorino Ramírez Reyes01 / 34
Biblioteca VirtualSección 01 / Introducción
01 El equipo
Cinco estudiantes, un solo proyecto.
Cada integrante asumió responsabilidad sobre un área del sistema. La presentación
está organizada por temas: cuando aparece tu nombre en la barra inferior, te toca exponer.
AA
Alvaro Acevedo MarianoArquitectura / Despliegue
DA
Dauri Abad SepúlvedaFrontend / UX·UI
DS
Daniel AsencioBackend / API
JB
Johancer Basiel BonetBase de datos / Modelado
JN
Jason Núñez De Los SantosAdministración / Testing
VR
Victorino Ramírez ReyesMaestro / Taller Programación I
Todos / Presenta Alvaro02 / 34
Biblioteca VirtualHoja de ruta
02 Contenido
Lo que vamos a recorrer.
Visión general — qué resuelve y para quién
Stack tecnológico — las herramientas que elegimos
Arquitectura — capas y separación de responsabilidades
Base de datos — modelo relacional con once tablas
Backend — .NET 10, Entity Framework, JWT
Frontend — React, Vite, Tailwind, diseño pastel
Funcionalidades — recorrido visual de cada pantalla
Despliegue — Docker en servidor casero + Cloudflare Tunnel
Dificultades — los problemas reales y cómo los resolvimos
Aprendizajes — lo que nos llevamos del proyecto
Alvaro03 / 34
Biblioteca VirtualSección 02 / El proyecto
03 El problema
Una biblioteca con libreta y lápiz no escala.
En muchas bibliotecas universitarias todavía se controlan los préstamos en cuadernos,
las multas se calculan a mano y los catálogos viven en hojas de cálculo dispersas.
El resultado: libros perdidos, multas mal cobradas, lectores frustrados.
Quisimos resolver un problema concreto: que cualquier estudiante pueda buscar,
reservar y prestar libros desde su celular, mientras el bibliotecario tiene control
total y trazabilidad de cada movimiento.
Lo que falla hoy
Catálogo desactualizado o inconsistente
Reservas que se pierden o se duplican
Cálculo manual de multas por retraso
Sin trazabilidad de quién hizo qué
Lo que entregamos
Plataforma web accesible desde cualquier dispositivo
Préstamos, reservas y multas automatizadas
Panel administrativo con auditoría completa
Alvaro04 / 34
Biblioteca VirtualVisión general
04 La solución
Una plataforma web con dos caras y un solo cerebro.
Para el lector
Catálogo en línea
Buscar libros por título, autor, categoría o ISBN. Reservar lo no disponible.
Solicitar préstamos en un clic. Recibir notificaciones automáticas.
Para el bibliotecario
Panel de control
Aprobar préstamos, asignar ejemplares físicos, procesar devoluciones y
consultar inventario en tiempo real desde un dashboard único.
Para la institución
Auditoría completa
Cada acción queda registrada. El histórico es append-only: nadie puede
«borrar» su rastro. Total transparencia operativa.
11
Tablas en la BD
36
Endpoints REST
22
Pantallas en la app
17/17
Tests automatizados
Alvaro05 / 34
Biblioteca VirtualCómo funciona
05 Flujo del sistema
Del catálogo a la devolución.
Cada préstamo recorre un camino claro. El lector busca un libro y lo solicita;
el bibliotecario aprueba y asigna un ejemplar físico; el lector lo usa por catorce
días y lo devuelve. Si se atrasa, el sistema genera la multa de manera automática.
Cada paso queda registrado en la auditoría.
Lector — busca, solicita, retira, devuelve y, si aplica, paga la multa.
Sistema — valida disponibilidad, calcula vencimientos y genera multas.
Bibliotecario — aprueba solicitudes, asigna ejemplares y procesa devoluciones.
Cada decisión queda registrada para que nada se pierda.
Johancer Basiel06 / 34
Biblioteca VirtualSección 03 / Arquitectura
06 Stack tecnológico
Las herramientas que elegimos.
Cada elección se justifica por una razón concreta. Nada está acá por moda.
Backend
.NET 10
ASP.NET Core Web API. Compilado, fuertemente tipado, rendimiento de primer nivel
y soporte oficial de Microsoft a largo plazo.
Frontend
React 18 + Vite
Componentes reutilizables, hot reload instantáneo y build de producción
optimizado por defecto. JSX para mantener la lógica cerca del marcado.
Estilos
Tailwind CSS v4
Sistema de diseño basado en utilidades. Paleta pastel personalizada en
tailwind.config.js.
Base de datos
PostgreSQL 16
Robusta, gratuita, y la mejor opción open-source. Migraciones gestionadas
por Entity Framework Core sobre Npgsql.
Auth
JWT + BCrypt
Tokens firmados con HMAC-SHA256 para sesiones sin estado. Contraseñas
con BCrypt — nunca en texto plano.
Testing
Vitest + xUnit
Vitest para el frontend (jsdom + Testing Library). xUnit para los
servicios .NET. Playwright para tests E2E.
Contenedores
Docker + Compose
Cada servicio en su contenedor. Una sola red interna. Reproducible en
cualquier máquina que tenga Docker.
Despliegue
Cloudflare Tunnel
Servidor casero expuesto sin abrir puertos del router, sin IP pública,
con HTTPS automático.
Alvaro07 / 34
Biblioteca VirtualArquitectura
07 Diseño de arquitectura
Tres capas, una responsabilidad cada una.
Separamos la aplicación en tres capas independientes que se comunican por contratos
bien definidos. Cada capa puede evolucionar sin romper a las otras.
Presentación — React. Lo único que sabe es cómo mostrar datos
y cómo enviar peticiones HTTP. Ignora todo lo demás.
Aplicación — Controllers + Services en .NET. Recibe peticiones,
valida, orquesta lógica de negocio y devuelve respuestas.
Datos — Entity Framework Core + PostgreSQL. Persistencia,
consultas y migraciones. El esquema vive acá.
Cada capa habla solo con la inmediatamente debajo. Sin atajos.
Johancer Basiel08 / 34
Biblioteca VirtualBase de datos
08 Diseño relacional
Once tablas, relaciones explícitas.
El modelo nació de las entidades del dominio real: libros, autores, categorías,
ejemplares físicos, usuarios, préstamos, reservas, multas. Cada relación tiene
sentido en el negocio.
Libro → tiene muchos Ejemplares
Préstamo conecta Usuario + Ejemplar
Reserva tiene cola con posicionCola
Multa deriva de un Préstamo vencido
AuditLog registra TODO (append-only)
PostgreSQL 16
Npgsql provider
EF Core migrations
Johancer Basiel09 / 34
Biblioteca VirtualSección 04 / Backend
09 .NET 10 + ASP.NET Core
El motor está escrito en C#.
El backend es una API REST construida con ASP.NET Core sobre .NET 10,
la versión más reciente y soportada a largo plazo. Está organizado en cuatro capas
internas, todas dentro del mismo proyecto.
Controllers — exponen los endpoints HTTP. Validan input y
delegan al service correspondiente.
Services — la lógica de negocio. Calculan multas, gestionan
colas de reserva, orquestan préstamos.
DbContext — el puente con PostgreSQL. Las migraciones se
ejecutan automáticamente al arrancar.
DTOs — modelos de transporte. Nunca exponemos entidades
directas al cliente.
// Controllers/PrestamosController.cs[ApiController][Route("api/prestamos")][Authorize]public class PrestamosController : ControllerBase
{
private readonly ICirculacionService _service;
[HttpPost]public async Task<IActionResult> Solicitar(
SolicitarPrestamoDto dto)
{
var prestamo = await
_service.SolicitarAsync(User, dto);
return CreatedAtAction(
nameof(Get),
new { id = prestamo.Id },
prestamo);
}
}
Logging
Serilog
Validación
DataAnnotations
Daniel Asencio10 / 34
Biblioteca VirtualBackend / Seguridad
10 Autenticación
Tokens JWT y contraseñas con BCrypt.
El backend no guarda sesiones. Cada petición protegida lleva un JSON Web Token
firmado por el servidor en su header. El token contiene el ID y el rol del usuario, y
expira a las 8 horas.
Login — el usuario envía email + password. El servidor compara
con BCrypt y, si coincide, emite un JWT firmado con HMAC-SHA256.
Storage — el frontend guarda el token en localStorage.
Cada petición — Axios agrega
Authorization: Bearer <token>.
Validación — un middleware verifica firma + expiración
antes de llegar al controller.
Roles — atributos [Authorize(Roles)]
protegen los endpoints sensibles.
Las contraseñas nunca salen del backend, ni siquiera para los administradores.
POST /api/auth/login
POST /api/auth/registro
GET /api/usuarios/yo
GET /api/admin/usuarios
PUT /api/admin/usuarios/{id}
Catálogo
GET /api/libros?search=...
GET /api/libros/{id}
POST /api/admin/libros
PUT /api/admin/libros/{id}
DELETE /api/admin/libros/{id}
Circulación
GET /api/prestamos
POST /api/prestamos
POST /api/prestamos/{id}/aprobar
POST /api/prestamos/{id}/devolver
POST /api/prestamos/{id}/renovar
Multas & Reservas
GET /api/reservas
POST /api/reservas
POST /api/reservas/{id}/cancelar
GET /api/multas
POST /api/multas/{id}/pago
Todos los endpoints siguen las convenciones REST: GET para leer, POST para crear,
PUT para actualizar y DELETE para borrar. Los códigos de estado son consistentes
(200, 201, 400, 401, 403, 404, 500).
Daniel Asencio12 / 34
Biblioteca VirtualSección 05 / Frontend
12 React + Vite
Una SPA reactiva, sin servidor de render.
El frontend es una Single Page Application escrita en React 18 con
Vite como bundler. Todo el routing es en cliente con React Router.
La comunicación con el backend pasa por Axios.
Componentes — pequeños, reutilizables, con props tipadas.
Cada pantalla es una page; cada bloque visual es un componente.
Estado global — Context API para autenticación.
useAuth()
expone el usuario actual, el token y la función de logout.
Estado local — useState / useEffect en cada page.
Servicios — capa
services/
que envuelve Axios. Centraliza interceptores y manejo de errores.
Routing — rutas públicas, privadas y de admin con
componente ProtectedRoute.
La interfaz usa una paleta cálida con tonos pastel: lavanda como
primario, durazno y menta como acentos, sobre un fondo
crema. La tipografía es Plus Jakarta Sans para que se sienta moderna pero seria.
Portadas reales de libros — pedimos las tapas a la API
pública de Open Library por ISBN; si no encuentra, caemos a Unsplash por categoría;
si todo falla, mostramos un gradiente pastel con iniciales.
Responsive — diseño mobile-first. Funciona en celular,
tablet y escritorio sin recargar layout.
LAVANDA
DURAZNO
MENTA
CIELO
SOL
CREMA
Plus Jakarta Sans
Tailwind v4
Mobile-first
Pastel / cálido
Dauri Abad14 / 34
Biblioteca VirtualSección 06 / Funcionalidades
14 Catálogo público
Explorar libros sin necesidad de cuenta.
Cualquier visitante puede buscar libros, ver detalles y revisar disponibilidad.
La búsqueda es por texto libre (título, autor, ISBN), con filtros por categoría
y disponibilidad.
Búsqueda en tiempo real
Filtros por autor, categoría, formato
Ordenamiento (A-Z, por año, por disponibilidad)
Paginación cliente-servidor
Tapas reales desde Open Library
/catalogo — GET /api/libros
Dauri Abad15 / 34
Biblioteca VirtualFuncionalidades / Detalle
15 Detalle de libro
Toda la ficha del libro, con acciones contextuales.
/catalogo/{id}
La página de detalle muestra la sinopsis, autor, categoría, año, ISBN, editorial,
formato y ubicación física. Si hay ejemplares disponibles, el botón es
Solicitar préstamo; si no, es Reservar.
Información completa del libro
Lista de ejemplares físicos disponibles
Acción adaptativa según disponibilidad
Si no hay sesión, redirige a login
Dauri Abad16 / 34
Biblioteca VirtualFuncionalidades / Auth
16 Acceso al sistema
Iniciar sesión o crear cuenta.
/login
/registro
Layout dividido en dos paneles: a la izquierda el branding de Unicaribe con un mensaje
de bienvenida, a la derecha el formulario. Las validaciones se hacen en cliente y en
servidor. Las contraseñas siempre se envían sobre HTTPS y se almacenan con BCrypt.
Dauri Abad17 / 34
Biblioteca VirtualFuncionalidades / Lector
17 Mi biblioteca
Un dashboard de un vistazo.
/mi-biblioteca
Al iniciar sesión, el lector ve su panel personal con tres tarjetas resumen:
préstamos activos, reservas pendientes y multas por pagar.
Préstamos activos (máximo 3)
Reservas con cuenta regresiva
Total de multas en pesos dominicanos
Acceso rápido a cada sección
Dauri Abad18 / 34
Biblioteca VirtualFuncionalidades / Lector
18 Mis préstamos
Solicitar, renovar, devolver.
El lector ve todos sus préstamos con estado, ejemplar asignado y fecha de
vencimiento. Si está activo, puede renovar. Si vence, se genera multa automática.
Fechas de devolución calculadas (14 días estándar)
Multa automática por retraso (RD$50 por día)
/prestamos
Dauri Abad19 / 34
Biblioteca VirtualFuncionalidades / Lector
19 Mis reservas
La cola justa para libros sin stock.
/reservas
Cuando todos los ejemplares de un libro están prestados, el lector se anota
en la cola. El sistema le asigna posición y, cuando llega su turno, le da
48 horas para retirarlo.
Posición en cola visible
Notificación cuando se asigna el ejemplar
48 horas para retirar antes de pasar al siguiente
Cancelable desde el panel
Dauri Abad20 / 34
Biblioteca VirtualFuncionalidades / Lector
20 Mis multas
Pagos simulados, registro real.
Las multas se calculan automáticamente al devolver un préstamo vencido. El usuario
ve el detalle y puede iniciar un pago simulado (no se conecta a un banco real;
es una pasarela de demostración con recibos y referencias generadas).
Cálculo automático por días de retraso
Pasarela simulada con aprobación/rechazo
Historial de intentos de pago
Recibo con número de referencia
/multas
Dauri Abad21 / 34
Biblioteca VirtualFuncionalidades / Lector
21 Notificaciones y perfil
Bandeja personal + datos de cuenta.
/notificaciones
/perfil
El sistema genera notificaciones internas cuando ocurre algo relevante: préstamo
aprobado, reserva asignada, multa generada, pago confirmado. Se guardan en la base
de datos y aparecen en la bandeja del usuario (no se envía email ni SMS real).
Dauri Abad22 / 34
Biblioteca VirtualSección 07 / Administración
22 Panel administrativo
Métricas operativas en tiempo real.
/admin — Dashboard ejecutivo
El dashboard de administrador muestra de un vistazo el pulso de la biblioteca:
cantidad de libros, usuarios, préstamos activos, vencidos, reservas y multas
pendientes.
Seis KPIs principales en tarjetas pastel
Top libros más prestados
Usuarios más activos
Préstamos por mes (gráfico de barras)
Categorías populares
Jason Núñez23 / 34
Biblioteca VirtualAdministración / Usuarios
23 Gestión de usuarios
Activar, desactivar, cambiar rol.
El administrador puede ver todos los usuarios registrados, su rol (lector o
administrador) y su estado (activo o inactivo). Puede activar o desactivar
cuentas con un clic.
Lista completa con búsqueda
Roles: Lector, Administrador
Activación/desactivación con confirmación
Auditoría: cada cambio queda registrado
/admin/usuarios
Jason Núñez24 / 34
Biblioteca VirtualAdministración / Catálogo
24 CRUD de catálogo
Crear, editar y eliminar libros, autores, categorías.
/admin/catalogo — CRUD completo
El bibliotecario gestiona el catálogo desde acá: agrega libros nuevos, define
autores y categorías, edita la información existente o elimina entradas
(con confirmación destructiva).
Tres formularios paralelos
Validación servidor + cliente
Confirmación antes de borrar
Stock inicial al crear
Jason Núñez25 / 34
Biblioteca VirtualAdministración / Circulación
25 Circulación
Aprobar préstamos, preparar reservas.
El corazón operativo del sistema. Cuando un lector solicita un préstamo, queda
en estado pendiente. El bibliotecario revisa la solicitud, asigna un ejemplar
físico disponible y aprueba.
Solicitudes pendientes de aprobación
Préstamos activos (con devolución)
Reservas listas para retirar
Asignación de ejemplar físico
/admin/circulacion
Jason Núñez26 / 34
Biblioteca VirtualAdministración / Inventario
26 Inventario físico
Cada copia tiene su código.
/admin/inventario
El sistema distingue entre libro (la entrada del catálogo) y
ejemplar (la copia física). Cada ejemplar tiene su código único,
estado y ubicación en la biblioteca.
Códigos únicos por ejemplar
Estados: Disponible, Prestado, Reservado
Tipo: Físico o Digital
Ubicación: estante físico
Jason Núñez27 / 34
Biblioteca VirtualAdministración / Auditoría
27 Auditoría
Cada acción queda registrada.
La auditoría es append-only: una vez que un evento entra, nadie
puede borrarlo ni modificarlo. Es la garantía de trazabilidad para la institución.
Quién hizo la acción
Qué entidad cambió
Cuándo (con timestamp)
Resultado (éxito o fallo)
Si no se puede borrar, no se puede ocultar.
/admin/auditoria
Jason Núñez28 / 34
Biblioteca VirtualSección 08 / Despliegue
28 Contenedores Docker
Todo en cajas reproducibles.
Cada componente del sistema corre en un contenedor Docker aislado. Una sola red
interna los conecta. Ningún puerto está abierto al exterior — el acceso es
exclusivo a través del túnel.
postgres — base de datos con volumen persistente
backend — ASP.NET con build multi-stage (sdk → runtime)
El servidor está en una PC vieja en casa. No abrimos puertos del router. No
pagamos hosting. Cloudflare Tunnel actúa como puente: el agente
cloudflared abre conexiones
salientes hacia los edges de Cloudflare. Cuando alguien visita
nuestro dominio, Cloudflare manda la petición por el túnel.
Cero puertos abiertos en el router
HTTPS automático con certificado de Cloudflare
IP pública oculta — Cloudflare es la cara
Sobrevive a cambios de IP del ISP
Protección DDoS incluida en el plan Free
Alvaro30 / 34
Biblioteca VirtualSección 09 / Calidad
30 Testing automatizado
El código se prueba solo.
Cada vez que se modifica el código, los tests se ejecutan automáticamente.
Si algo se rompe, lo sabemos antes de que un usuario lo descubra. Es la red
de seguridad del proyecto.
17
Tests frontend
9
Suites backend
100%
Verde en CI
Frontend
Vitest + Testing Library
Tests de componentes con jsdom. Mockeo de servicios. Cobertura de pages,
contexts y guardas de ruta.
Backend
xUnit + WebApplicationFactory
Tests de integración que arrancan la API real contra una BD en memoria.
Validan endpoints, autenticación y reglas de negocio.
End-to-End
Playwright
Recorridos completos en navegador real (Chromium). Simulan flujos: login,
reserva, devolución, pago de multa.
Jason Núñez31 / 34
Biblioteca VirtualSección 10 / Lecciones
31 Dificultades
Los problemas reales que enfrentamos.
01
Migraciones de EF Core al arrancar
El backend intentaba conectar antes de que Postgres estuviera listo y fallaba.
Resuelto: depends_on con condition: service_healthy en compose.
02
HTTPS detrás del túnel
ASP.NET creía que la conexión era HTTP y armaba redirects rotos.
Resuelto: middleware ForwardedHeaders confía en X-Forwarded-Proto.
03
Imagen .NET 10 ya trae usuario «app»
El Dockerfile intentaba crear ese usuario y chocaba (novedad de .NET 10).
Resuelto: eliminar el groupadd/useradd, usar el usuario que ya viene.
04
DNS de Docker fallaba con Cloudflare
cloudflared no resolvía argotunnel.com vía el resolver embebido (127.0.0.11).
Resuelto: forzamos DNS público (1.1.1.1) en el container del túnel.
05
SSL universal solo cubre un nivel
api.biblioteca.alvaroacevedo.dev fallaba el handshake — son dos niveles.
Resuelto: renombramos a api-biblioteca (un solo nivel).
06
Tapas de libros de ISBN ficticios
El seed usa ISBN 978-0-00-X que no existen en Open Library.
Resuelto: cascada portadaUrl → Open Library → Unsplash → gradiente.
Alvaro32 / 34
Biblioteca VirtualAprendizajes
32 Lo que nos llevamos
Lo que aprendimos en el camino.
Sobre programar
Separar capas no es burocracia; es lo que hace que el código siga vivo en seis meses.
Validar dos veces: en el cliente para UX, en el servidor para seguridad. Nunca solo uno.
Los tipos fuertes (C#) detectan errores que JavaScript te deja pasar.
Los nombres importan. Un método bien nombrado es documentación gratis.
Sobre construir software
Docker no es magia: es el seguro contra «en mi máquina sí funciona».
Los tests no son opcionales; son lo que permite cambiar código sin miedo.
La trazabilidad (auditoría, logs) salva carreras en producción.
Deployar es la mitad del proyecto. Codear local es la parte fácil.
Programar es resolver problemas. Las herramientas cambian; el método se queda.
Todos33 / 34
Biblioteca VirtualFin
33 Cierre
Gracias por escucharnos.
El proyecto está vivo en
biblioteca.alvaroacevedo.dev
y el código fuente está abierto en
github.com/varocode/biblioteca-virtual.