# RSVP Digital - Invitaciones web

Templates para vender invitaciones web con RSVP para fiestas de 15, casamientos, baby shower, infantiles y eventos sociales.

La estetica cambia por plantilla: 15 elegante, baby shower suave, infantil ludico, boda minimal y fiesta moderna. Todas mantienen portada full screen, contador, ubicacion, vestimenta, regalos, playlist cuando aplica y formulario RSVP.

## Arquitectura del proyecto

Frontend: HTML5/CSS3/JS estatico. Todas las invitaciones de clientes se sirven desde un unico contenedor Nginx.

Backend: `scripts/admin-server.py`, que actua como API para RSVP, canciones, dashboard, imagenes y administracion. En Docker corre como el servicio `invitaciones-admin`.

Base de datos: SQLite local en `clientes/_data/invitaciones.sqlite3` para RSVP, canciones y tokens del panel cliente.

Configuracion visible de cada invitacion: `config.json` por cliente, porque cada sitio estatico lo carga directo desde su carpeta.

Servicios Docker:

- `invitaciones-admin`: panel admin, panel cliente final y API en el puerto local `8099`.
- `invitaciones-web`: Nginx para publicar `clientes/<slug>/` en el puerto local `8092`.

La arquitectura esta pensada para usar Nginx Proxy Manager por delante. En produccion conviene crear dos proxy hosts:

- dominio admin -> `http://<server-ip>:8099`
- dominio clientes -> `http://<server-ip>:8092`

Luego configurar `ADMIN_PUBLIC_URL` y `CLIENTS_PUBLIC_URL` en `docker-compose.yml` para que los links, WhatsApp y Open Graph salgan con dominio publico. En produccion tambien configurar `ADMIN_PASSWORD` para proteger `/admin/` y las APIs administrativas con usuario `admin` por defecto.

## Estructura

```bash
.
├── sitio-web/
│   ├── index.html       # Invitacion principal
│   ├── panel.html       # Panel estatico heredado para config puntual
│   ├── config.json      # Datos editables del cliente
│   └── assets/          # Imagenes self-hosted
├── templates/           # Plantillas por estilo de evento
├── clientes/            # Invitaciones generadas por cliente
├── admin/               # Dashboard multi-cliente
├── cliente/             # Panel limitado para el cliente final
├── scripts/
│   ├── admin-server.py  # API y servidor del dashboard
│   └── nuevo-cliente.sh # Automatizacion CLI para nuevos clientes
├── docker-compose.yml
└── README
```

## Admin multi-cliente

Para administrar clientes, templates, imagenes y publicacion, usar el servidor admin local:

```bash
scripts/admin-server.py
```

Luego abrir:

```text
http://127.0.0.1:8099/admin/
```

Desde ahi se puede:

- listar clientes
- crear clientes desde templates
- editar `config.json`
- subir imagen principal y secundaria
- ajustar foco horizontal, foco vertical y zoom de cada imagen
- previsualizar la invitacion dentro del admin
- guardar cambios
- archivar clientes
- restaurar clientes archivados
- abrir o copiar el link privado del panel para cliente final

El editor del admin permite configurar:

- tipo de evento, nombres y fecha
- frase, firma y footer
- salon, direccion, hora, Maps y Waze
- dress code con nota, colores sugeridos y colores a evitar
- WhatsApp
- alias, CBU y titular
- paleta sugerida de la invitacion
- imagen principal, imagen secundaria y SEO
- maximo de invitados por grupo familiar

## Panel para cliente final

Cada cliente activo tiene un link privado con token para editar solo su invitacion:

```text
http://127.0.0.1:8099/cliente/?slug=<slug>&token=<token>
```

Ese link se obtiene desde el admin, seleccionando el cliente y usando **Panel cliente** o **Copiar acceso**.

El cliente final puede editar:

- datos visibles del evento
- fecha, lugar, direccion, Maps y Waze
- dress code con colores sugeridos y colores a evitar
- WhatsApp
- datos de regalo
- paleta sugerida
- imagen principal y secundaria
- ver dashboard de RSVP con busqueda y filtros
- exportar CSV/XLS total o CSV solo de la vista filtrada
- imprimir el dashboard o guardarlo como PDF desde el navegador

No puede crear clientes, cambiar template, archivar, restaurar ni tocar campos tecnicos globales.

El dashboard del cliente muestra:

- total confirmados
- cantidad de personas
- menus y personas por menu en la vista filtrada
- no asisten
- busqueda por nombre, menu o mensaje
- filtros por confirmados, no asisten y menu
- canciones sugeridas
- resumen copiable para enviar al organizador
- exportacion CSV/XLS total y CSV visible
- impresion/PDF

El dashboard se carga al abrir el panel y se refresca automaticamente cada 30 segundos. El boton **Actualizar ahora** queda solo para forzar una recarga manual.

## WhatsApp

Cada invitacion incluye un bloque de acciones directas para confirmar asistencia, compartir la invitacion, consultar ubicacion y avisar al organizador. Se configura desde:

```text
whatsapp
shareUrl
whatsappRsvpText
whatsappShareText
whatsappLocationText
whatsappOrganizerText
```

Los mensajes aceptan variables simples: `{nombres}`, `{salon}`, `{direccion}`, `{hora}` y `{url}`. Si `shareUrl` esta vacio, se comparte la URL actual de la invitacion.

## Preview para WhatsApp

Cada cliente tiene metadatos Open Graph estaticos en `index.html`, pensados para que WhatsApp muestre bien la vista previa sin depender de JavaScript. El admin los regenera al crear o guardar un cliente.

Campos principales:

