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.

ℹ️ Proyecto academico

Desarrollado en colaboracion con el Museo de Arte Moderno de Barranquilla y la Universidad Simon Bolivar, Barranquilla.

Vista de la aplicacion MAMB

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

TecnologiaUso
HTML5Estructura semantica de la SPA
CSS3Diseno visual responsive, mobile-first
JavaScript VanillaLogica de la app, sin frameworks
PWA / Service WorkerInstalacion nativa y cache offline

Backend

TecnologiaUso
Node.jsRuntime del servidor
Express.jsFramework para la API REST
PostgreSQLBase de datos relacional
JWT + bcryptjsAutenticacion y hashing de contrasenas
HelmetHeaders HTTP de seguridad
CORSControl de origenes cruzados
MulterSubida de imagenes (hasta 20 MB)
MorganLogging de peticiones HTTP

Infraestructura

ServicioUso
RenderHosting del backend + frontend
NamecheapDominio mamb.online
GitHub PagesLanding 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.

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

EntornoURL
Aplicacion (produccion)mamb.online
Render (directo)mamb-qsi0.onrender.com
Landing pagerisharddv.github.io/MAMBQ/landing
Repositoriogithub.com/risharddv/MAMBQ
Documentacionrisharddv.github.io/MAMBQ

Instalacion

Guia para poner en marcha el proyecto MAMB en tu maquina local.

Requisitos previos

Software necesario

RequisitoVersion minima
Node.jsv18+
PostgreSQLv14+
Gitcualquier 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
⚠️ Seguridad

Nunca subas el archivo .env al repositorio. Ya esta incluido en .gitignore.

Descripcion de variables

VariableDescripcion
PORTPuerto donde escucha el servidor (default: 3000)
DATABASE_URLCadena de conexion a PostgreSQL
JWT_SECRETClave secreta para firmar tokens JWT
NODE_ENVEntorno 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.

💡 Tip

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):

  1. Abre la app en Chrome o un navegador compatible
  2. Busca el icono de instalacion en la barra de direcciones
  3. Selecciona "Instalar" o "Anadir a pantalla de inicio"

En escritorio (Chrome)

  1. Abre la app en Chrome
  2. Haz clic en el icono de instalacion en la barra de URL
  3. Confirma la instalacion

La app se instalara como aplicacion nativa en tu dispositivo.

App MAMB en dispositivo movil

Resolucion de problemas

El backend no arranca

  • Verifica que PostgreSQL este corriendo
  • Revisa que DATABASE_URL en .env sea 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.

Pantalla principal de MAMB

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
Pantalla de inicio

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
Galeria de obras

Subir obra

Formulario para que los visitantes publiquen su propia obra.

Pasos para subir

  1. Selecciona o toma una fotografia de la obra
  2. Ingresa titulo y descripcion
  3. Selecciona la tecnica artistica
  4. Elige un avatar y apodo de visitante
  5. 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
Formulario de subida

Juego de memoria

Mini-juego de cartas con datos curiosos sobre pinturas famosas del MAMB.

Como jugar

  1. Se muestran cartas boca abajo
  2. Voltea dos cartas por turno
  3. Encuentra los pares para desbloquear datos de cada obra
  4. Completa el tablero para ganar

Objetivo educativo

Cada par desbloqueado revela informacion sobre una pintura famosa: autor, tecnica, ano y datos curiosos.

Juego de memoria

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.

Pantalla de perfil

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

ElementoDescripcion
ImagenVista ampliada de la obra
TituloNombre de la obra
AutorApodo del visitante o artista
TecnicaTipo de tecnica artistica
DescripcionTexto 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
Detalle de una obra

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 localStorage para 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

Landing page del proyecto MAMB

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

ArchivoFuncion
index.htmlEstructura semantica de la pagina (~398 lineas)
index.jsAnimaciones, scroll suave e interacciones (~200 lineas)
styles.cssDiseno visual responsive
img/Imagenes del museo y del proyecto

Tecnologias

TecnologiaUso
HTML5Estructura semantica
CSS3Diseno visual y responsive
JavaScriptAnimaciones e interacciones
GitHub PagesHosting 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

  1. Ve a Settings > Pages en el repositorio
  2. Selecciona la rama main como source
  3. 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.

Vista de la landing page

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
Dashboard de Render

Configuracion del servicio

Crear Web Service en Render

  1. Entra a dashboard.render.com
  2. Clic en New > Web Service
  3. Conecta el repositorio de GitHub (risharddv/MAMBQ)

Parametros del servicio

CampoValor
Namemamb
RegionOregon (US West)
Branchmain
Build Commandnpm install
Start Commandnode backend/server.js
Instance TypeFree

Variables de entorno

En la seccion Environment del servicio:

