Ir al contenido

Manual para crear tu propia invitación — Madify Invita

Este documento explica cómo armar tu propia página de invitación (a mano o pidiéndosela a una inteligencia artificial como Claude) para publicarla en Madify Invita. Tu página recibe los datos de tu evento automáticamente y las confirmaciones de asistencia llegan a tu panel.

Si vas a usar una IA: copia este documento completo en la conversación y pídele tu diseño. Al final hay un bloque «Prompt para la IA» listo para usar.

1. Qué vas a entregar

Un archivo ZIP con tu sitio:

mi-invitacion.zip
├── index.html        ← obligatorio (en la raíz del ZIP o dentro de UNA carpeta)
├── css/estilos.css
├── js/app.js
└── img/foto.webp
  • index.html es la portada. Puedes tener más páginas (galeria.html); también reciben los datos.
  • Usa rutas relativas: img/foto.webp, nunca /img/foto.webp ni rutas de tu computadora.
  • Todo en UTF-8.

2. Reglas del ZIP

  • Extensiones permitidas: avif, css, eot, gif, htm, html, ico, jpeg, jpg, js, json, m4a, map, mjs, mp3, mp4, ogg, otf, png, svg, ttf, txt, wav, webm, webmanifest, webp, woff, woff2.
  • Máximo 50 MB comprimido, 200 MB descomprimido y 500 archivos.
  • Se ignoran __MACOSX/, .DS_Store y archivos ocultos. No se aceptan enlaces simbólicos ni rutas con ...
  • Optimiza las imágenes (WebP o JPEG, menos de 400 KB cada una): la mayoría de tus invitados abrirá la invitación desde el celular.
  • Si la página tiene un error de sintaxis en las variables, el sistema te dice el archivo y la línea.

3. Datos dinámicos (variables)

Tu HTML se procesa con el motor de plantillas de Django. Escribe {{ variable }} donde quieras que aparezca un dato y {% if … %}…{% endif %} para mostrar algo solo si existe.

Llaves principales:

Variable Qué es
event Datos del evento (tabla «event»)
guest El invitado del link personal, o vacío en el link general (tabla «guest»)
rsvp La respuesta previa de ese invitado, o vacío (tabla «rsvp»)
rsvp_config Configuración del formulario de confirmación (tabla «rsvp_config»)
theme Solo en diseños del catálogo: las opciones que personaliza el cliente ({{ theme.<clave> }}) y theme.design (slug, name, version). Vacío en un ZIP propio
now Fecha y hora actual del servidor

event

Variable Tipo Descripción Ejemplo
event.title texto Título del evento Boda de Ana y Luis
event.slug texto Path del evento en la URL boda-ana-y-luis
event.type texto Tipo (clave): boda, xv_anos, bautizo, primera_comunion, presentacion, baby_shower, infantil, cumpleanos, fiesta, graduacion, corporativo, conferencia, otro boda
event.type_label texto Tipo legible Boda
event.honorees texto Festejado(s) Ana y Luis
event.hosts texto Anfitriones / papás / padrinos Familia López
event.description texto Mensaje principal (usa linebreaksbr para saltos de línea)
event.starts_at fecha y hora Inicio del evento (usa el filtro date) {{ event.starts_at|date:"l j \d\e F" }} → sábado 24 de octubre
event.ends_at fecha y hora Fin del evento (puede estar vacío)
event.dress_code texto Código de vestimenta Formal
event.contact_phone texto WhatsApp del anfitrión (con lada) 5214431234567
event.whatsapp_url URL Link directo a WhatsApp del anfitrión (vacío si no hay teléfono) https://wa.me/5214431234567
event.rsvp_deadline fecha Fecha límite para confirmar (puede estar vacía) {{ event.rsvp_deadline|date:"j \d\e F" }}
event.rsvp_open sí/no Si todavía se puede confirmar True
event.allow_public_rsvp sí/no Si se puede confirmar sin link personal True
event.allow_children sí/no Si la invitación admite niños True
event.locations lista Ubicaciones en orden (ver tabla de ubicaciones) {% for loc in event.locations %}…{% endfor %}
event.main_location ubicación La primera ubicación (o vacío) {{ event.main_location.name }}
event.links lista Links del evento (ver tabla de links) {% for link in event.links %}…{% endfor %}
event.gift_links lista Solo los links de tipo «mesa de regalos» {{ event.gift_links.0.url }}
event.bank_accounts lista Cuentas para regalo por transferencia (ver tabla de cuentas). Las marcadas «solo links personales» no aparecen en el link general {% for acc in event.bank_accounts %}{{ acc.clabe }}{% endfor %}
event.music_url URL Música de fondo del evento (vacío si no hay). Mejor usa {% music_player %}: sin autoplay, suena al primer toque
event.gallery_url URL Página para que los invitados suban fotos (vacío si el evento o su plan no tienen galería). Con link personal ya trae el ?i= https://invite.madify.mx/boda-ana-y-luis/fotos/
event.gallery_open sí/no La galería recibe fotos ahora. Mejor usa True
event.extra diccionario Datos libres que captura el anfitrión {{ event.extra.hashtag }}
event.url texto Ruta relativa de la invitación /boda-ana-y-luis/
event.public_url URL Dirección completa de la invitación (dominio propio si lo hay) https://invite.madify.mx/boda-ana-y-luis/