```text
publicUrl
ogTitle
ogDescription
ogImage
favicon
```

Si `ogTitle` esta vacio, se usa `<nombres> - <fechaCorta>`. Si `ogDescription` esta vacio, se usa `seoDescription`. Por defecto se generan:

```text
assets/og-image.svg
assets/favicon.svg
```

`favicon.svg` usa las iniciales del evento. Si `publicUrl` esta vacio, `og:image` queda relativo para desarrollo local; en produccion conviene completar `publicUrl` con el dominio publico para que WhatsApp use URLs absolutas.

Flujo recomendado para un cliente nuevo:

1. Abrir `http://127.0.0.1:8099/admin/`.
2. Crear el cliente indicando slug, template y nombre visible.
3. Seleccionar el cliente en la lista.
4. Editar los datos, subir imagenes y presionar **Guardar cambios**.
5. Abrir la URL local indicada por el admin.

## Imagenes del cliente

Las invitaciones usan imagenes self-hosted por defecto:

```text
assets/hero.svg
assets/event.svg
assets/quote.svg
```

Para usar fotos reales del cliente, copiar los archivos dentro de la carpeta del cliente, por ejemplo:

```text
clientes/magali-15/assets/hero.jpg
clientes/magali-15/assets/event.jpg
```

Luego actualizar la ruta desde el admin:

```text
Imagen principal: assets/hero.jpg
Imagen secundaria: assets/event.jpg
```

Si usas fotos, conviene guardarlas como `.jpg`, `.png` o `.webp` y actualizar las rutas en el admin. Solo reemplazar `hero.svg` o `event.svg` manteniendo el mismo nombre si el archivo nuevo tambien es SVG.

Tambien se pueden subir desde el admin, usando el servidor admin local:

```bash
scripts/admin-server.py
```

Abrir:

```text
http://127.0.0.1:8099/admin/
```

En el editor del cliente, usar **Subir principal** o **Subir secundaria**. El admin guarda la imagen en `clientes/<slug>/assets/`, actualiza la ruta del campo y despues hay que presionar **Guardar cambios**.

## Crear un nuevo cliente por CLI

El flujo recomendado es hacerlo desde `/admin/`. El script CLI queda disponible para automatizar o crear clientes sin abrir el panel.

Usar el script:

```bash
scripts/nuevo-cliente.sh magali-15
```

Elegir un template:

```bash
scripts/nuevo-cliente.sh magali-15 --template quince-elegante
```

Tambien se puede indicar nombre visible:

```bash
scripts/nuevo-cliente.sh boda-alma-mateo --name "Alma & Mateo"
```

Si ya tenes un JSON propio:

```bash
scripts/nuevo-cliente.sh magali-15 --config ~/Downloads/config.json
```

El script:

- crea `clientes/<slug>`
- copia la invitacion base o `templates/<nombre>`
- aplica un `config.json` propio si se pasa `--config`
- la invitacion queda disponible en el contenedor `invitaciones-web`

Templates disponibles:

- `quince-elegante`
- `boda-minimal`
- `fiesta-moderna`
- `cumpleanos-infantil`
- `baby-shower`

Despues de crearlo, abrir:

```text
http://127.0.0.1:8092/clientes/magali-15/
```

## Backend RSVP

El RSVP y las canciones sugeridas se guardan en el backend local del admin:

```text
clientes/_data/invitaciones.sqlite3
```

El servidor migra automaticamente datos legacy desde `clientes/_data/<slug>/rsvps.json`, `clientes/_data/<slug>/songs.json` y `clientes/_access/client-panel.json` si existen. El panel del cliente lee SQLite para armar el dashboard y exportar CSV/XLS.

## Spotify para playlist

La seccion **Armemos la playlist** busca canciones reales en Spotify y guarda la sugerencia con metadatos limpios:

```text
song
artist
album
image
spotify_uri
spotify_url
spotify_track_id
source
```

Para habilitar la busqueda, crear una app en Spotify Developer Dashboard y levantar el admin con:

```bash
SPOTIFY_CLIENT_ID=... SPOTIFY_CLIENT_SECRET=... scripts/admin-server.py
```

Opcionalmente se puede definir `SPOTIFY_MARKET=AR`. Si las credenciales no estan configuradas, la invitacion muestra el fallback manual y el guardado sigue funcionando.

## Desarrollo local

Levantar toda la app con Docker:

```bash
docker compose up -d --build
```

La imagen propia del admin se publica como:

```text
sebastian962/invitaciones-admin:latest
```

Para usar un tag fijo en produccion:

```bash
ADMIN_IMAGE_TAG=2026.04.30 docker compose up -d
```

Para proteger el admin publico, definir una clave larga en el `.env` del servidor:

```bash
ADMIN_USER=admin
ADMIN_PASSWORD=una-clave-larga-y-privada
```

Si `ADMIN_PASSWORD` queda vacio, el admin no pide autenticacion. Las invitaciones publicas, RSVP, canciones y el panel de cliente con token siguen funcionando sin usuario/clave.

Admin:

```text
http://127.0.0.1:8099/admin/
```

Clientes:

```text
http://127.0.0.1:8092/clientes/<slug>/
```

Tambien se puede levantar el admin sin Docker para desarrollo:

```bash
scripts/admin-server.py
```

Admin:

```text
http://127.0.0.1:8099/admin/
```

Logs:

```bash
docker logs -f invitaciones-admin
docker logs -f invitaciones-web
```

## Operacion

Para nuevos clientes, usar `/admin/`: crear desde template, cargar datos, subir imagenes, guardar cambios y copiar el acceso del panel cliente.

Propietario: Sebastian Ibarra