PORT=10000
DATABASE_URL=postgresql://...
JWT_SECRET=tu_clave_secreta
NODE_ENV=production

Puerto dinamico

⚠️ Precaucion

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.

Proceso de despliegue en Render

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/
Configuracion del dominio en Namecheap

Plan gratuito — consideraciones

Limitaciones

AspectoDetalle
HibernacionEl servicio se duerme tras 15 min de inactividad
Cold startPrimera peticion tras reposo tarda 20-30 segundos
Horas de computo750 h/mes en la capa gratuita
PeticionesSin limite mensual

Recomendaciones

💡 Rendimiento

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
Dashboard de Render con logs

Hoja de ruta — IA

⚠️ Funcionalidad planificada

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

  1. El visitante sube una imagen de su obra
  2. La imagen pasa por moderacion de contenido (ya implementada)
  3. El visitante selecciona un estilo artistico
  4. TensorFlow.js procesa la imagen
  5. 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

ComponenteTecnologia
Modelo baseTensorFlow.js (browser o Node.js)
TecnicaNeural Style Transfer / Arbitrary Style Transfer

Almacenamiento

OpcionVentaja
Render DiskIntegrado, sin configuracion extra
CloudinaryCDN global, transformaciones de imagen
Amazon S3Escalable, bajo costo por GB

Estado actual del proyecto

Componentes implementados

ComponenteEstado
Subida de imagenesImplementado
Moderacion de contenidoImplementado
Galeria funcionalImplementado
Base de datos PostgreSQLImplementado
API REST completaImplementado

Componentes pendientes

ComponenteEstado
Integracion TensorFlow.jsPendiente
Seleccion de estilos artisticosPendiente
Almacenamiento de imagenes procesadasPendiente

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

CapaResponsabilidad
PresentacionPWA en el navegador (HTML/CSS/JS)
APIExpress.js con middleware de seguridad
LogicaValidacion, moderacion, autenticacion
DatosPostgreSQL + sistema de archivos

Flujo de peticiones

Consultar la galeria

  1. El visitante abre la app y navega a la galeria
  2. api.js envia GET /api/obras con parametros de busqueda/filtro
  3. Express consulta PostgreSQL y devuelve las obras en JSON
  4. app.js renderiza las tarjetas en el DOM
  5. Si no hay conexion, se muestran obras guardadas en localStorage

Subir una obra

  1. El visitante llena el formulario y selecciona una imagen
  2. api.js envia POST /api/obras como multipart/form-data
  3. Express valida el JWT y procesa la imagen con Multer
  4. Se ejecuta moderacion de contenido sobre el apodo
  5. La obra se guarda en PostgreSQL y la imagen en /uploads
  6. Se devuelve la obra creada al cliente

Dar like a una obra

  1. El visitante pulsa el boton de like
  2. api.js envia POST /api/obras/:id/like
  3. Express incrementa likes_count en PostgreSQL
  4. Se devuelve el nuevo conteo al cliente

Calificar una obra

  1. El visitante selecciona estrellas (1-5)
  2. api.js envia POST /api/obras/:id/rate con el rating
  3. Express suma al rating_total e incrementa rating_count
  4. 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

CarpetaContenido
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

OrigenDestinoProtocoloDescripcion
PWABackendHTTPS/RESTTodas las operaciones CRUD
PWAlocalStorageJS APICache offline de obras
BackendPostgreSQLTCPPersistencia de datos
BackendDiskFSAlmacenamiento de imagenes
LandingPWAEnlace HTTPRedireccion a la app
NamecheapRenderDNSDominio 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

ArchivoLineasResponsabilidad
index.html~1018Estructura HTML de las 9 pantallas
app.js~1188Logica de navegacion, renderizado, juego, perfiles
style.css~2509Diseno responsive, variables CSS, animaciones
api.js~192Llamadas a la API REST con fallback offline
usernameModeration.js~132Filtro de apodos inapropiados
manifest.json~34Metadatos PWA
sw.js~76Service 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

IDPantallaFuncion
screen-inicioInicioSplash + ingreso de nombre
screen-galeriaGaleriaListado de obras con busqueda y filtros
screen-subirSubir obraFormulario de publicacion
screen-memoryJuegoJuego de memoria con datos de arte
screen-perfilPerfilConfiguracion del visitante
screen-coleccionesColeccionesObras favoritas guardadas
screen-aboutAcerca deInfo del museo
screen-detalleDetalleVista ampliada de una obra
screen-juegoJuegosActividades interactivas

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