Cada ubicación (event.locations, event.main_location)

Variable Tipo Descripción Ejemplo
loc.kind texto Clave: ceremonia, recepcion, evento, otro ceremonia
loc.kind_label texto Tipo legible Ceremonia
loc.name texto Nombre del lugar (puede estar vacío) Parroquia de San José
loc.address texto Dirección Centro, Morelia
loc.maps_url URL Link de Google Maps tal cual lo capturaron (puede estar vacío) https://maps.app.goo.gl/…
loc.maps_link URL maps_url o, si está vacío, una búsqueda de Google Maps con lugar + dirección https://www.google.com/maps/search/?api=1&query=…
loc.starts_at fecha y hora Hora de esta ubicación (puede estar vacía) {{ loc.starts_at|time:"g:i a" }}
loc.notes texto Notas Estacionamiento en la parte trasera

Cada link (event.links, event.gift_links)

Variable Tipo Descripción Ejemplo
link.kind texto Clave: regalos, hospedaje, transmision, playlist, fotos, otro regalos
link.kind_label texto Tipo legible Mesa de regalos
link.label texto Texto del botón Ver mesa de regalos
link.url URL Destino https://mesaderegalos.liverpool.com.mx/…

Cuentas para regalo ({% for acc in event.bank_accounts %})

Variable Tipo Descripción Ejemplo
acc.bank texto Banco BBVA
acc.holder texto Titular Ana López
acc.clabe texto CLABE interbancaria (18 dígitos, ya validada) 012180001234567899
acc.concept texto Concepto sugerido (puede estar vacío) Regalo boda Ana y Luis

guest (solo cuando se abre con link personal)

Variable Tipo Descripción Ejemplo
guest.name texto Nombre de la invitación (persona, pareja o familia) Familia Pérez
guest.max_adults número Lugares para adultos 2
guest.max_children número Lugares para niños 1
guest.max_total número Total de lugares 3
guest.token texto Código del link personal (?i=) VoVZx4P4BgNt

rsvp (la respuesta previa de ese invitado, si ya confirmó)

Variable Tipo Descripción Ejemplo
rsvp.name texto Nombre con el que confirmó Laura Pérez
rsvp.response texto Su respuesta: yes (asiste), no, maybe (aún no sabe) yes
rsvp.attending sí/no Si asiste (True solo cuando response es yes) True
rsvp.adults número Adultos confirmados 2
rsvp.children número Niños confirmados 1
rsvp.message texto Mensaje que dejó ¡Felicidades!
rsvp.attendees lista Acompañantes: name, type (adult/child), age. Las alergias nunca se incluyen (son datos de salud) {% for a in rsvp.attendees %}{{ a.name }}{% endfor %}
rsvp.updated_at fecha y hora Última actualización de su respuesta

