Documentación para IAs y Desarrolladores: Cómo Crear Cartas Web-2 y Web-2-Form

Esta documentación explica cómo crear cartas en Luz de Dedicación. Se cubren los dos tipos principales: web-2 (estándar) y web-2-form (con formulario). La explicación se presenta de manera estructurada.

Importante: Todas las cartas deben seguir reglas estrictas para su funcionamiento. Utilice comentarios en el HTML para definir variables, con el formato . Las variables DEBEN ir siempre inmediatamente después de <!DOCTYPE html> (antes de <html> o en las primeras líneas de <head>). Esto permite que el sistema las procese correctamente.

1. Descripción de las Cartas Web-2 y Web-2-Form

Las cartas son páginas HTML que se integran en la aplicación. Se almacenan en la tabla "dedicaciones" de Supabase, con columnas como ruta (URL base), ruta_imagen (imagen de vista previa), tipo ("web-2") y form (verdadero o falso para indicar si incluye formulario).

En la tabla, el tipo se establece siempre en "web-2". La columna form indica si es interactiva (true) o estándar (false).

2. Reglas Fundamentales de Variables

Tipos de datos soportados: El sistema soporta los siguientes tipos de variables (los mismos que view.html puede leer y procesar):

Posición de las variables: Todas las variables en forma de comentarios DEBEN estar ubicadas inmediatamente después de <!DOCTYPE html>, preferiblemente en las primeras líneas antes de <html> o dentro de <head> al inicio. Esto es esencial para que el sistema las reconozca y procese correctamente.

Comportamiento de datos faltantes: Si un usuario accede a la carta sin proporcionar un valor para una variable, NUNCA se deja ese campo en blanco. En su lugar, se utiliza automáticamente el valor default especificado en el comentario de la variable. Esto garantiza que la carta siempre se vea completa y profesional.

Parámetro ?json= para editar variables: Solo las variables que llegan a través de ?json= en la URL pueden ser editadas dinámicamente. Este parámetro contiene exclusivamente las variables que el usuario o el sistema desea modificar. Cualquier variable no incluida en este parámetro mantiene su valor default.

Ejemplo de URL con parámetro ?json=:

https://tudominio.com/carta/?json={"page_title":"Mi Amor","message":"Te amo","background_image":"https://example.com/custom-bg.jpg","fecha":"14/02/2026"}

En este caso, solo las variables page_title, message, background_image y fecha se sobrescriben. Cualquier otra variable definida usa su valor default.

Nota sobre fechas: La variable fecha con tipo "date" siempre se transmite en formato DD/MM/YYYY. En el ejemplo anterior, "14/02/2026" representa el 14 de febrero de 2026.

4. Creación de una Carta Web-2 (Estándar)

Para una carta web-2 estándar, desarrolle un HTML con variables definidas en comentarios. No requiere formularios ni llamadas al worker. View.html la carga desde la ruta (URL base).

Pasos:

  1. Cree un archivo index.html que esté hosteado en un servidor web. La web debe estar deployada y accesible en línea.
  2. Defina las variables en comentarios inmediatamente después de <!DOCTYPE html>:
<!DOCTYPE html>
<!-- Variable: page_title | text | Valor por defecto: Mi Carta Simple -->
<!-- Variable: message | text | Valor por defecto: Te quiero mucho -->
<!-- Variable: background_image | url | Valor por defecto: https://example.com/fondo.jpg -->
<!-- Variable: special_date | date | Valor por defecto: 14/02/2026 -->
<!-- Variable: is_special | bool | Valor por defecto: false -->
<html lang="es">

3. En el cuerpo del HTML, utilice las variables con JavaScript:

