Solicitud enviada
Tu cuenta está pendiente de aprobación por el administrador del Team Inquebrantables. Te notificaremos cuando tengas acceso. Normalmente tarda menos de 24 horas.
👋
¡Hola! Configura
tu perfil
Estos datos se usarán automáticamente en tus creativos, carruseles y landing pages. Todo es opcional — puedes completarlo después desde tu perfil.
Tu nombre completo Opcional
Número de WhatsApp Opcional
Tu link de distribuidor Farmasi Opcional
Link de registro como socio Opcional
Ciudad o región Opcional
Puedes editar esta información en cualquier momento desde tu perfil en la esquina superior derecha.
Bienvenido de vuelta
Cargando... 🦅
0
Creativos
0
Carruseles
0
Landings
0
Total generados
— Herramientas disponibles
01 · Meta Ads
Disponible
🎨
Creativos
Imágenes publicitarias en formatos 1:1, 4:5 y 9:16 con copy generado por IA y caption para redes.
1:1 Feed 4:5 Instagram 9:16 Stories
02 · Secuencia
Disponible
🎠
Carruseles
Hasta 10 slides con narrativa psicológica — shock, curiosidad, lista, educativo o transformación.
Hasta 10 slides Narrativa IA CTA integrado
03 · Web
Disponible
🚀
Landing Pages
5 tipos de landing page generadas con IA, editables y publicadas automáticamente en Netlify.
Venta directa Captura leads Link-in-bio VSL
— Actividad reciente
Ver todo →
Todo listo para crear
Tus generaciones aparecerán aquí. Elige un módulo arriba para empezar.
Panel de Administración
axelfarmasi@gmail.com
👥 Usuarios pendientes
0
No hay solicitudes pendientes ✓
✅ Usuarios aprobados
0
Sin usuarios aprobados aún
`; } // ─── PREVIEW ─── function verModoPreview(modo) { const wrap = document.getElementById('land-preview-wrap'); wrap.className = modo === 'mobile' ? 'land-preview-wrap mobile' : 'land-preview-wrap'; } // ─── DESCARGAR ─── function descargarLanding() { if (!landingHTMLGenerada) return; const blob = new Blob([landingHTMLGenerada], { type: 'text/html' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = (landingDatosActual.subdominio || 'landing') + '.html'; a.click(); } // ─── PUBLICAR EN NETLIFY ─── async function publicarLanding() { if (!landingHTMLGenerada) return; const subdominio = landingDatosActual.subdominio || ('landing-' + Date.now()); mostrarToast('Publicando en Netlify...', 'info'); try { // Crear site en Netlify const siteRes = await fetch('https://api.netlify.com/api/v1/sites', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${NETLIFY_TOKEN}` }, body: JSON.stringify({ name: subdominio }) }); const site = await siteRes.json(); if (!site.id) throw new Error('No se pudo crear el site: ' + JSON.stringify(site)); // Subir como deploy const encoder = new TextEncoder(); const bytes = encoder.encode(landingHTMLGenerada); const deployRes = await fetch(`https://api.netlify.com/api/v1/sites/${site.id}/deploys`, { method: 'POST', headers: { 'Content-Type': 'application/zip', 'Authorization': `Bearer ${NETLIFY_TOKEN}`, }, body: await crearZipSimple(landingHTMLGenerada) }); const deploy = await deployRes.json(); const url = `https://${site.subdomain}.netlify.app`; mostrarToast('¡Publicado! ' + url, 'exito'); // Guardar en historial con URL await guardarLandingHistorial(url, site.id); // Mostrar link const linkEl = document.createElement('div'); linkEl.style.cssText = 'margin-top:12px; padding:12px; background:var(--naranja-dim); border:1px solid var(--naranja); border-radius:10px; font-size:13px;'; linkEl.innerHTML = `🚀 Tu landing está en: ${url}`; document.getElementById('land-paso-4').appendChild(linkEl); } catch(e) { mostrarToast('Error al publicar: ' + e.message, 'error'); console.error(e); } } async function crearZipSimple(htmlContent) { // Crear un FormData con el HTML como si fuera un ZIP simple // Netlify acepta deploys de un solo archivo si se envía con el Content-Type correcto // Usamos la API de files en lugar de ZIP const siteId = landingDatosActual.netlitySiteId; // Alternativa: usar deploy de archivos individuales via multipart // Por simplicidad enviamos el HTML comprimido como Blob const blob = new Blob([htmlContent], { type: 'text/html' }); return blob; } // ─── GUARDAR ─── async function guardarLandingHistorial(urlPublicada = '', siteId = '') { if (!usuarioActual) return; try { await db.collection('generaciones').add({ uid: usuarioActual.uid, tipo: 'landing', subTipo: landingDatosActual.tipo || 'venta', nombreProd: landingDatosActual.prodNombre || '', titulo: landingDatosActual.prodNombre || 'Landing page', urlPublicada, siteId, paleta: landingDatosActual.paleta || '', htmlSnapshot: landingHTMLGenerada.substring(0, 500), creadoEn: firebase.firestore.FieldValue.serverTimestamp() }); mostrarToast('Guardado en historial ✓', 'exito'); cargarDashboard(); } catch(e) { console.error('Error guardando landing:', e); } } // ─── MIS LANDINGS ─── async function cargarMisLandings() { const cont = document.getElementById('mis-landings-lista'); cont.innerHTML = '
Cargando...
'; try { const snap = await db.collection('generaciones') .where('uid', '==', usuarioActual.uid) .where('tipo', '==', 'landing') .orderBy('creadoEn', 'desc').limit(20).get(); if (snap.empty) { cont.innerHTML = '
🚀
Sin landings aún
Crea tu primera landing page arriba.
'; return; } cont.innerHTML = ''; snap.forEach(doc => { const d = doc.data(); const fecha = d.creadoEn?.toDate?.()?.toLocaleDateString('es-MX', {day:'2-digit',month:'short',year:'numeric'}) || ''; const tipoLabel = {venta:'💰 Venta',gracias:'🎉 Gracias',leads:'📧 Leads',linkinbio:'🔗 Link bio',prospecto:'🤝 Prospección'}[d.subTipo] || '🚀 Landing'; cont.innerHTML += `
${d.titulo || d.nombreProd || 'Landing page'}
${tipoLabel} · ${fecha}
${d.urlPublicada ? `` : '
Sin publicar aún
'}
${d.urlPublicada ? `` : ''}
`; }); } catch(e) { cont.innerHTML = '
Error al cargar.
'; } }