rsvp_config

Variable Tipo Descripción Ejemplo
rsvp_config.endpoint URL A dónde se manda la confirmación (POST JSON) /api/v1/public/events/boda-ana-y-luis/rsvp/
rsvp_config.token texto Token del invitado (vacío en el link general)
rsvp_config.mode texto guest (link personal), public (link general), invite_only (solo con link personal), closed (ya cerró) o demo (vista previa: no envía nada) guest
rsvp_config.max_adults número Máximo de adultos que puede confirmar quien abre la página 2
rsvp_config.max_children número Máximo de niños 1
rsvp_config.allow_children sí/no Si puede confirmar niños True
rsvp_config.deadline texto Fecha límite ISO (o vacío) 2026-10-15
rsvp_config.allow_maybe sí/no Si se ofrece la respuesta «Aún no sé» True
rsvp_config.ask_dietary sí/no Si se preguntan alergias o restricciones por acompañante True
rsvp_config.questions lista Preguntas propias del anfitrión (RSVP avanzado): id, label, type (text/choice), choices, required. El campo del formulario es q_ {% for q in rsvp_config.questions %}{{ q.label }}{% endfor %}

Filtros útiles

{{ event.starts_at|date:"l j \d\e F \d\e Y" }}   → sábado 24 de octubre de 2026
{{ event.starts_at|date:"g:i a" }}              → 1:00 p.m.
{{ event.starts_at|date:"c" }}                  → 2026-10-24T13:00:00-06:00 (para cuentas regresivas en JS)
{{ event.description|linebreaksbr }}            → respeta los saltos de línea
{{ event.honorees|upper }}                      → ANA Y LUIS
{{ guest.max_adults|pluralize:"es" }}           → «es» si es plural (lugar/lugares)
{{ event.extra.hashtag|default:"#AnayLuis" }}   → valor por defecto si está vacío

Ejemplos:

<h1>{{ event.honorees }}</h1>
<p>{{ event.starts_at|date:"l j \d\e F" }} · {{ event.starts_at|date:"g:i a" }}</p>

{% if guest %}
  <p>¡Hola, {{ guest.name }}! Reservamos {{ guest.max_adults }} lugar{{ guest.max_adults|pluralize:"es" }}.</p>
{% endif %}

{% for loc in event.locations %}
  <h3>{{ loc.kind_label }}: {{ loc.name }}</h3>
  <p>{{ loc.address }}</p>
  {% if loc.maps_link %}<a href="{{ loc.maps_link }}">Ver mapa</a>{% endif %}
{% endfor %}

{% for link in event.gift_links %}<a href="{{ link.url }}">{{ link.label }}</a>{% endfor %}

Si tu JavaScript usa llaves dobles (Vue, Handlebars, etc.), enciérralo en {% verbatim %}…{% endverbatim %} para que no se procese.

4. Confirmación de asistencia

Opción A — formulario listo

<section id="confirmar">
  {% rsvp_form %}