<body>
    <h1 id="title"></h1>
    <p id="msg"></p>
    <p id="date-display"></p>
    <script>
        // Extraer variables de la URL (?json=)
        const urlParams = new URLSearchParams(window.location.search);
        const jsonParam = urlParams.get('json');
        const vars = jsonParam ? JSON.parse(jsonParam) : {};
        
        // Usar variable o valor default si no viene en ?json=
        document.getElementById('title').textContent = vars.page_title || 'Mi Carta Simple';
        document.getElementById('msg').textContent = vars.message || 'Te quiero mucho';
        document.body.style.backgroundImage = `url(${vars.background_image || 'https://example.com/fondo.jpg'})`;
        
        // Manejo de fecha (formato DD/MM/YYYY)
        const fecha = vars.special_date || '14/02/2026';
        document.getElementById('date-display').textContent = `Fecha especial: ${fecha}`;
        
        // Manejo de booleano
        const esEspecial = vars.is_special === 'true' || vars.is_special === true;
        if (esEspecial) {
            document.body.classList.add('special-mode');
        }
    </script>
</body>

4. Asegúrese de que su web esté hosteada en un servidor y obtenga la URL base (ejemplo: https://tudominio.com/carta/). En la tabla dedicaciones, establezca tipo = "web-2" y form = false.

View.html carga la carta desde esa ruta y genera el QR para compartir.

5. Creación de una Carta Web-2-Form (con Formulario)

Para web-2-form, incluya interacciones como botones. Siempre realice llamadas al worker para conectar con el canal y enviar mensajes. En la tabla, tipo = "web-2" y form = true.

Pasos:

  1. Cree un archivo index.html con variables en comentarios inmediatamente después de <!DOCTYPE html>, similar al ejemplo proporcionado. Este archivo debe estar hosteado y deployado en un servidor web accesible:
<!DOCTYPE html>
<!-- Variable: page_title | text | Valor por defecto: ¿Me perdonas? -->
<!-- Variable: main_question | text | Valor por defecto: ¿Me perdonas? -->
<!-- Variable: yes_button | text | Valor por defecto: Sí -->
<!-- Variable: no_button | text | Valor por defecto: No -->
<!-- Variable: thank_message | text | Valor por defecto: ¡Gracias por perdonarme! -->
<!-- Variable: promise_text | text | Valor por defecto: Prometo mejorar -->
<!-- Variable: happy_gif | url | Valor por defecto: https://media.tenor.com/bWUeVRqW9-IAAAAi/fast-cat-cat-excited.gif -->
<!-- Variable: redirect_url | url | Valor por defecto:  -->
<html lang="es">

2. Incluya botones y lógica para interacciones. Primero, extraiga las variables del parámetro ?json=, luego use sus valores o los defaults. Agregue la llamada al worker con los cuatro parámetros requeridos:

// Extraer variables de la URL (?json=)
const urlParams = new URLSearchParams(window.location.search);
const jsonParam = urlParams.get('json');
const vars = jsonParam ? JSON.parse(jsonParam) : {};

// Usar variables o valores defaults
const pageTitle = vars.page_title || '¿Me perdonas?';
const mainQuestion = vars.main_question || '¿Me perdonas?';
const yesButton = vars.yes_button || 'Sí';
const noButton = vars.no_button || 'No';

const IDenlace = urlParams.get('IDenlace') || '';
const IDpuerto = urlParams.get('IDpuerto') || '';
const workerUrl = 'https://luzdedicacion.aaronalexisquispe64-humwindroit.workers.dev/';
const IDproyecto = 'b2858ced-ff38-4c1f-ab76-119796d090a5';

async function sendToWorker(message) {
    try {
        await fetch(`${workerUrl}?IDproyecto=${IDproyecto}&IDenlace=${IDenlace}&IDpuerto=${IDpuerto}`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ mensaje: message })
        });
    } catch (e) {
        console.error('Error enviando a worker:', e);
    }
}

3. Llame a sendToWorker() en eventos, por ejemplo en el botón Sí:

document.getElementById('si').addEventListener('click', function() {
    // Código de respuesta
    sendToWorker('La persona que le enviaste esto te perdonó');
});

Para el botón No, envíe mensajes como 'No quiere perdonarte'.

4. Asegúrese de que su archivo está hosteado en un servidor accesible y obtenga la URL base. En la tabla dedicaciones, establezca tipo = "web-2" y form = true. El worker gestiona el canal para notificaciones.

