Museo de Arte Moderno de Barranquilla
MAMB es una aplicacion web progresiva (PWA) desarrollada para el Museo de Arte Moderno de Barranquilla. Permite a estudiantes y visitantes explorar la galeria del museo, subir sus propias obras y participar en juegos interactivos.
Desarrollado en colaboracion con el Museo de Arte Moderno de Barranquilla y la Universidad Simon Bolivar, Barranquilla.
Descripcion general
El sistema busca fomentar la creatividad y la participacion artistica de ninos y visitantes del museo, ofreciendo una plataforma digital interactiva accesible desde cualquier dispositivo.
Objetivos del proyecto
- Incentivar la creatividad infantil a traves del arte digital
- Facilitar la exposicion de obras artisticas de visitantes
- Crear una experiencia digital interactiva y educativa
- Acercar el museo a nuevas audiencias mediante tecnologia web
- Promover el aprendizaje mediante actividades ludicas
Publico objetivo
- Estudiantes de primaria y secundaria en visitas escolares
- Visitantes del museo de todas las edades
- Comunidad artistica de Barranquilla
Stack tecnologico
Frontend
| Tecnologia | Uso |
|---|---|
| HTML5 | Estructura semantica de la SPA |
| CSS3 | Diseno visual responsive, mobile-first |
| JavaScript Vanilla | Logica de la app, sin frameworks |
| PWA / Service Worker | Instalacion nativa y cache offline |
Backend
| Tecnologia | Uso |
|---|---|
| Node.js | Runtime del servidor |
| Express.js | Framework para la API REST |
| PostgreSQL | Base de datos relacional |
| JWT + bcryptjs | Autenticacion y hashing de contrasenas |
| Helmet | Headers HTTP de seguridad |
| CORS | Control de origenes cruzados |
| Multer | Subida de imagenes (hasta 20 MB) |
| Morgan | Logging de peticiones HTTP |
Infraestructura
| Servicio | Uso |
|---|---|
| Render | Hosting del backend + frontend |
| Namecheap | Dominio mamb.online |
| GitHub Pages | Landing page estatica |
Componentes del sistema
El proyecto esta compuesto por tres modulos principales:
Landing Page
Sitio web informativo alojado en GitHub Pages donde los visitantes conocen el museo y acceden a la aplicacion principal.
- URL: risharddv.github.io/MAMBQ
- Tecnologias: HTML, CSS, JavaScript
- Despliegue automatico desde la rama
main
Aplicacion Web (PWA)
Aplicacion principal con 9 pantallas interactivas:
- Inicio — splash + ingreso de nombre
- Galeria — listado de obras con busqueda y filtros
- Subir obra — formulario con moderacion automatica
- Juego de memoria — mini-juego con datos de arte
- Perfil — configuracion del visitante
- Colecciones — obras favoritas guardadas
- Acerca de — informacion del museo
- Detalle — vista ampliada de una obra
- Autenticacion — registro e inicio de sesion
Backend API
API REST que gestiona toda la logica del servidor:
- Obras — CRUD completo con subida de imagenes
- Interacciones — likes y calificaciones (1-5 estrellas)
- Usuarios — registro, login, perfiles
- Moderacion — filtro de contenido inapropiado
- Seguridad — JWT, Helmet, CORS
Caracteristicas principales
Galeria virtual
Obras del museo y obras subidas por visitantes. Busqueda por titulo o artista, filtros por tecnica (Oleo, Acuarela, Acrilico, Mixta, Escultura).
Subida de obras
Formulario con seleccion de imagen, titulo, descripcion, tecnica y avatar. Moderacion automatica de contenido antes de publicar.
Juego de memoria
Mini-juego de cartas con datos curiosos sobre pinturas famosas del MAMB. Encuentra los pares para desbloquear informacion educativa.
Sistema de interaccion
- Likes — contador de corazones por obra
- Calificaciones — sistema de 1 a 5 estrellas con promedio visible
PWA instalable
Service Worker con estrategia de cache inteligente. Instalable en movil y escritorio como app nativa. Soporte offline con fallback a localStorage.
Moderacion de contenido
Filtro automatico de apodos inapropiados con deteccion de leet-speak (ej: h4ck3r), homoglifos Unicode y lista de palabras prohibidas.
Perfiles de visitante
Cada usuario tiene nombre, ciudad, avatar seleccionable (8 opciones) y historial de obras subidas.
Enlaces del proyecto
| Entorno | URL |
|---|---|
| Aplicacion (produccion) | mamb.online |
| Render (directo) | mamb-qsi0.onrender.com |
| Landing page | risharddv.github.io/MAMBQ/landing |
| Repositorio | github.com/risharddv/MAMBQ |
| Documentacion | risharddv.github.io/MAMBQ |
Instalacion
Guia para poner en marcha el proyecto MAMB en tu maquina local.
Requisitos previos
Software necesario
| Requisito | Version minima |
|---|---|
| Node.js | v18+ |
| PostgreSQL | v14+ |
| Git | cualquier version reciente |
Verificar instalacion
node -v # debe mostrar v18 o superior
psql --version
git --version
Clonar el repositorio
git clone https://github.com/risharddv/MAMBQ.git
cd MAMBQ
Configurar el backend
Variables de entorno
Crea un archivo .env en la carpeta backend/:
PORT=3000
DATABASE_URL=postgresql://usuario:contraseña@localhost:5432/mamb
JWT_SECRET=tu_clave_secreta_aqui
NODE_ENV=development
Nunca subas el archivo .env al repositorio. Ya esta incluido en .gitignore.
Descripcion de variables
| Variable | Descripcion |
|---|---|
PORT | Puerto donde escucha el servidor (default: 3000) |
DATABASE_URL | Cadena de conexion a PostgreSQL |
JWT_SECRET | Clave secreta para firmar tokens JWT |
NODE_ENV | Entorno de ejecucion (development o production) |
Instalar dependencias
cd backend
npm install
Arrancar el servidor
npm run start
El servidor quedara disponible en http://localhost:3000.
Ejecutar el frontend
Con servidor local
El frontend es una SPA estatica que no necesita build ni dependencias adicionales:
cd frontend
npx http-server -p 8080
Abre http://localhost:8080 en tu navegador.
Sin servidor (modo rapido)
Tambien puedes abrir frontend/index.html directamente en el navegador.
Algunas funciones de red (API calls) requieren que el backend este corriendo para funcionar correctamente.
Base de datos PostgreSQL
Crear la base de datos
Asegurate de tener PostgreSQL corriendo y crea la base de datos:
CREATE DATABASE mamb;
Creacion automatica de tablas
El backend crea las tablas automaticamente al arrancar si no existen. No necesitas ejecutar migraciones manualmente.
Verificar conexion
Puedes probar que la base de datos esta conectada visitando:
http://localhost:3000/api/health
Deberia responder:
{ "status": "ok", "museo": "MAMB", "db": "PostgreSQL" }
Instalar como PWA
En dispositivo movil
Una vez que la app este corriendo (local o en produccion):
- Abre la app en Chrome o un navegador compatible
- Busca el icono de instalacion en la barra de direcciones
- Selecciona "Instalar" o "Anadir a pantalla de inicio"
En escritorio (Chrome)
- Abre la app en Chrome
- Haz clic en el icono de instalacion en la barra de URL
- Confirma la instalacion
La app se instalara como aplicacion nativa en tu dispositivo.
Resolucion de problemas
El backend no arranca
- Verifica que PostgreSQL este corriendo
- Revisa que
DATABASE_URLen.envsea correcta - Asegurate de haber ejecutado
npm install
La app no se conecta al backend
- Verifica que el backend este corriendo en el puerto correcto
- Revisa la consola del navegador para errores de CORS
- En modo local, el frontend debe apuntar a
http://localhost:3000
Guia de uso
La aplicacion MAMB cuenta con 9 pantallas principales. A continuacion se describe cada una con su funcionalidad.
Inicio
Pantalla de bienvenida donde el visitante ingresa su nombre para comenzar la experiencia.
Elementos de la pantalla
- Campo de texto para ingresar nombre de visitante
- Accesos directos a la galeria y a subir una obra
- Carrusel de obras destacadas
Galeria
Vista principal con todas las obras del museo y de los visitantes.
Busqueda y filtros
- Buscar por titulo o nombre del artista
- Filtrar por tecnica artistica:
- Oleo
- Acuarela
- Acrilico
- Mixta
- Escultura
Interacciones en la galeria
- Dar like a una obra con un toque
- Ver contador de likes acumulados
- Acceder al detalle completo de cada pieza
Subir obra
Formulario para que los visitantes publiquen su propia obra.
Pasos para subir
- Selecciona o toma una fotografia de la obra
- Ingresa titulo y descripcion
- Selecciona la tecnica artistica
- Elige un avatar y apodo de visitante
- Envia el formulario
Moderacion automatica
El sistema filtra automaticamente nombres inapropiados antes de publicar, usando:
- Deteccion de leet-speak (ej:
h4ck3r) - Deteccion de homoglifos Unicode
- Lista de palabras prohibidas
Juego de memoria
Mini-juego de cartas con datos curiosos sobre pinturas famosas del MAMB.
Como jugar
- Se muestran cartas boca abajo
- Voltea dos cartas por turno
- Encuentra los pares para desbloquear datos de cada obra
- Completa el tablero para ganar
Objetivo educativo
Cada par desbloqueado revela informacion sobre una pintura famosa: autor, tecnica, ano y datos curiosos.
Perfil
Gestiona tu informacion de visitante.
Datos del perfil
- Apodo (nombre de usuario)
- Ciudad de origen
- Avatar seleccionado
Seleccion de avatar
8 opciones de avatar disponibles, generados con la API de DiceBear.
Historial de obras
Lista de todas las obras que el visitante ha subido a la plataforma.
Colecciones
Explora las colecciones permanentes del museo.
Organizacion
Las colecciones estan organizadas por sala o artista. Puedes guardar tus obras favoritas para acceder rapidamente.
Acerca del museo
Informacion sobre el Museo de Arte Moderno de Barranquilla.
Contenido
- Historia del museo
- Mision y vision cultural
- Equipo detras del proyecto
- Informacion de contacto
Detalle de obra
Vista expandida de una obra especifica.
Informacion mostrada
| Elemento | Descripcion |
|---|---|
| Imagen | Vista ampliada de la obra |
| Titulo | Nombre de la obra |
| Autor | Apodo del visitante o artista |
| Tecnica | Tipo de tecnica artistica |
| Descripcion | Texto descriptivo de la obra |
Sistema de interaccion
- Likes — contador de corazones acumulados
- Calificacion — promedio de estrellas (1-5)
- Boton calificar — permite asignar 1 a 5 estrellas
Autenticacion
Sistema de registro e inicio de sesion.
Registro
- Nombre de usuario (apodo)
- Ciudad
- Seleccion de avatar
- Contrasena
Inicio de sesion
- Login con apodo y contrasena
- Token JWT almacenado de forma segura
Sesion y offline
- Token con expiracion automatica
- Sincronizacion con
localStoragepara soporte offline - Si el token expira, se solicita nuevo login
Landing Page
La landing page es el sitio web informativo del proyecto MAMB. Esta alojada en GitHub Pages y sirve como punto de entrada para que los visitantes conozcan el museo antes de acceder a la aplicacion principal.
URL: risharddv.github.io/MAMBQ
Proposito
La landing page cumple tres funciones principales:
Presentar el museo
Informacion sobre el MAMB, su mision cultural y su importancia para la comunidad artistica de Barranquilla.
Mostrar el proyecto
Descripcion de la aplicacion web, sus funcionalidades principales y las tecnologias utilizadas.
Redirigir a la app
Enlace directo a la PWA en mamb.online para que los visitantes accedan rapidamente.
Estructura del codigo
La landing se encuentra en la carpeta Landing MAMB/ del repositorio:
Archivos principales
Landing MAMB/
├── index.html # Estructura HTML de la pagina
├── index.js # Interacciones y animaciones
├── styles.css # Estilos visuales
└── img/ # Imagenes y recursos graficos
Descripcion de archivos
| Archivo | Funcion |
|---|---|
index.html | Estructura semantica de la pagina (~398 lineas) |
index.js | Animaciones, scroll suave e interacciones (~200 lineas) |
styles.css | Diseno visual responsive |
img/ | Imagenes del museo y del proyecto |
Tecnologias
| Tecnologia | Uso |
|---|---|
| HTML5 | Estructura semantica |
| CSS3 | Diseno visual y responsive |
| JavaScript | Animaciones e interacciones |
| GitHub Pages | Hosting gratuito |
Despliegue
GitHub Pages
La landing se despliega automaticamente desde la rama main del repositorio mediante GitHub Pages. Cualquier cambio que se suba a main se refleja en produccion en minutos.
Configuracion en GitHub
- Ve a Settings > Pages en el repositorio
- Selecciona la rama
maincomo source - La URL publica sera
https://risharddv.github.io/MAMBQ/
Actualizaciones
Cada git push a la rama main actualiza automaticamente la landing page sin necesidad de configuracion adicional.
Despliegue en Render
La aplicacion MAMB (frontend + backend) esta desplegada en Render, una plataforma cloud con despliegue automatico desde GitHub.
URL de produccion: mamb.online (redirige a Render)
Arquitectura del despliegue
Servicio unificado
Render sirve tanto el frontend estatico como el backend Express desde un unico servicio. El servidor detecta si la peticion es para la API o para el frontend.
Diagrama de flujo
Cliente (navegador)
|
v
mamb.online (Namecheap DNS)
|
v
Render (Web Service)
|
|-- /api/* --> Express (Node.js + PostgreSQL)
+-- /* --> Sirve frontend/index.html
Configuracion del servicio
Crear Web Service en Render
- Entra a dashboard.render.com
- Clic en New > Web Service
- Conecta el repositorio de GitHub (
risharddv/MAMBQ)
Parametros del servicio
| Campo | Valor |
|---|---|
| Name | mamb |
| Region | Oregon (US West) |
| Branch | main |
| Build Command | npm install |
| Start Command | node backend/server.js |
| Instance Type | Free |
Variables de entorno
En la seccion Environment del servicio:
PORT=10000
DATABASE_URL=postgresql://...
JWT_SECRET=tu_clave_secreta
NODE_ENV=production
Puerto dinamico
Render asigna el puerto dinamicamente. El backend lee process.env.PORT:
const PORT = process.env.PORT || 3000;
app.listen(PORT);
Despliegue automatico
Cada git push a la rama main dispara un nuevo despliegue automaticamente. Render ejecuta el build y arranca el servidor sin intervencion manual.
Dominio personalizado
Registro del dominio
Se adquirio el dominio mamb.online a traves de Namecheap.
Configuracion DNS
Este dominio redirige automaticamente al servicio alojado en Render, proporcionando una URL profesional y facil de recordar.
Flujo de redireccion
https://www.mamb.online/ --> https://mamb-qsi0.onrender.com/
Plan gratuito — consideraciones
Limitaciones
| Aspecto | Detalle |
|---|---|
| Hibernacion | El servicio se duerme tras 15 min de inactividad |
| Cold start | Primera peticion tras reposo tarda 20-30 segundos |
| Horas de computo | 750 h/mes en la capa gratuita |
| Peticiones | Sin limite mensual |
Recomendaciones
Para evitar cold starts en demos o presentaciones, puedes hacer un ping al endpoint /api/health unos minutos antes.
Logs y monitoreo
Acceso a logs
Desde el dashboard de Render se accede a los logs en tiempo real del servicio.
Diagnostico de errores
Si el despliegue falla, el log muestra el error exacto del proceso de build o del arranque del servidor. Errores comunes:
- Variables de entorno faltantes
- Dependencias no instaladas
- Puerto ya en uso
Hoja de ruta — IA
El modulo de inteligencia artificial no esta implementado en la version actual. Esta pagina documenta la funcionalidad prevista para fases futuras.
Objetivo
Integrar un modelo de estilizacion artistica (Neural Style Transfer) que permita a los visitantes aplicar estilos de artistas reconocidos del MAMB a sus propias obras.
Flujo previsto
Proceso del usuario
- El visitante sube una imagen de su obra
- La imagen pasa por moderacion de contenido (ya implementada)
- El visitante selecciona un estilo artistico
- TensorFlow.js procesa la imagen
- La imagen estilizada se publica en la galeria
Diagrama de flujo
Visitante sube imagen
|
v
Moderacion de contenido (ya implementada)
|
v
Seleccion de estilo artistico
(ej: "estilo Obregon", "estilo Grau")
|
v
TensorFlow.js aplica el estilo
|
v
Imagen estilizada publicada en la galeria
Tecnologias planificadas
Modelo de IA
| Componente | Tecnologia |
|---|---|
| Modelo base | TensorFlow.js (browser o Node.js) |
| Tecnica | Neural Style Transfer / Arbitrary Style Transfer |
Almacenamiento
| Opcion | Ventaja |
|---|---|
| Render Disk | Integrado, sin configuracion extra |
| Cloudinary | CDN global, transformaciones de imagen |
| Amazon S3 | Escalable, bajo costo por GB |
Estado actual del proyecto
Componentes implementados
| Componente | Estado |
|---|---|
| Subida de imagenes | Implementado |
| Moderacion de contenido | Implementado |
| Galeria funcional | Implementado |
| Base de datos PostgreSQL | Implementado |
| API REST completa | Implementado |
Componentes pendientes
| Componente | Estado |
|---|---|
| Integracion TensorFlow.js | Pendiente |
| Seleccion de estilos artisticos | Pendiente |
| Almacenamiento de imagenes procesadas | Pendiente |
Requisitos para la implementacion
Modelos pre-entrenados
Seleccionar y optimizar modelos de style transfer para ejecucion en el navegador. Los modelos deben ser lo suficientemente ligeros para funcionar en dispositivos moviles.
Galeria de estilos
Recopilar obras de referencia de artistas del MAMB para usar como estilos base. Cada estilo necesita una imagen de referencia de alta calidad.
Infraestructura de almacenamiento
Definir servicio para persistir las imagenes procesadas. Las imagenes originales ya se almacenan en Render, pero las procesadas requieren almacenamiento adicional.
Vista general
MAMB sigue una arquitectura cliente-servidor con el frontend desacoplado del backend. Ambos se despliegan dentro del mismo servicio en Render.
Diagrama de componentes
Arquitectura completa
+-----------------------------------------------------+
| CLIENTE (PWA) |
| index.html - app.js - style.css - manifest.json |
| Service Worker (sw.js) |
+-------------------------+---------------------------+
| HTTPS / REST JSON
+-------------------------v---------------------------+
| BACKEND — Node.js + Express |
| /api/obras /api/obras/:id /api/health |
| JWT Auth - Helmet - CORS - Multer - Morgan |
+-------------------------+---------------------------+
|
+-----------v-----------+
| PostgreSQL |
| obras | usuarios |
| likes | ratings |
+-----------+-----------+
|
+-----------v-----------+
| Render Disk |
| /uploads (imagenes) |
+-----------------------+
Capas del sistema
| Capa | Responsabilidad |
|---|---|
| Presentacion | PWA en el navegador (HTML/CSS/JS) |
| API | Express.js con middleware de seguridad |
| Logica | Validacion, moderacion, autenticacion |
| Datos | PostgreSQL + sistema de archivos |
Flujo de peticiones
Consultar la galeria
- El visitante abre la app y navega a la galeria
api.jsenviaGET /api/obrascon parametros de busqueda/filtro- Express consulta PostgreSQL y devuelve las obras en JSON
app.jsrenderiza las tarjetas en el DOM- Si no hay conexion, se muestran obras guardadas en
localStorage
Subir una obra
- El visitante llena el formulario y selecciona una imagen
api.jsenviaPOST /api/obrascomomultipart/form-data- Express valida el JWT y procesa la imagen con Multer
- Se ejecuta moderacion de contenido sobre el apodo
- La obra se guarda en PostgreSQL y la imagen en
/uploads - Se devuelve la obra creada al cliente
Dar like a una obra
- El visitante pulsa el boton de like
api.jsenviaPOST /api/obras/:id/like- Express incrementa
likes_counten PostgreSQL - Se devuelve el nuevo conteo al cliente
Calificar una obra
- El visitante selecciona estrellas (1-5)
api.jsenviaPOST /api/obras/:id/ratecon el rating- Express suma al
rating_totale incrementarating_count - Se devuelve el nuevo total al cliente
Estructura del repositorio
Arbol de directorios
MAMBQ/
|-- frontend/
| |-- index.html # SPA — 9 pantallas
| |-- app.js # Logica principal (1188 lineas)
| |-- style.css # Estilos mobile-first (2509 lineas)
| |-- api.js # Cliente API REST con fallback offline
| |-- usernameModeration.js # Filtro de contenido
| |-- manifest.json # Configuracion PWA
| +-- icons/ # Iconos SVG 192x192, 512x512
|
|-- Landing MAMB/ # Landing estatica (GitHub Pages)
| |-- index.html
| |-- index.js
| |-- styles.css
| +-- img/
|
|-- backend/ # API REST (Render)
| |-- server.js # Entry point del servidor
| +-- uploads/ # Imagenes subidas por visitantes
|
|-- MAMB-docs/ # Documentacion (Docusaurus)
|
|-- sw.js # Service Worker global
+-- readme.md # README del proyecto
Descripcion de carpetas
| Carpeta | Contenido |
|---|---|
frontend/ | SPA con 9 pantallas, PWA instalable |
Landing MAMB/ | Pagina informativa en GitHub Pages |
backend/ | Servidor Express con API REST |
MAMB-docs/ | Documentacion Docusaurus |
Comunicacion entre componentes
Tabla de comunicaciones
| Origen | Destino | Protocolo | Descripcion |
|---|---|---|---|
| PWA | Backend | HTTPS/REST | Todas las operaciones CRUD |
| PWA | localStorage | JS API | Cache offline de obras |
| Backend | PostgreSQL | TCP | Persistencia de datos |
| Backend | Disk | FS | Almacenamiento de imagenes |
| Landing | PWA | Enlace HTTP | Redireccion a la app |
| Namecheap | Render | DNS | Dominio mamb.online |
Seguridad en la comunicacion
- HTTPS obligatorio en produccion
- JWT para endpoints protegidos
- Helmet para headers de seguridad
- CORS configurado para origenes permitidos
Frontend
El frontend es una Single Page Application (SPA) desarrollada en JavaScript vanilla, sin frameworks. Es instalable como PWA y esta disenada con enfoque mobile-first.
Modulos principales
Tabla de archivos
| Archivo | Lineas | Responsabilidad |
|---|---|---|
index.html | ~1018 | Estructura HTML de las 9 pantallas |
app.js | ~1188 | Logica de navegacion, renderizado, juego, perfiles |
style.css | ~2509 | Diseno responsive, variables CSS, animaciones |
api.js | ~192 | Llamadas a la API REST con fallback offline |
usernameModeration.js | ~132 | Filtro de apodos inapropiados |
manifest.json | ~34 | Metadatos PWA |
sw.js | ~76 | Service Worker para cache offline |
index.html
Archivo HTML unico que contiene las 9 pantallas como secciones <section>. Solo una seccion es visible a la vez, controlada por CSS y JavaScript.
app.js
Modulo principal que maneja:
- Navegacion entre pantallas
- Renderizado de tarjetas de obras
- Logica del juego de memoria
- Gestion de perfiles y avatares
- Manejo de eventos de usuario
style.css
Estilos mobile-first con:
- Variables CSS para temas
- Grid y Flexbox para layout responsive
- Animaciones y transiciones
- Soporte para modo oscuro
api.js
Cliente HTTP que encapsula todas las llamadas al backend con fallback automatico a localStorage cuando no hay conexion.
Pantallas de la app
Tabla de pantallas
| ID | Pantalla | Funcion |
|---|---|---|
screen-inicio | Inicio | Splash + ingreso de nombre |
screen-galeria | Galeria | Listado de obras con busqueda y filtros |
screen-subir | Subir obra | Formulario de publicacion |
screen-memory | Juego | Juego de memoria con datos de arte |
screen-perfil | Perfil | Configuracion del visitante |
screen-colecciones | Colecciones | Obras favoritas guardadas |
screen-about | Acerca de | Info del museo |
screen-detalle | Detalle | Vista ampliada de una obra |
screen-juego | Juegos | Actividades interactivas |
Navegacion SPA
Mecanismo de navegacion
No usa rutas del navegador. Cada pantalla es una seccion con display: none por defecto. app.js controla la visibilidad:
function showScreen(screenId) {
document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
document.getElementById(screenId).classList.add('active');
}
Ventajas de este enfoque
- Sin dependencia de router externo
- Transiciones instantaneas entre pantallas
- Compatible con cualquier navegador
- Sin recarga de pagina
Cliente API (api.js)
Endpoints consumidos
| Metodo | Endpoint | Funcion |
|---|---|---|
GET | /api/obras | Listar obras con filtros |
GET | /api/obras/:id | Obtener obra por ID |
POST | /api/obras | Crear obra (multipart) |
DELETE | /api/obras/:id | Eliminar obra |
POST | /api/obras/:id/like | Dar like |
POST | /api/obras/:id/rate | Calificar (1-5) |
Fallback offline
Cuando el backend no responde, api.js usa obras guardadas en localStorage bajo la clave mamb_local_obras, permitiendo navegar la galeria sin conexion.
Manejo de errores
El cliente captura errores de red y muestra mensajes apropiados al usuario. En caso de fallo, los datos se persisten localmente para sincronizar despues.
Service Worker
Estrategias de cache
| Tipo de recurso | Estrategia | Comportamiento |
|---|---|---|
Peticiones API (/api/*) | Network-first | Intenta red primero, cache como fallback |
| Assets estaticos (CSS, JS, imagenes) | Cache-first | Sirve desde cache, actualiza en background |
Ciclo de vida
- Instalacion — precachea assets criticos
- Activacion — limpia caches antiguas
- Fetch — intercepta peticiones y aplica estrategia segun tipo
PWA
Criterios de instalacion
La app cumple los requisitos minimos de PWA:
manifest.jsonconname,short_name,start_url,display: standalone- Service Worker registrado con estrategias de cache
- Iconos en formatos 192x192 y 512x512 px (SVG)
- Tema de color y color de fondo definidos
Configuracion del manifest
| Campo | Valor |
|---|---|
name | Museo de Arte Moderno |
short_name | MAMB |
display | standalone |
start_url | / |
theme_color | Definido en manifest |
Moderacion de contenido
usernameModeration.js
Filtra apodos inapropiados del lado del cliente antes de enviarlos al servidor.
Tecnicas de deteccion
- Lista negra — palabras prohibidas directas
- Leet-speak — detecta sustituciones como
h4ck3r,@dmin - Homoglifos — caracteres Unicode visualmente similares (ej: cirilico
аvs latinoa) - Normalizacion — convierte a forma canonica para evitar evasiones
Base de datos
MAMB utiliza PostgreSQL como sistema de gestion de base de datos relacional. La conexion se configura mediante la variable de entorno DATABASE_URL.
Modelo de datos
Diagrama de entidades
+---------------------+ +---------------------+
| obras | | usuarios |
+---------------------+ +---------------------+
| id (PK, SERIAL) | | id (PK, SERIAL) |
| titulo | | apodo (UNIQUE) |
| descripcion | | ciudad |
| image_url | | avatar_index |
| autor_apodo | | password_hash |
| avatar_index | | created_at |
| likes_count | +---------------------+
| rating_total |
| rating_count |
| created_at |
+---------------------+
Relaciones
Actualmente no hay claves foraneas entre tablas. La relacion entre obras y usuarios es implicita a traves del campo autor_apodo.
Tabla obras
Descripcion
Almacena las obras de arte del museo y de los visitantes.
Columnas
| Columna | Tipo | Descripcion |
|---|---|---|
id | SERIAL PRIMARY KEY | ID autoincremental |
titulo | VARCHAR(255) | Titulo de la obra (requerido) |
descripcion | TEXT | Descripcion libre |
image_url | TEXT | Ruta relativa al archivo subido en /uploads |
autor_apodo | VARCHAR(100) | Apodo del visitante que subio la obra |
avatar_index | INTEGER | Indice del avatar seleccionado (0-7) |
likes_count | INTEGER DEFAULT 0 | Contador de likes |
rating_total | INTEGER DEFAULT 0 | Suma total de calificaciones recibidas |
rating_count | INTEGER DEFAULT 0 | Numero de calificaciones recibidas |
created_at | TIMESTAMPTZ | Fecha y hora de creacion |
Calificacion promedio
El rating promedio se calcula como rating_total / rating_count. Este diseno permite actualizar con un solo UPDATE sin subconsultas.
Tabla usuarios
Descripcion
Almacena los perfiles de visitantes registrados.
Columnas
| Columna | Tipo | Descripcion |
|---|---|---|
id | SERIAL PRIMARY KEY | ID autoincremental |
apodo | VARCHAR(100) UNIQUE | Nombre de usuario unico |
ciudad | VARCHAR(100) | Ciudad del visitante |
avatar_index | INTEGER | Avatar elegido (0-7) |
password_hash | TEXT | Hash bcrypt de la contrasena |
created_at | TIMESTAMPTZ | Fecha de registro |
Seguridad de contrasenas
Las contrasenas se almacenan como hash bcrypt, nunca en texto plano. El hashing se realiza en el backend antes de insertar en la base de datos.
Conexion
Configuracion del pool
El backend se conecta usando el paquete pg:
const { Pool } = require('pg');
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: process.env.NODE_ENV === 'production'
? { rejectUnauthorized: false }
: false
});
Variable de entorno
DATABASE_URL=postgresql://usuario:contraseña@host:5432/mamb
SSL segun entorno
| Entorno | SSL |
|---|---|
| Produccion (Render) | Habilitado (rejectUnauthorized: false) |
| Desarrollo local | Deshabilitado |
Migracion automatica
Comportamiento
El backend crea las tablas automaticamente al arrancar si no existen. No se usa un sistema de migraciones formal — la creacion es declarativa en el codigo del servidor.
Ventajas
- Sin pasos manuales de migracion
- El esquema siempre esta sincronizado con el codigo
- Despliegue simplificado
Almacenamiento de imagenes
Ubicacion
Las imagenes no se guardan en la base de datos. Se almacenan en el sistema de archivos bajo backend/uploads/. La BD solo guarda la ruta relativa en image_url.
Restricciones
| Aspecto | Detalle |
|---|---|
| Ubicacion | backend/uploads/ |
| Tamano maximo | 20 MB por imagen |
| Formatos | .jpg, .jpeg, .png, .webp, .gif |
| Procesamiento | Multer (middleware de Express) |
Disco efimero en Render
En el plan gratuito de Render, el disco es efimero: las imagenes se pierden cuando el servicio se reinicia o se redespliega. Para persistencia permanente se recomienda un servicio externo (Cloudinary, S3, etc.).
API REST — Vista general
La API de MAMB gestiona obras de arte, interacciones (likes y calificaciones) y autenticacion. Todos los endpoints retornan y aceptan JSON, excepto la creacion de obras que usa multipart/form-data.
Base URL
URLs por entorno
| Entorno | URL |
|---|---|
| Produccion | https://mamb-qsi0.onrender.com/api |
| Produccion (dominio) | https://www.mamb.online/api |
| Local | http://localhost:3000/api |
Resumen de endpoints
Obras (CRUD)
| Metodo | Ruta | Descripcion |
|---|---|---|
GET | /api/obras | Listar obras con filtros y paginacion |
GET | /api/obras/:id | Obtener una obra por ID |
POST | /api/obras | Crear nueva obra (multipart) |
PATCH | /api/obras/:id | Actualizar titulo/descripcion |
DELETE | /api/obras/:id | Eliminar una obra |
Interacciones
| Metodo | Ruta | Descripcion |
|---|---|---|
POST | /api/obras/:id/like | Dar like a una obra |
POST | /api/obras/:id/rate | Calificar una obra (1-5) |
Sistema
| Metodo | Ruta | Descripcion |
|---|---|---|
GET | /api/health | Estado del servidor y conexion a BD |
Autenticacion
JWT Bearer Token
Los endpoints protegidos requieren un JWT Bearer token en el header:
Authorization: Bearer <token>
Obtencion del token
El token se obtiene al registrarse o iniciar sesion y tiene expiracion automatica.
Endpoints sin autenticacion
Los endpoints de lectura (GET) son publicos y no requieren token.
Health check
Endpoint
GET /api/health
Respuesta exitosa
200 OK:
{
"status": "ok",
"museo": "MAMB",
"db": "PostgreSQL"
}
Uso recomendado
Usar este endpoint para verificar que el servidor y la base de datos estan operativos. Util para monitoreo y para "despertar" el servicio en Render antes de una demo.
Manejo de errores
Formato de error
Todos los errores siguen el mismo formato:
{
"error": "Descripcion del error"
}
Codigos de estado
| Codigo | Significado | Ejemplo |
|---|---|---|
400 | Datos invalidos o faltantes | Falta el titulo de la obra |
401 | Token JWT ausente o expirado | No se envio Authorization header |
404 | Recurso no encontrado | Obra con ese ID no existe |
500 | Error interno del servidor | Fallo en la conexion a BD |
Middleware
Cadena de middleware
El backend aplica los siguientes middleware a todas las peticiones, en orden:
| Middleware | Funcion |
|---|---|
| Helmet | Headers HTTP de seguridad (XSS, HSTS, etc.) |
| CORS | Control de origenes cruzados |
| Morgan | Logging de peticiones HTTP en consola |
| express.json() | Parsing de body JSON |
| Multer | Procesamiento de archivos (solo en POST /api/obras) |
Helmet — headers de seguridad
Helmet configura automaticamente headers como:
X-Content-Type-Options: nosniffX-Frame-Options: DENYStrict-Transport-Security
CORS — origenes permitidos
CORS esta configurado para permitir peticiones desde el frontend desplegado y desde localhost en desarrollo.
Obras — Referencia completa
Documentacion detallada de todos los endpoints relacionados con obras de arte.
Listar obras
Endpoint
GET /api/obras
Parametros de consulta
| Parametro | Tipo | Descripcion | Ejemplo |
|---|---|---|---|
search | string | Filtra por titulo o descripcion | ?search=paisaje |
autorApodo | string | Filtra por apodo del autor | ?autorApodo=Carlos |
page | number | Numero de pagina | ?page=2 |
limit | number | Resultados por pagina | ?limit=10 |
Respuesta exitosa
200 OK:
[
{
"id": 1,
"titulo": "Paisaje Costero",
"descripcion": "Vista del Caribe desde el malecon",
"image_url": "/uploads/obra_123.jpg",
"autor_apodo": "Carlos",
"avatar_index": 0,
"likes_count": 5,
"rating_total": 12,
"rating_count": 3,
"created_at": "2026-05-29T14:00:00Z"
}
]
Obtener obra por ID
Endpoint
GET /api/obras/:id
Respuesta exitosa
200 OK: objeto obra (mismo esquema que el listado).
Respuesta de error
404:
{ "error": "Obra no encontrada" }
Crear nueva obra
Endpoint
POST /api/obras
Content-Type: multipart/form-data
Campos del formulario
| Campo | Tipo | Requerido | Descripcion |
|---|---|---|---|
image | File | Si | Imagen de la obra |
titulo | string | Si | Titulo de la obra |
descripcion | string | No | Descripcion libre |
autorApodo | string | Si | Apodo del visitante |
avatarIndex | number | No | Indice del avatar (0-7) |
Restricciones de imagen
- Tamano maximo: 20 MB
- Formatos aceptados:
.jpg,.jpeg,.png,.webp,.gif
Respuesta exitosa
201 Created: objeto obra creado con todos los campos.
Ejemplo con curl
curl -X POST https://www.mamb.online/api/obras \
-F "image=@mi-obra.jpg" \
-F "titulo=Mi primera obra" \
-F "descripcion=Pintura al oleo" \
-F "autorApodo=Carlos" \
-F "avatarIndex=3"
Actualizar obra
Endpoint
PATCH /api/obras/:id
Content-Type: application/json
Body de la peticion
{
"titulo": "Nuevo titulo",
"descripcion": "Nueva descripcion"
}
Respuesta exitosa
200 OK: obra actualizada con los nuevos valores.
Eliminar obra
Endpoint
DELETE /api/obras/:id
Respuesta exitosa
200 OK:
{ "message": "Obra eliminada" }
Comportamiento
Elimina la obra de la base de datos y el archivo de imagen del disco.
Dar like
Endpoint
POST /api/obras/:id/like
Comportamiento
Incrementa en 1 el contador de likes de la obra.
Respuesta exitosa
200 OK:
{ "likes_count": 6 }
Calificar obra
Endpoint
POST /api/obras/:id/rate
Content-Type: application/json
Body de la peticion
{ "rating": 4 }
Validacion
El valor de rating debe ser un entero entre 1 y 5.
Respuesta exitosa
200 OK:
{
"rating_total": 16,
"rating_count": 4
}
Calcular promedio
Para obtener el rating promedio: rating_total / rating_count = 16 / 4 = 4.0 estrellas.
Esquema completo de una obra
Objeto obra
{
"id": 1,
"titulo": "Paisaje Costero",
"descripcion": "Vista del Caribe desde el malecon",
"image_url": "/uploads/obra_1717000000000.jpg",
"autor_apodo": "Carlos",
"avatar_index": 2,
"likes_count": 12,
"rating_total": 35,
"rating_count": 8,
"created_at": "2026-05-29T14:00:00.000Z"
}
Descripcion de campos
| Campo | Tipo | Descripcion |
|---|---|---|
id | number | Identificador unico |
titulo | string | Titulo de la obra |
descripcion | string | Descripcion textual |
image_url | string | Ruta relativa a la imagen |
autor_apodo | string | Apodo del autor |
avatar_index | number | Indice del avatar (0-7) |
likes_count | number | Total de likes recibidos |
rating_total | number | Suma de todas las calificaciones |
rating_count | number | Numero de calificaciones |
created_at | string (ISO 8601) | Fecha de creacion |