</section>
{% rsvp_script %}   {# antes de </body> #}

Genera un formulario completo (nombre, asiste sí/no, adultos, niños, nombres de acompañantes, mensaje) que puedes estilizar con CSS: .rsvp-form, .rsvp-field, .rsvp-submit, .rsvp-success, .rsvp-error.

Opción B — tu propio formulario

Pon data-rsvp en tu <form> y usa estos name en los campos:

Campo (name) Qué es
name Nombre de quien confirma (obligatorio en el link general)
attending Respuesta: radio/select/checkbox con valores yes / no / maybe (también si, tal vez, no se, true/false). maybe solo si rsvp_config.allow_maybe. También puede llamarse response
adults Número de adultos
children Número de niños
guests Total de personas (alternativa a adults/children; se cuentan como adultos)
message Mensaje para los anfitriones
phone Teléfono (opcional)
email Correo (opcional)
website Campo trampa anti-spam: agrégalo oculto y déjalo vacío
attendee_notes Dentro de cada acompañante que genera data-rsvp-attendees (rsvp.js lo agrega solo si rsvp_config.ask_dietary): alergias o restricciones. Nunca se prellena
q_<id> Respuesta a la pregunta propia del anfitrión (ver rsvp_config.questions)

Atributos que entiende el script:

Atributo Para qué
data-rsvp En el
: lo conecta con la API (el endpoint sale de {% rsvp_script %})
data-rsvp-attendees Contenedor donde se generan los campos de nombre por cada adulto/niño
data-rsvp-when-attending Visible solo si responde que sí asiste
data-rsvp-when-declined Visible solo si responde que no
data-rsvp-when-maybe Visible solo si responde «Aún no sé»
data-rsvp-children Se oculta si la invitación no incluye niños
data-rsvp-success Mensaje de éxito (se muestra al confirmar)
data-rsvp-error Mensaje de error
data-rsvp-closed Visible si la confirmación ya cerró
data-rsvp-invite-only Visible si solo se acepta con link personal
data-success-yes / data-success-no / data-success-maybe En el : textos de agradecimiento personalizados
<form data-rsvp data-success-yes="¡Gracias! Nos vemos pronto." data-success-no="¡Te extrañaremos!">
  <input name="name" placeholder="Tu nombre" required>
  <label><input type="radio" name="attending" value="yes"> Sí asistiré</label>
  <label><input type="radio" name="attending" value="no"> No podré ir</label>
  <div data-rsvp-when-attending hidden>
    <input type="number" name="adults" min="1" value="1">
    <input type="number" name="children" min="0" value="0" data-rsvp-children>
    <div data-rsvp-attendees></div>
  </div>
  <textarea name="message"></textarea>
  <input type="text" name="website" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px">
  <button type="submit">Enviar</button>
  <p data-rsvp-success hidden></p>
  <p data-rsvp-error hidden></p>
</form>
{% rsvp_script %}
  • Con link personal (?i=…) el nombre se llena solo, se respetan los lugares del invitado y, si ya había confirmado, su respuesta aparece para modificarla.
  • Sin link personal (link general) se pide el nombre y se respetan los límites del evento.
  • Los límites se validan también en el servidor: no se puede confirmar de más aunque alguien modifique la página.

Funciones del evento (etiquetas listas)

Funcionan igual en cualquier diseño. Si tu página no las incluye, la música y el botón de la galería se agregan solos (flotantes) cuando el evento los tiene.

Etiqueta Qué hace
{% share_buttons %} Botones de WhatsApp, Facebook, copiar link y compartir (celular). Siempre comparten el link general, nunca el personal. Clases: .mi-share, .mi-share-btn
{% music_player %} Botón ▶︎ de la música del evento (los navegadores no permiten que suene sola: se activa al primer toque). Clases: .mi-music, .mi-music-btn
{% gallery_button %} «📸 Sube tus fotos», solo mientras la galería de invitados recibe fotos (plan Premium). Clase: .mi-gallery-btn
{% invite_extras %} Antes de </body>: activa la cuenta regresiva y los botones de copiar/compartir
<div data-countdown="{{ event.starts_at|date:'c' }}">
  <span data-countdown-days></span> días · <span data-countdown-hours></span> h · <span data-countdown-minutes></span> min
</div>
{% gallery_button "Comparte tus fotos" %}
{% share_buttons %}
{% invite_extras %}   {# antes de </body> #}

5. Página de ejemplo completa (mínima)

<!doctype html>
<html lang="es-MX">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{{ event.title }}</title>
  <link rel="stylesheet" href="css/estilos.css">
</head>
<body>
  <header>
    <p class="eyebrow">{{ event.type_label }}</p>
    <h1>{{ event.honorees }}</h1>
    <p>{{ event.starts_at|date:"l j \d\e F \d\e Y" }} · {{ event.starts_at|date:"g:i a" }}</p>
    {% if guest %}<p class="hola">¡Hola, {{ guest.name }}!</p>{% endif %}
  </header>

  {% if event.description %}<section><p>{{ event.description|linebreaksbr }}</p></section>{% endif %}

  <section>
    {% for loc in event.locations %}
      <article>
        <h2>{{ loc.kind_label }}</h2>
        {% if loc.name %}<h3>{{ loc.name }}</h3>{% endif %}
        <p>{{ loc.address }}{% if loc.starts_at %} · {{ loc.starts_at|time:"g:i a" }}{% endif %}</p>
        {% if loc.maps_link %}<a href="{{ loc.maps_link }}" target="_blank" rel="noopener">Cómo llegar</a>{% endif %}
      </article>
    {% endfor %}
  </section>

  {% if event.gift_links %}
  <section>
    <h2>Mesa de regalos</h2>
    {% for link in event.gift_links %}<a href="{{ link.url }}" target="_blank" rel="noopener">{{ link.label }}</a>{% endfor %}
  </section>
  {% endif %}

  <section id="confirmar">
    <h2>Confirma tu asistencia</h2>
    {% if event.rsvp_deadline %}<p>Antes del {{ event.rsvp_deadline|date:"j \d\e F" }}.</p>{% endif %}
    {% rsvp_form %}
  </section>

  {% rsvp_script %}
</body>
</html>

6. Prompt para la IA

Copia y pega esto después de este manual, cambiando lo que está entre corchetes:

Con base en el manual anterior, crea mi invitación digital para [tipo de evento: boda, XV años, bautizo…]
con estilo [describe: elegante, minimalista, floral, rústico, colores dorado y verde olivo…].

Requisitos:
- Entrégame el contenido de cada archivo y la estructura del ZIP (index.html en la raíz, css/, img/).
- Usa SOLO las variables del manual ({{ event.… }}, {{ guest.… }}); no escribas datos fijos de fecha, lugar o nombres.
- Incluye una sección de confirmación con {% rsvp_form %} (o un formulario data-rsvp) y {% rsvp_script %} antes de </body>.
- Diseño mobile first, que cargue rápido (sin frameworks pesados); fuentes de Google Fonts permitidas.
- No cargues scripts de terceros (salvo Google Fonts) ni envíes datos a otros servidores.
- Si usas JavaScript con llaves dobles, enciérralo en {% verbatim %}.
- Rutas relativas para imágenes y CSS. Indica qué imágenes debo agregar y de qué tamaño.
Secciones que quiero: [portada con nombres y fecha, cuenta regresiva, mensaje, ubicaciones con mapa, mesa de regalos, galería, confirmación…].

7. Antes de enviar (checklist)

  • [ ] index.html en la raíz del ZIP y rutas relativas.
  • [ ] Probaste la página abriéndola en el celular (los datos aparecen como {{ … }} hasta que se publica: es normal).
  • [ ] La sección de confirmación usa {% rsvp_form %} o un form data-rsvp y {% rsvp_script %}.
  • [ ] Imágenes optimizadas y el ZIP pesa menos de 50 MB.
  • [ ] Sin scripts externos ni formularios que manden datos a otros sitios.
  • [ ] No hay un fotos/index.html: la dirección /fotos/ de tu invitación es la galería de invitados.

8. Cómo enviarlo

  1. Entra a tu panel: https://invite-app.madify.mx/admin/ → Mi sitio → Enviar sitio.
  2. Elige tu evento y sube el ZIP. Si algo no cumple las reglas, verás el error al momento.
  3. Lo revisamos (normalmente en menos de 24 horas) y te avisamos por correo cuando esté publicado. Si necesita cambios, te decimos cuáles.

Necesitas un plan que incluya sitio propio. Consulta los planes en https://invite.madify.mx/precios/.

9. Qué no se permite

  • Scripts que capturen datos de tus invitados y los manden a otros servidores, o formularios que apunten a otros sitios.
  • Contenido ilegal, engañoso u ofensivo, o que use marcas o imágenes sin permiso.
  • Intentar leer archivos del servidor o romper el sistema (la página se rechaza).

¿Dudas? Escríbenos a contacto@madify.mx.