Reglas clave: (1) Las variables en comentarios DEBEN ir inmediatamente después de <!DOCTYPE html>. (2) Si un dato no viene en ?json=, nunca va en blanco: se usa el valor default. (3) Solo los parámetros en ?json= pueden sobrescribir variables; cualquier otro parámetro de URL se ignora. (4) Utilice siempre los cuatro parámetros exactos para el worker y defina variables con el formato preciso en comentarios.

6. Validación y Manejo de JSON

Validación del parámetro ?json=: El parámetro debe ser un JSON válido y estar correctamente codificado en la URL (usando encodeURIComponent en JavaScript).

Caracteres especiales: Si tus variables contienen acentos (á, é, í, ó, ú), ñ, o caracteres especiales, deben escaparse correctamente en el JSON:

// Correcto:
?json={"mensaje":"Te quiero mucho","nombre":"María"}

// Incorrecto (causará error):
?json={"mensaje":"Te quiero mucho","nombre":"María"}  // sin comillas escapadas

// Para caracteres especiales en el JSON:
const vars = {
    mensaje: "Te quiero mucho",
    nombre: "María",
    dedicacion: "¡Eres lo mejor!"
};
const jsonString = JSON.stringify(vars);
const encodedJson = encodeURIComponent(jsonString);
const url = `https://tudominio.com/carta/?json=${encodedJson}`;

Límites de tamaño: El parámetro ?json= tiene un límite recomendado de 2000 caracteres (límite de URL estándar es 2048). Para cartas con muchas variables, considere valores defaults más cortos.

7. Seguridad y Buenas Prácticas

Validación en el lado del cliente: Siempre valida el JSON parseado antes de usarlo:

const urlParams = new URLSearchParams(window.location.search);
const jsonParam = urlParams.get('json');
let vars = {};

if (jsonParam) {
    try {
        const decoded = decodeURIComponent(jsonParam);
        vars = JSON.parse(decoded);
        
        // Validar que solo contiene variables esperadas
        const allowedVars = ['page_title', 'message', 'background_image'];
        for (let key in vars) {
            if (!allowedVars.includes(key)) {
                console.warn(`Variable no esperada: ${key}`);
                delete vars[key];
            }
        }
    } catch (e) {
        console.error('JSON inválido en parámetro:', e);
        vars = {}; // Usar todos los valores defaults
    }
}

Protección contra XSS: Si muestras contenido de variables en el HTML, escapalo adecuadamente:

// Inseguro (permite XSS):
document.getElementById('title').innerHTML = vars.page_title;

// Seguro:
document.getElementById('title').textContent = vars.page_title;

// O si necesitas HTML:
function escapeHtml(text) {
    const map = {
        '&': '&',
        '<': '<',
        '>': '>',
        '"': '"',
        "'": '''
    };
    return text.replace(/[&<>"']/g, m => map[m]);
}
document.getElementById('title').innerHTML = escapeHtml(vars.page_title);

HTTPS obligatorio: Todas las cartas deben servirse sobre HTTPS. Las URLs sin HTTPS serán bloqueadas por navegadores modernos.

8. Errores Comunes y Troubleshooting

Error: "Variables no aparecen en el formulario"

Causas posibles:

Solución: Verifica que el comentario sea exactamente: <!-- Variable: nombre | tipo | Valor por defecto: valor -->

Error: "El ?json= no funciona"

Causas posibles:

Solución: Usa JSON.stringify() + encodeURIComponent() en JavaScript. Prueba con una herramienta como JSONLint antes de usarlo.

Error: "Las fechas se ven incorrectas"

Causas posibles:

Solución: Siempre transmite fechas como string en formato "DD/MM/YYYY". Si necesitas convertir un Date de JavaScript a este formato: const fecha = [d.getDate(), d.getMonth()+1, d.getFullYear()].map(n => String(n).padStart(2,'0')).join('/');

Error: "El worker no recibe mis mensajes"

Causas posibles:

Solución: Abre la consola del navegador (F12), ve a Network, y verifica que la llamada fetch al worker devuelva status 200 o al menos no lance error.

9. Mejores Prácticas

10. Recursos Útiles

Esta documentación se actualiza regularmente. Última actualización: 8 de enero de 2026.