MetodoEndpointFuncion
GET/api/obrasListar obras con filtros
GET/api/obras/:idObtener obra por ID
POST/api/obrasCrear obra (multipart)
DELETE/api/obras/:idEliminar obra
POST/api/obras/:id/likeDar like
POST/api/obras/:id/rateCalificar (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 recursoEstrategiaComportamiento
Peticiones API (/api/*)Network-firstIntenta red primero, cache como fallback
Assets estaticos (CSS, JS, imagenes)Cache-firstSirve desde cache, actualiza en background

Ciclo de vida

  1. Instalacion — precachea assets criticos
  2. Activacion — limpia caches antiguas
  3. Fetch — intercepta peticiones y aplica estrategia segun tipo

PWA

Criterios de instalacion

La app cumple los requisitos minimos de PWA:

  • manifest.json con name, 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

CampoValor
nameMuseo de Arte Moderno
short_nameMAMB
displaystandalone
start_url/
theme_colorDefinido en manifest
App MAMB responsive

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 latino a)
  • 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

ColumnaTipoDescripcion
idSERIAL PRIMARY KEYID autoincremental
tituloVARCHAR(255)Titulo de la obra (requerido)
descripcionTEXTDescripcion libre
image_urlTEXTRuta relativa al archivo subido en /uploads
autor_apodoVARCHAR(100)Apodo del visitante que subio la obra
avatar_indexINTEGERIndice del avatar seleccionado (0-7)
likes_countINTEGER DEFAULT 0Contador de likes
rating_totalINTEGER DEFAULT 0Suma total de calificaciones recibidas
rating_countINTEGER DEFAULT 0Numero de calificaciones recibidas
created_atTIMESTAMPTZFecha y hora de creacion

Calificacion promedio

💡 Tip

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

ColumnaTipoDescripcion
idSERIAL PRIMARY KEYID autoincremental
apodoVARCHAR(100) UNIQUENombre de usuario unico
ciudadVARCHAR(100)Ciudad del visitante
avatar_indexINTEGERAvatar elegido (0-7)
password_hashTEXTHash bcrypt de la contrasena
created_atTIMESTAMPTZFecha 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

EntornoSSL
Produccion (Render)Habilitado (rejectUnauthorized: false)
Desarrollo localDeshabilitado

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

AspectoDetalle
Ubicacionbackend/uploads/
Tamano maximo20 MB por imagen
Formatos.jpg, .jpeg, .png, .webp, .gif
ProcesamientoMulter (middleware de Express)

Disco efimero en Render

⚠️ Precaucion

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

EntornoURL
Produccionhttps://mamb-qsi0.onrender.com/api
Produccion (dominio)https://www.mamb.online/api
Localhttp://localhost:3000/api

Resumen de endpoints

Obras (CRUD)

MetodoRutaDescripcion
GET/api/obrasListar obras con filtros y paginacion
GET/api/obras/:idObtener una obra por ID
POST/api/obrasCrear nueva obra (multipart)
PATCH/api/obras/:idActualizar titulo/descripcion
DELETE/api/obras/:idEliminar una obra

Interacciones

MetodoRutaDescripcion
POST/api/obras/:id/likeDar like a una obra
POST/api/obras/:id/rateCalificar una obra (1-5)

Sistema

MetodoRutaDescripcion
GET/api/healthEstado 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

CodigoSignificadoEjemplo
400Datos invalidos o faltantesFalta el titulo de la obra
401Token JWT ausente o expiradoNo se envio Authorization header
404Recurso no encontradoObra con ese ID no existe
500Error interno del servidorFallo en la conexion a BD

Middleware

Cadena de middleware

El backend aplica los siguientes middleware a todas las peticiones, en orden:

MiddlewareFuncion
HelmetHeaders HTTP de seguridad (XSS, HSTS, etc.)
CORSControl de origenes cruzados
MorganLogging de peticiones HTTP en consola
express.json()Parsing de body JSON
MulterProcesamiento de archivos (solo en POST /api/obras)

Helmet — headers de seguridad

Helmet configura automaticamente headers como:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • Strict-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

ParametroTipoDescripcionEjemplo
searchstringFiltra por titulo o descripcion?search=paisaje
autorApodostringFiltra por apodo del autor?autorApodo=Carlos
pagenumberNumero de pagina?page=2
limitnumberResultados 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

CampoTipoRequeridoDescripcion
imageFileSiImagen de la obra
titulostringSiTitulo de la obra
descripcionstringNoDescripcion libre
autorApodostringSiApodo del visitante
avatarIndexnumberNoIndice del avatar (0-7)

Restricciones de imagen

ℹ️ Info
  • 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

💡 Tip

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

CampoTipoDescripcion
idnumberIdentificador unico
titulostringTitulo de la obra
descripcionstringDescripcion textual
image_urlstringRuta relativa a la imagen
autor_apodostringApodo del autor
avatar_indexnumberIndice del avatar (0-7)
likes_countnumberTotal de likes recibidos
rating_totalnumberSuma de todas las calificaciones
rating_countnumberNumero de calificaciones
created_atstring (ISO 8601)Fecha de creacion
En esta pagina