AiGAP Studio
/ Projects / Ready build #2841 · 2 min ago
Open in new tab
Alex Rivera usr_aig_K7M2NQ
Profile Settings Billing Back to onboarding
Chat · iterative editing Aigap live
send · Shift+↵ new line Aigap Framework · gpt-4 class
🔒 aigap.com/runtime/rt_aig_BUTCE_2841
build #2841 time: 0.42s boyut: 142KB
✓ Aigap runtime · healthy
§ Solution Package · v2.3.1 · pkg_aig_REST_2841
🍽

Restaurant Management Solution

Full package for restaurant management — POS, menu, reservations, inventory, staff.

Live
Modules 4
Total Builds 47
Last Update 2 min ago
Deploy URL restoran-paketim.aigap.com

Modules

Each module runs independently, deploys as a package

Package Actions

`, pomodoro: `
Odak modu — 02 / 04 seans
14:23
Deep work
12
Sessions today
3.5
Hours
7
Day streak
`, kanban: `

Kanban Board

RUNTIME · build #2256
To-do3
Read client brief
urgentfriday
Prepare presentation
3 hours
Second draft
next week
In progress2
Design iteration 3
design
API entegrasyonu
%60
In review1
Login flow
QA
Tamam5
Meeting notes
yesterday
Spec writing
2 days ago
Early coffee
3 days ago
`, yoga: `
Sun Salutation · Pose 4 / 12

Adho Mukha Svanasana

04
Downward Facing Dog
— deep breath, lengthen back
00:32
— nefes al · ver —
`, tarif: `

Tarif Defteri

RUNTIME · build #3104 · 14 tarif
Tarif №7

Pancakes, maple syrup

4 servings30 mineasy
Method
01

Whisk flour, eggs and milk into a smooth batter. Rest 5 minutes.

02

Pour into a hot pan, cook 2 minutes per side until golden.

03

Drizzle with maple syrup and serve warm.

04

Pul biber ile servis edin. Afiyet olsun.

`, }; // ============================================================== // STATE & DOM // ============================================================== // Placeholder runtime for projects without full templates function makePlaceholderRuntime(p) { const initials = p.name.split(' ').slice(0,2).map(s => s[0] || '').join('').toUpperCase(); const safeName = p.name.replace(/(\w+)$/, '$1'); return [ '', '

' + safeName + '

', '
RUNTIME PREVIEW build #' + p.buildNum + 'aigap live
', '
', '
Total
', '
Bu hafta
', '
', '
', '
' + initials + '
', '
' + initials + '
', '
' + initials + '
', '
', '
Loading full preview…
', '' ].join(''); } let activeProj = 'butce'; const messagesEl = document.getElementById('messages'); const suggestionsEl = document.getElementById('suggestions'); const projNameEl = document.getElementById('projName'); const buildMetaEl = document.getElementById('buildMeta'); const buildStatusEl = document.getElementById('buildStatus'); const runtimeIdEl = document.getElementById('runtimeId'); const footBuildEl = document.getElementById('footBuild'); const runtimeFrame = document.getElementById('runtimeFrame'); const composer = document.getElementById('composerInput'); const sendBtn = document.getElementById('sendBtn'); const quotaUsed = document.getElementById('quotaUsed'); const quotaFill = document.getElementById('quotaFill'); let quotaUsedNum = 3; let totalQuota = 5; // ============================================================== // RENDER // ============================================================== function escapeHtml(s) { return String(s).replace(/&/g,'&').replace(//g,'>'); } function renderMessage(m) { if (m.type === 'system') { const el = document.createElement('div'); el.className = 'msg system'; el.textContent = m.text; return el; } if (m.type === 'build') { const el = document.createElement('div'); el.className = 'build-card'; el.innerHTML = `
Runtime build #${PROJECTS[activeProj].buildNum}
${m.steps.map(s => `
${s}
`).join('')}
`; return el; } const el = document.createElement('div'); el.className = 'msg ' + m.type; if (m.html) el.innerHTML = m.html; else el.textContent = m.text; return el; } function renderProject(key) { activeProj = key; const p = PROJECTS[key]; if (!p) return; // Update sidebar active state document.querySelectorAll('.proj-item').forEach(b => b.classList.toggle('active', b.dataset.proj === key)); // Update top bar projNameEl.value = p.name; buildMetaEl.textContent = `build #${p.buildNum} · ${p.lastUpdate}`; runtimeIdEl.textContent = p.runtimeId; footBuildEl.textContent = '#' + p.buildNum; // Render messages messagesEl.innerHTML = ''; p.messages.forEach(m => messagesEl.appendChild(renderMessage(m))); messagesEl.scrollTop = messagesEl.scrollHeight; // Render suggestions suggestionsEl.innerHTML = p.suggestions.map(s => `` ).join(''); suggestionsEl.querySelectorAll('.suggestion-chip').forEach(c => { c.addEventListener('click', () => { composer.value = c.textContent.replace(/^\\+\\s*/, ''); composer.focus(); autoResize(); }); }); // Update runtime frame runtimeFrame.srcdoc = RUNTIME_TEMPLATES[key] || makePlaceholderRuntime(p); } // ============================================================== // INTERACTIONS // ============================================================== // Project switching document.querySelectorAll('.proj-item').forEach(b => { b.addEventListener('click', () => renderProject(b.dataset.proj)); }); // Composer auto-resize function autoResize() { composer.style.height = '40px'; composer.style.height = Math.min(composer.scrollHeight, 140) + 'px'; } composer.addEventListener('input', autoResize); // Send message function send() { const text = composer.value.trim(); if (!text) return; if (quotaUsedNum >= totalQuota) { showToast('Daily build limit reached', 'UPGRADE TO PRO TO CONTINUE'); return; } // Add user message messagesEl.appendChild(renderMessage({ type: 'user', text })); composer.value = ''; autoResize(); messagesEl.scrollTop = messagesEl.scrollHeight; // Bot typing → response → build setTimeout(() => { // Typing indicator const typingEl = document.createElement('div'); typingEl.className = 'msg bot'; typingEl.innerHTML = '
'; messagesEl.appendChild(typingEl); messagesEl.scrollTop = messagesEl.scrollHeight; setTimeout(() => { typingEl.remove(); // Bot response const botMsg = document.createElement('div'); botMsg.className = 'msg bot'; botMsg.innerHTML = 'AIGAPGot it. Applying the change — will come alive in the right panel within seconds.'; messagesEl.appendChild(botMsg); // Build status: building buildStatusEl.textContent = 'Building'; buildStatusEl.classList.add('building'); setTimeout(() => { // Build card const buildSteps = ['intent parsed', 'module scaffolding', 'state graph refreshed', 'runtime deploy', 'preview ready']; const buildEl = document.createElement('div'); buildEl.className = 'build-card'; buildEl.innerHTML = `
Runtime build #${PROJECTS[activeProj].buildNum + 1}
${buildSteps.map(() => '
').join('')}
`; messagesEl.appendChild(buildEl); messagesEl.scrollTop = messagesEl.scrollHeight; // Animate build steps const stepEls = buildEl.querySelectorAll('.s'); let idx = 0; const stepTick = () => { if (idx >= stepEls.length) { // Final bot message const final = document.createElement('div'); final.className = 'msg bot'; final.innerHTML = `AIGAPReady. build #${PROJECTS[activeProj].buildNum + 1} · 0.${Math.floor(30+Math.random()*40)}s. You'll see it in the right panel.`; messagesEl.appendChild(final); messagesEl.scrollTop = messagesEl.scrollHeight; // Update build counter PROJECTS[activeProj].buildNum += 1; PROJECTS[activeProj].lastUpdate = 'now'; buildMetaEl.textContent = `build #${PROJECTS[activeProj].buildNum} · now`; footBuildEl.textContent = '#' + PROJECTS[activeProj].buildNum; buildStatusEl.textContent = 'Ready'; buildStatusEl.classList.remove('building'); // Refresh iframe (simulate rebuild) runtimeFrame.contentWindow.location.reload(); // Quota quotaUsedNum = Math.min(totalQuota, quotaUsedNum + 1); quotaUsed.textContent = quotaUsedNum; quotaFill.style.width = (quotaUsedNum / totalQuota * 100) + '%'; return; } const stepText = buildSteps[idx]; stepEls[idx].textContent = stepText; stepEls[idx].classList.add('done'); idx++; setTimeout(stepTick, 220 + Math.random() * 280); }; stepTick(); }, 600); }, 900 + Math.random() * 600); }, 200); } sendBtn.addEventListener('click', send); composer.addEventListener('keydown', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }); // Project name editable projNameEl.addEventListener('blur', () => { PROJECTS[activeProj].name = projNameEl.value; document.querySelector(`.proj-item[data-proj="${activeProj}"] .proj-info-block b`).textContent = projNameEl.value; showToast('Project name updated', projNameEl.value); }); projNameEl.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); projNameEl.blur(); } }); // Device toggle document.querySelectorAll('#deviceToggle button').forEach(b => { b.addEventListener('click', () => { document.querySelectorAll('#deviceToggle button').forEach(x => x.classList.remove('active')); b.classList.add('active'); const body = document.getElementById('runtimeBody'); body.classList.remove('desktop', 'tablet', 'mobile'); body.classList.add(b.dataset.device); }); }); // Refresh button document.getElementById('refreshBtn').addEventListener('click', () => { runtimeFrame.contentWindow.location.reload(); showToast('Runtime refreshed'); }); // Share button document.getElementById('shareBtn').addEventListener('click', () => { showToast('Share link copied', 'AIGAP.COM/' + activeProj.toUpperCase()); }); // Open live button document.getElementById('openLiveBtn').addEventListener('click', (e) => { e.preventDefault(); document.getElementById('openTabBtn').click(); }); // History button document.getElementById('historyBtn').addEventListener('click', () => { showToast('Build history', PROJECTS[activeProj].buildNum + ' BUILDS FOR THIS PROJECT'); }); // New project document.getElementById('newProject').addEventListener('click', () => { showToast('Opening new project templates', 'CHOOSE YOUR STARTING POINT'); }); // User dropdown const avatarBtn = document.getElementById('avatarBtn'); const userDropdown = document.getElementById('userDropdown'); avatarBtn.addEventListener('click', (e) => { e.stopPropagation(); userDropdown.classList.toggle('open'); }); document.addEventListener('click', (e) => { if (!userDropdown.contains(e.target) && e.target !== avatarBtn) { userDropdown.classList.remove('open'); } }); // Toast function showToast(msg, meta) { let toast = document.getElementById('studioToast'); if (!toast) { toast = document.createElement('div'); toast.id = 'studioToast'; toast.className = 'toast'; document.body.appendChild(toast); } toast.innerHTML = '
' + msg + '
' + (meta ? `
${meta}
` : ''); requestAnimationFrame(() => toast.classList.add('show')); clearTimeout(toast._t); toast._t = setTimeout(() => toast.classList.remove('show'), 3500); } // Initial render renderProject('butce'); // ============================================================== // SOLUTION PACKAGES // ============================================================== const SOLUTIONS = { restaurant: { name: 'Restaurant Management Solution', nameEn: 'Restaurant Management Suite', icon: '🍽', accentColor: '#e51f36', packageId: 'pkg_aig_REST_2841', description: 'Full package for restaurant operations — POS, menu, reservations, inventory, staff.', descriptionEn: 'Complete restaurant operations suite — POS, menu, reservations, inventory, staff.', version: '2.3.1', totalBuilds: 47, lastUpdate: '2 min ago', deployStatus: 'live', deployUrl: 'restoran-paketim.aigap.com', modules: [ { id: 'rest-pos', name: 'POS System', desc: 'Register, payment, receipt printing', runtimeId: 'rt_aig_POS_2841', buildNum: 142, lastUpdate: '2 min ago', status: 'healthy', icon: '💳' }, { id: 'rest-menu', name: 'Menu Management', desc: 'Products, categories, pricing', runtimeId: 'rt_aig_MENU_1923', buildNum: 87, lastUpdate: '1 hour ago', status: 'healthy', icon: '📋' }, { id: 'rest-res', name: 'Reservations', desc: 'Tables, customers, reminders', runtimeId: 'rt_aig_RES_0432', buildNum: 34, lastUpdate: '3 hours ago', status: 'healthy', icon: '📅' }, { id: 'rest-stok', name: 'Inventory', desc: 'Suppliers, count, waste report', runtimeId: 'rt_aig_STOK_0156', buildNum: 12, lastUpdate: 'build error', status: 'error', icon: '📦' }, ], }, ecommerce: { name: 'E-commerce Solution', nameEn: 'E-commerce Solution', icon: '🛒', accentColor: '#2d7a4f', packageId: 'pkg_aig_ECOM_4118', description: 'Full-stack e-commerce — catalog, cart, payment, orders, customer management in one package.', descriptionEn: 'Full-stack e-commerce — catalog, cart, checkout, orders, customer management.', version: '4.1.0', totalBuilds: 128, lastUpdate: '15 min ago', deployStatus: 'live', deployUrl: 'magaza.aigap.com', modules: [ { id: 'ec-catalog', name: 'Catalog Management', desc: 'Products, categories, variants, image CMS', runtimeId: 'rt_aig_CAT_5231', buildNum: 87, lastUpdate: '15 min ago', status: 'healthy', icon: '📚' }, { id: 'ec-cart', name: 'Cart & Checkout', desc: 'Cart, shipping options, discount codes', runtimeId: 'rt_aig_CART_3902', buildNum: 65, lastUpdate: '2 hours ago', status: 'healthy', icon: '🛍' }, { id: 'ec-pay', name: 'Payment', desc: 'Stripe, PayPal, bank transfer, Apple Pay', runtimeId: 'rt_aig_PAY_4118', buildNum: 124, lastUpdate: '1 day ago', status: 'healthy', icon: '💳' }, { id: 'ec-order', name: 'Order Management', desc: 'Order tracking, shipping, returns flow', runtimeId: 'rt_aig_ORD_2876', buildNum: 91, lastUpdate: 'now', status: 'building', icon: '📮' }, { id: 'ec-cust', name: 'Customer', desc: 'Account, order history, loyalty', runtimeId: 'rt_aig_CUST_1043', buildNum: 53, lastUpdate: '6 hours ago', status: 'healthy', icon: '👤' }, ], }, clinic: { name: 'Clinic Management Solution', nameEn: 'Clinic Management Suite', icon: '🏥', accentColor: '#2a4a6b', packageId: 'pkg_aig_CLIN_0921', description: 'Appointment, patient, prescription, and billing management for dental, dermatology, and physiotherapy clinics.', descriptionEn: 'Dental, dermatology, physio clinics — appointments, patients, prescriptions, billing.', version: '1.8.4', totalBuilds: 23, lastUpdate: '1 day ago', deployStatus: 'staging', deployUrl: 'klinik-staging.aigap.com', modules: [ { id: 'cl-apt', name: 'Appointments', desc: 'Calendar, slots, SMS reminders', runtimeId: 'rt_aig_APT_0921', buildNum: 8, lastUpdate: '1 day ago', status: 'healthy', icon: '📅' }, { id: 'cl-pat', name: 'Patient Records', desc: 'History, file upload, anamnesis', runtimeId: 'rt_aig_PAT_0512', buildNum: 6, lastUpdate: '2 days ago', status: 'healthy', icon: '📑' }, { id: 'cl-rx', name: 'Prescriptions', desc: 'Medication, dosage, treatment plan', runtimeId: 'rt_aig_RX_0234', buildNum: 5, lastUpdate: '3 days ago', status: 'healthy', icon: '💊' }, { id: 'cl-bil', name: 'Billing', desc: 'Insurance, private, installments, e-invoice', runtimeId: 'rt_aig_BIL_0188', buildNum: 4, lastUpdate: '5 days ago', status: 'building', icon: '🧾' }, ], }, }; // ============================================================ // I18N — multi-language support // ============================================================ const I18N = { en: { 'studio.brand.suffix': 'Studio', 'studio.tab.projects': 'Projects', 'studio.tab.solutions': 'Solutions', 'studio.btn.newProject': '+ New project', 'studio.btn.newSolution': '+ New solution package', 'studio.search.placeholder': 'Search…', 'studio.quickLinks.title': 'Quick access', 'studio.quickLinks.templates': 'Templates', 'studio.quickLinks.history': 'Build history', 'studio.quickLinks.api': 'API keys', 'studio.quickLinks.docs': 'Documentation', 'studio.upgrade.cta': '↗ Upgrade to Pro', 'studio.btn.history': 'History', 'studio.btn.share': 'Share', 'studio.btn.openLive': 'Open in new tab', 'studio.user.profile': 'Profile', 'studio.user.settings': 'Settings', 'studio.user.billing': 'Billing', 'studio.user.changePlan': 'Change plan', 'studio.user.onboarding': 'Back to onboarding', 'studio.user.logout': 'Sign out', 'studio.composer.placeholder': 'Write a message, start a build…', 'studio.composer.hint': 'Enter to send · Shift+Enter for new line', 'studio.sol.crumb': '§ Solution Package', 'studio.sol.modules': 'Modules', 'studio.sol.totalBuilds': 'Total Builds', 'studio.sol.lastUpdate': 'Last Update', 'studio.sol.deployUrl': 'Deploy URL', 'studio.sol.modulesTitle': 'Modules', 'studio.sol.modulesHint': 'Each module runs independently, deploys as a package', 'studio.sol.addModule': '+ Add new module', 'studio.sol.packageActions': 'Package Actions', 'studio.sol.deployAll': 'Deploy entire package', 'studio.sol.deployAllSub': 'Push all modules live in one go', 'studio.sol.download': 'Download package', 'studio.sol.downloadSub': '.aigap.zip file — self-host on your server', 'studio.sol.settings': 'Package settings', 'studio.sol.settingsSub': 'Name, version, dependencies, environment variables', 'studio.sol.archive': 'Archive package', 'studio.sol.archiveSub': 'Modules frozen, can be restored later', 'studio.deploy.live': 'Live', 'studio.deploy.staging': 'Staging', 'studio.deploy.draft': 'Draft', 'studio.module.healthy': 'healthy', 'studio.module.building': 'building', 'studio.module.error': 'build error', 'studio.breadcrumb.back': '← Back to package', 'studio.lang.label': 'Language', }, tr: { 'studio.brand.suffix': 'Studio', 'studio.tab.projects': 'Projeler', 'studio.tab.solutions': 'Çözümler', 'studio.btn.newProject': '+ Yeni proje', 'studio.btn.newSolution': '+ Yeni çözüm paketi', 'studio.search.placeholder': 'Ara…', 'studio.quickLinks.title': 'Hızlı erişim', 'studio.quickLinks.templates': 'Şablonlar', 'studio.quickLinks.history': 'Build geçmişi', 'studio.quickLinks.api': 'API anahtarları', 'studio.quickLinks.docs': 'Dokümantasyon', 'studio.upgrade.cta': '↗ Pro\'ya yükselt', 'studio.btn.history': 'Geçmiş', 'studio.btn.share': 'Paylaş', 'studio.btn.openLive': 'Yeni sekmede aç', 'studio.user.profile': 'Profil', 'studio.user.settings': 'Ayarlar', 'studio.user.billing': 'Faturalama', 'studio.user.changePlan': 'Plan değiştir', 'studio.user.onboarding': 'Onboarding\'e dön', 'studio.user.logout': 'Çıkış yap', 'studio.composer.placeholder': 'Bir mesaj yaz, build başlat…', 'studio.composer.hint': 'Göndermek için Enter · Yeni satır için Shift+Enter', 'studio.sol.crumb': '§ Çözüm Paketi', 'studio.sol.modules': 'Modüller', 'studio.sol.totalBuilds': 'Toplam Build', 'studio.sol.lastUpdate': 'Son Güncelleme', 'studio.sol.deployUrl': 'Deploy URL', 'studio.sol.modulesTitle': 'Modüller', 'studio.sol.modulesHint': 'Her modül bağımsız çalışır, paket olarak deploy olur', 'studio.sol.addModule': '+ Yeni modül ekle', 'studio.sol.packageActions': 'Paket İşlemleri', 'studio.sol.deployAll': 'Tüm paketi deploy et', 'studio.sol.deployAllSub': 'Tüm modülleri tek seferde canlıya gönder', 'studio.sol.download': 'Paketi indir', 'studio.sol.downloadSub': '.aigap.zip dosyası — kendi sunucunda barındır', 'studio.sol.settings': 'Paket ayarları', 'studio.sol.settingsSub': 'Ad, versiyon, bağımlılıklar, ortam değişkenleri', 'studio.sol.archive': 'Paketi arşivle', 'studio.sol.archiveSub': 'Modüller dondurulur, sonra geri getirilebilir', 'studio.deploy.live': 'Canlı', 'studio.deploy.staging': 'Staging', 'studio.deploy.draft': 'Taslak', 'studio.module.healthy': 'sağlıklı', 'studio.module.building': 'derleniyor', 'studio.module.error': 'build hatası', 'studio.breadcrumb.back': '← Pakete dön', 'studio.lang.label': 'Dil', }, es: { 'studio.tab.projects': 'Proyectos', 'studio.tab.solutions': 'Soluciones', 'studio.btn.newProject': '+ Nuevo proyecto', 'studio.lang.label': 'Idioma', 'studio.brand.suffix': 'Studio', 'studio.btn.newSolution': '+ Nueva solución', 'studio.btn.history': 'Historial', 'studio.breadcrumb.back': '← Volver al paquete', 'studio.module.building': 'construyendo', 'studio.module.error': 'error de build' , 'studio.search.placeholder': 'Buscar…', 'studio.quickLinks.title': 'Acceso rápido', 'studio.quickLinks.templates': 'Plantillas', 'studio.quickLinks.history': 'Historial de builds', 'studio.quickLinks.api': 'Claves API', 'studio.quickLinks.docs': 'Documentación', 'studio.upgrade.cta': '↗ Subir a Pro', 'studio.btn.share': 'Compartir', 'studio.btn.openLive': 'Abrir en nueva pestaña', 'studio.user.profile': 'Perfil', 'studio.user.settings': 'Configuración', 'studio.user.billing': 'Facturación', 'studio.user.changePlan': 'Cambiar plan', 'studio.user.onboarding': 'Volver al onboarding', 'studio.user.logout': 'Cerrar sesión', 'studio.composer.placeholder': 'Escribe un mensaje, inicia un build…', 'studio.composer.hint': 'Enter para enviar · Shift+Enter para nueva línea', 'studio.sol.crumb': '§ Paquete de Solución', 'studio.sol.modules': 'Módulos', 'studio.sol.totalBuilds': 'Builds totales', 'studio.sol.lastUpdate': 'Última actualización', 'studio.sol.deployUrl': 'URL de despliegue', 'studio.sol.modulesTitle': 'Módulos', 'studio.sol.modulesHint': 'Cada módulo corre independiente, despliega como paquete', 'studio.sol.addModule': '+ Agregar nuevo módulo', 'studio.sol.packageActions': 'Acciones del paquete', 'studio.sol.deployAll': 'Desplegar paquete completo', 'studio.sol.deployAllSub': 'Lanza todos los módulos a producción de una vez', 'studio.sol.download': 'Descargar paquete', 'studio.sol.downloadSub': 'Archivo .aigap.zip — auto-hostea en tu servidor', 'studio.sol.settings': 'Configuración del paquete', 'studio.sol.settingsSub': 'Nombre, versión, dependencias, variables de entorno', 'studio.sol.archive': 'Archivar paquete', 'studio.sol.archiveSub': 'Módulos congelados, restaurables después', 'studio.deploy.live': 'En vivo', 'studio.deploy.staging': 'Staging', 'studio.deploy.draft': 'Borrador', 'studio.module.healthy': 'saludable' }, de: { 'studio.tab.projects': 'Projekte', 'studio.tab.solutions': 'Lösungen', 'studio.btn.newProject': '+ Neues Projekt', 'studio.lang.label': 'Sprache', 'studio.brand.suffix': 'Studio', 'studio.btn.newSolution': '+ Neue Lösung', 'studio.btn.history': 'Verlauf', 'studio.breadcrumb.back': '← Zurück zum Paket', 'studio.module.building': 'wird gebaut', 'studio.module.error': 'Build-Fehler' , 'studio.search.placeholder': 'Suchen…', 'studio.quickLinks.title': 'Schnellzugriff', 'studio.quickLinks.templates': 'Vorlagen', 'studio.quickLinks.history': 'Build-Verlauf', 'studio.quickLinks.api': 'API-Schlüssel', 'studio.quickLinks.docs': 'Dokumentation', 'studio.upgrade.cta': '↗ Auf Pro upgraden', 'studio.btn.share': 'Teilen', 'studio.btn.openLive': 'In neuem Tab öffnen', 'studio.user.profile': 'Profil', 'studio.user.settings': 'Einstellungen', 'studio.user.billing': 'Abrechnung', 'studio.user.changePlan': 'Plan ändern', 'studio.user.onboarding': 'Zurück zum Onboarding', 'studio.user.logout': 'Abmelden', 'studio.composer.placeholder': 'Nachricht schreiben, Build starten…', 'studio.composer.hint': 'Enter zum Senden · Shift+Enter für neue Zeile', 'studio.sol.crumb': '§ Lösungspaket', 'studio.sol.modules': 'Module', 'studio.sol.totalBuilds': 'Gesamt Builds', 'studio.sol.lastUpdate': 'Letztes Update', 'studio.sol.deployUrl': 'Deploy-URL', 'studio.sol.modulesTitle': 'Module', 'studio.sol.modulesHint': 'Jedes Modul läuft unabhängig, deployt als Paket', 'studio.sol.addModule': '+ Neues Modul hinzufügen', 'studio.sol.packageActions': 'Paket-Aktionen', 'studio.sol.deployAll': 'Gesamtes Paket deployen', 'studio.sol.deployAllSub': 'Alle Module auf einmal live setzen', 'studio.sol.download': 'Paket herunterladen', 'studio.sol.downloadSub': '.aigap.zip Datei — selbst hosten', 'studio.sol.settings': 'Paket-Einstellungen', 'studio.sol.settingsSub': 'Name, Version, Abhängigkeiten, Umgebungsvariablen', 'studio.sol.archive': 'Paket archivieren', 'studio.sol.archiveSub': 'Module eingefroren, später wiederherstellbar', 'studio.deploy.live': 'Live', 'studio.deploy.staging': 'Staging', 'studio.deploy.draft': 'Entwurf', 'studio.module.healthy': 'gesund' }, fr: { 'studio.tab.projects': 'Projets', 'studio.tab.solutions': 'Solutions', 'studio.btn.newProject': '+ Nouveau projet', 'studio.lang.label': 'Langue', 'studio.brand.suffix': 'Studio', 'studio.btn.newSolution': '+ Nouvelle solution', 'studio.btn.history': 'Historique', 'studio.breadcrumb.back': '← Retour au pack', 'studio.module.building': 'compilation', 'studio.module.error': 'erreur de build' , 'studio.search.placeholder': 'Rechercher…', 'studio.quickLinks.title': 'Accès rapide', 'studio.quickLinks.templates': 'Modèles', 'studio.quickLinks.history': 'Historique des builds', 'studio.quickLinks.api': 'Clés API', 'studio.quickLinks.docs': 'Documentation', 'studio.upgrade.cta': '↗ Passer à Pro', 'studio.btn.share': 'Partager', 'studio.btn.openLive': 'Ouvrir dans un nouvel onglet', 'studio.user.profile': 'Profil', 'studio.user.settings': 'Paramètres', 'studio.user.billing': 'Facturation', 'studio.user.changePlan': 'Changer de plan', 'studio.user.onboarding': 'Retour à l\'onboarding', 'studio.user.logout': 'Déconnexion', 'studio.composer.placeholder': 'Écris un message, lance un build…', 'studio.composer.hint': 'Entrée pour envoyer · Maj+Entrée pour nouvelle ligne', 'studio.sol.crumb': '§ Package Solution', 'studio.sol.modules': 'Modules', 'studio.sol.totalBuilds': 'Builds totaux', 'studio.sol.lastUpdate': 'Dernière mise à jour', 'studio.sol.deployUrl': 'URL de déploiement', 'studio.sol.modulesTitle': 'Modules', 'studio.sol.modulesHint': 'Chaque module tourne indépendamment, déployé comme package', 'studio.sol.addModule': '+ Ajouter un nouveau module', 'studio.sol.packageActions': 'Actions du package', 'studio.sol.deployAll': 'Déployer le package entier', 'studio.sol.deployAllSub': 'Mettre tous les modules en ligne en une fois', 'studio.sol.download': 'Télécharger le package', 'studio.sol.downloadSub': 'Fichier .aigap.zip — auto-héberge sur ton serveur', 'studio.sol.settings': 'Paramètres du package', 'studio.sol.settingsSub': 'Nom, version, dépendances, variables d\'environnement', 'studio.sol.archive': 'Archiver le package', 'studio.sol.archiveSub': 'Modules gelés, restaurables plus tard', 'studio.deploy.live': 'En ligne', 'studio.deploy.staging': 'Staging', 'studio.deploy.draft': 'Brouillon', 'studio.module.healthy': 'sain' }, ar: { 'studio.tab.projects': 'المشاريع', 'studio.tab.solutions': 'الحلول', 'studio.btn.newProject': '+ مشروع جديد', 'studio.lang.label': 'اللغة', 'studio.brand.suffix': 'Studio', 'studio.btn.newSolution': '+ حل جديد', 'studio.btn.history': 'السجل', 'studio.breadcrumb.back': '← العودة للحزمة', 'studio.module.building': 'جارٍ البناء', 'studio.module.error': 'خطأ في البناء' , 'studio.search.placeholder': 'بحث…', 'studio.quickLinks.title': 'الوصول السريع', 'studio.quickLinks.templates': 'القوالب', 'studio.quickLinks.history': 'سجل البناء', 'studio.quickLinks.api': 'مفاتيح API', 'studio.quickLinks.docs': 'الوثائق', 'studio.upgrade.cta': '↗ الترقية إلى Pro', 'studio.btn.share': 'مشاركة', 'studio.btn.openLive': 'فتح في علامة تبويب جديدة', 'studio.user.profile': 'الملف الشخصي', 'studio.user.settings': 'الإعدادات', 'studio.user.billing': 'الفوترة', 'studio.user.changePlan': 'تغيير الخطة', 'studio.user.onboarding': 'العودة للإعداد', 'studio.user.logout': 'تسجيل الخروج', 'studio.composer.placeholder': 'اكتب رسالة، ابدأ بناءً…', 'studio.composer.hint': 'Enter للإرسال · Shift+Enter لسطر جديد', 'studio.sol.crumb': '§ حزمة حل', 'studio.sol.modules': 'الوحدات', 'studio.sol.totalBuilds': 'إجمالي البنيات', 'studio.sol.lastUpdate': 'آخر تحديث', 'studio.sol.deployUrl': 'رابط النشر', 'studio.sol.modulesTitle': 'الوحدات', 'studio.sol.modulesHint': 'كل وحدة تعمل مستقلة، تُنشر كحزمة', 'studio.sol.addModule': '+ إضافة وحدة جديدة', 'studio.sol.packageActions': 'إجراءات الحزمة', 'studio.sol.deployAll': 'نشر الحزمة كاملة', 'studio.sol.deployAllSub': 'انشر كل الوحدات مباشرة دفعة واحدة', 'studio.sol.download': 'تنزيل الحزمة', 'studio.sol.downloadSub': 'ملف .aigap.zip — استضف ذاتياً على خادمك', 'studio.sol.settings': 'إعدادات الحزمة', 'studio.sol.settingsSub': 'الاسم، الإصدار، التبعيات، متغيرات البيئة', 'studio.sol.archive': 'أرشفة الحزمة', 'studio.sol.archiveSub': 'الوحدات مجمدة، يمكن استعادتها لاحقاً', 'studio.deploy.live': 'مباشر', 'studio.deploy.staging': 'تجريبي', 'studio.deploy.draft': 'مسودة', 'studio.module.healthy': 'سليم' }, ru: { 'studio.tab.projects': 'Проекты', 'studio.tab.solutions': 'Решения', 'studio.btn.newProject': '+ Новый проект', 'studio.lang.label': 'Язык', 'studio.brand.suffix': 'Studio', 'studio.btn.newSolution': '+ Новое решение', 'studio.btn.history': 'История', 'studio.breadcrumb.back': '← Назад к пакету', 'studio.module.building': 'сборка', 'studio.module.error': 'ошибка сборки' , 'studio.search.placeholder': 'Поиск…', 'studio.quickLinks.title': 'Быстрый доступ', 'studio.quickLinks.templates': 'Шаблоны', 'studio.quickLinks.history': 'История билдов', 'studio.quickLinks.api': 'API-ключи', 'studio.quickLinks.docs': 'Документация', 'studio.upgrade.cta': '↗ Перейти на Pro', 'studio.btn.share': 'Поделиться', 'studio.btn.openLive': 'Открыть в новой вкладке', 'studio.user.profile': 'Профиль', 'studio.user.settings': 'Настройки', 'studio.user.billing': 'Биллинг', 'studio.user.changePlan': 'Сменить тариф', 'studio.user.onboarding': 'Вернуться к онбордингу', 'studio.user.logout': 'Выйти', 'studio.composer.placeholder': 'Напишите сообщение, начните билд…', 'studio.composer.hint': 'Enter — отправить · Shift+Enter — новая строка', 'studio.sol.crumb': '§ Пакет решения', 'studio.sol.modules': 'Модули', 'studio.sol.totalBuilds': 'Всего билдов', 'studio.sol.lastUpdate': 'Обновлено', 'studio.sol.deployUrl': 'URL развёртывания', 'studio.sol.modulesTitle': 'Модули', 'studio.sol.modulesHint': 'Каждый модуль работает независимо, разворачивается как пакет', 'studio.sol.addModule': '+ Добавить новый модуль', 'studio.sol.packageActions': 'Действия с пакетом', 'studio.sol.deployAll': 'Развернуть весь пакет', 'studio.sol.deployAllSub': 'Запустить все модули в продакшен сразу', 'studio.sol.download': 'Скачать пакет', 'studio.sol.downloadSub': 'Файл .aigap.zip — самохостинг на вашем сервере', 'studio.sol.settings': 'Настройки пакета', 'studio.sol.settingsSub': 'Имя, версия, зависимости, переменные окружения', 'studio.sol.archive': 'Архивировать пакет', 'studio.sol.archiveSub': 'Модули заморожены, можно восстановить позже', 'studio.deploy.live': 'В сети', 'studio.deploy.staging': 'Staging', 'studio.deploy.draft': 'Черновик', 'studio.module.healthy': 'здоров' }, pt: { 'studio.tab.projects': 'Projetos', 'studio.tab.solutions': 'Soluções', 'studio.btn.newProject': '+ Novo projeto', 'studio.lang.label': 'Idioma', 'studio.brand.suffix': 'Studio', 'studio.btn.newSolution': '+ Nova solução', 'studio.btn.history': 'Histórico', 'studio.breadcrumb.back': '← Voltar ao pacote', 'studio.module.building': 'construindo', 'studio.module.error': 'erro de build' , 'studio.search.placeholder': 'Buscar…', 'studio.quickLinks.title': 'Acesso rápido', 'studio.quickLinks.templates': 'Templates', 'studio.quickLinks.history': 'Histórico de builds', 'studio.quickLinks.api': 'Chaves API', 'studio.quickLinks.docs': 'Documentação', 'studio.upgrade.cta': '↗ Upgrade para Pro', 'studio.btn.share': 'Compartilhar', 'studio.btn.openLive': 'Abrir em nova aba', 'studio.user.profile': 'Perfil', 'studio.user.settings': 'Configurações', 'studio.user.billing': 'Cobrança', 'studio.user.changePlan': 'Mudar plano', 'studio.user.onboarding': 'Voltar ao onboarding', 'studio.user.logout': 'Sair', 'studio.composer.placeholder': 'Escreva uma mensagem, inicie um build…', 'studio.composer.hint': 'Enter para enviar · Shift+Enter para nova linha', 'studio.sol.crumb': '§ Pacote de Solução', 'studio.sol.modules': 'Módulos', 'studio.sol.totalBuilds': 'Total de builds', 'studio.sol.lastUpdate': 'Última atualização', 'studio.sol.deployUrl': 'URL de deploy', 'studio.sol.modulesTitle': 'Módulos', 'studio.sol.modulesHint': 'Cada módulo roda independente, faz deploy como pacote', 'studio.sol.addModule': '+ Adicionar novo módulo', 'studio.sol.packageActions': 'Ações do pacote', 'studio.sol.deployAll': 'Deploy do pacote inteiro', 'studio.sol.deployAllSub': 'Coloca todos os módulos no ar de uma vez', 'studio.sol.download': 'Baixar pacote', 'studio.sol.downloadSub': 'Arquivo .aigap.zip — auto-hospede no seu servidor', 'studio.sol.settings': 'Configurações do pacote', 'studio.sol.settingsSub': 'Nome, versão, dependências, variáveis de ambiente', 'studio.sol.archive': 'Arquivar pacote', 'studio.sol.archiveSub': 'Módulos congelados, podem ser restaurados depois', 'studio.deploy.live': 'Ao vivo', 'studio.deploy.staging': 'Staging', 'studio.deploy.draft': 'Rascunho', 'studio.module.healthy': 'saudável' }, ja: { 'studio.tab.projects': 'プロジェクト', 'studio.tab.solutions': 'ソリューション', 'studio.btn.newProject': '+ 新規プロジェクト', 'studio.lang.label': '言語', 'studio.brand.suffix': 'Studio', 'studio.btn.newSolution': '+ 新規ソリューション', 'studio.btn.history': '履歴', 'studio.breadcrumb.back': '← パッケージに戻る', 'studio.module.building': 'ビルド中', 'studio.module.error': 'ビルドエラー' , 'studio.search.placeholder': '検索…', 'studio.quickLinks.title': 'クイックアクセス', 'studio.quickLinks.templates': 'テンプレート', 'studio.quickLinks.history': 'ビルド履歴', 'studio.quickLinks.api': 'APIキー', 'studio.quickLinks.docs': 'ドキュメント', 'studio.upgrade.cta': '↗ Proにアップグレード', 'studio.btn.share': '共有', 'studio.btn.openLive': '新しいタブで開く', 'studio.user.profile': 'プロフィール', 'studio.user.settings': '設定', 'studio.user.billing': '請求', 'studio.user.changePlan': 'プラン変更', 'studio.user.onboarding': 'オンボーディングに戻る', 'studio.user.logout': 'サインアウト', 'studio.composer.placeholder': 'メッセージを書く、ビルド開始…', 'studio.composer.hint': 'Enterで送信 · Shift+Enterで改行', 'studio.sol.crumb': '§ ソリューションパッケージ', 'studio.sol.modules': 'モジュール', 'studio.sol.totalBuilds': '総ビルド数', 'studio.sol.lastUpdate': '最終更新', 'studio.sol.deployUrl': 'デプロイURL', 'studio.sol.modulesTitle': 'モジュール', 'studio.sol.modulesHint': '各モジュールは独立して動作、パッケージとしてデプロイ', 'studio.sol.addModule': '+ 新規モジュール追加', 'studio.sol.packageActions': 'パッケージ操作', 'studio.sol.deployAll': 'パッケージ全体をデプロイ', 'studio.sol.deployAllSub': '全モジュールを一度にライブ反映', 'studio.sol.download': 'パッケージダウンロード', 'studio.sol.downloadSub': '.aigap.zip ファイル — 自分のサーバーでセルフホスト', 'studio.sol.settings': 'パッケージ設定', 'studio.sol.settingsSub': '名前、バージョン、依存関係、環境変数', 'studio.sol.archive': 'パッケージをアーカイブ', 'studio.sol.archiveSub': 'モジュール凍結、後で復元可能', 'studio.deploy.live': 'ライブ', 'studio.deploy.staging': 'ステージング', 'studio.deploy.draft': '下書き', 'studio.module.healthy': '正常' }, zh: { 'studio.tab.projects': '项目', 'studio.tab.solutions': '解决方案', 'studio.btn.newProject': '+ 新项目', 'studio.lang.label': '语言', 'studio.brand.suffix': 'Studio', 'studio.btn.newSolution': '+ 新解决方案', 'studio.btn.history': '历史', 'studio.breadcrumb.back': '← 返回包', 'studio.module.building': '构建中', 'studio.module.error': '构建错误' , 'studio.search.placeholder': '搜索…', 'studio.quickLinks.title': '快速访问', 'studio.quickLinks.templates': '模板', 'studio.quickLinks.history': '构建历史', 'studio.quickLinks.api': 'API 密钥', 'studio.quickLinks.docs': '文档', 'studio.upgrade.cta': '↗ 升级到 Pro', 'studio.btn.share': '分享', 'studio.btn.openLive': '在新标签页打开', 'studio.user.profile': '个人资料', 'studio.user.settings': '设置', 'studio.user.billing': '账单', 'studio.user.changePlan': '更改套餐', 'studio.user.onboarding': '返回引导', 'studio.user.logout': '退出登录', 'studio.composer.placeholder': '写一条消息,开始构建…', 'studio.composer.hint': 'Enter 发送 · Shift+Enter 换行', 'studio.sol.crumb': '§ 解决方案包', 'studio.sol.modules': '模块', 'studio.sol.totalBuilds': '总构建数', 'studio.sol.lastUpdate': '最后更新', 'studio.sol.deployUrl': '部署 URL', 'studio.sol.modulesTitle': '模块', 'studio.sol.modulesHint': '每个模块独立运行,作为包部署', 'studio.sol.addModule': '+ 添加新模块', 'studio.sol.packageActions': '包操作', 'studio.sol.deployAll': '部署整个包', 'studio.sol.deployAllSub': '一次性将所有模块上线', 'studio.sol.download': '下载包', 'studio.sol.downloadSub': '.aigap.zip 文件 — 在您的服务器自托管', 'studio.sol.settings': '包设置', 'studio.sol.settingsSub': '名称、版本、依赖、环境变量', 'studio.sol.archive': '归档包', 'studio.sol.archiveSub': '模块已冻结,之后可恢复', 'studio.deploy.live': '在线', 'studio.deploy.staging': '预发布', 'studio.deploy.draft': '草稿', 'studio.module.healthy': '健康' } }; let currentLang = 'en'; try { const savedLang = localStorage.getItem('aigap_lang'); if (savedLang && I18N[savedLang]) currentLang = savedLang; } catch(e) {} function t(key) { return (I18N[currentLang] && I18N[currentLang][key]) || (I18N.en[key] || key); } function applyI18n(lang) { if (!I18N[lang]) I18N[lang] = {}; currentLang = lang; try { localStorage.setItem('aigap_lang', lang); } catch(e) {} document.documentElement.lang = lang; document.documentElement.dir = (lang==='ar') ? "rtl" : "ltr"; // Update text content of [data-i18n] elements document.querySelectorAll('[data-i18n]').forEach(el => { const key = el.dataset.i18n; const val = I18N[lang][key]; if (val !== undefined) el.textContent = val; }); // Update placeholders document.querySelectorAll('[data-i18n-placeholder]').forEach(el => { const key = el.dataset.i18nPlaceholder; const val = I18N[lang][key]; if (val !== undefined) el.placeholder = val; }); // Update title attributes document.querySelectorAll('[data-i18n-title]').forEach(el => { const key = el.dataset.i18nTitle; const val = I18N[lang][key]; if (val !== undefined) el.title = val; }); // Update language button display const langCode = document.querySelector('.lang-btn .lang-code'); const langFlag = document.getElementById('langBtnFlag'); if (langCode) langCode.textContent = lang.toUpperCase(); if (langFlag) langFlag.textContent = (lang === 'tr') ? '🇹🇷' : '🇬🇧'; document.querySelectorAll('.lang-dropdown button').forEach(b => { b.classList.toggle('active', b.dataset.lang === lang); }); // If solution overview is visible, re-render to apply translated strings if (currentMode === 'solution' && activeSolution) { renderSolutionOverview(activeSolution); } } // ============================================================ // LANGUAGE SWITCHER — dropdown wiring // ============================================================ (function initLangSwitcher() { const langBtn = document.getElementById('langBtn'); const langDropdown = document.getElementById('langDropdown'); if (!langBtn || !langDropdown) return; langBtn.addEventListener('click', (e) => { e.stopPropagation(); langDropdown.classList.toggle('open'); }); langDropdown.querySelectorAll('button[data-lang]').forEach(btn => { btn.addEventListener('click', (e) => { e.stopPropagation(); const lang = btn.dataset.lang; applyI18n(lang); langDropdown.classList.remove('open'); }); }); document.addEventListener('click', (e) => { if (!langBtn.contains(e.target) && !langDropdown.contains(e.target)) { langDropdown.classList.remove('open'); } }); // Apply saved language on load applyI18n(currentLang); })(); // ============================================================ // SIDEBAR TABS — Projects / Solutions // ============================================================ let activeSidebarTab = 'projects'; const sideTabs = document.querySelectorAll('.side-tab'); const sidePanes = document.querySelectorAll('.side-list-pane'); function switchSidebarTab(tabName) { activeSidebarTab = tabName; sideTabs.forEach(t => t.classList.toggle('active', t.dataset.tab === tabName)); sidePanes.forEach(p => p.classList.toggle('hidden', p.dataset.list !== tabName)); // Toggle "+ Yeni" button document.querySelectorAll('[data-mode-projects]').forEach(el => el.hidden = (tabName !== 'projects')); document.querySelectorAll('[data-mode-solutions]').forEach(el => el.hidden = (tabName !== 'solutions')); // Reset search if (searchInput) { searchInput.value = ''; applySearchFilter(); } } sideTabs.forEach(tab => { tab.addEventListener('click', () => switchSidebarTab(tab.dataset.tab)); }); // ============================================================ // SOLUTIONS rendering // ============================================================ const solList = document.getElementById('sideSolutions'); function renderSolutionsList() { if (!solList) return; solList.innerHTML = ''; Object.entries(SOLUTIONS).forEach(([key, sol]) => { const btn = document.createElement('button'); btn.className = 'sol-item'; btn.dataset.sol = key; btn.dataset.name = sol.name; const statusClass = sol.deployStatus; const statusLabel = t('studio.deploy.' + sol.deployStatus); btn.innerHTML = '' + sol.icon + '' + '' + '' + sol.name + '' + '' + sol.modules.length + ' modules · v' + sol.version + '' + ''; btn.addEventListener('click', () => openSolution(key)); solList.appendChild(btn); }); } // ============================================================ // MODE SWITCHING — project | solution | module // ============================================================ let currentMode = 'project'; // 'project' | 'solution' | 'module' let activeSolution = null; let activeModule = null; const mainEl = document.querySelector('.main'); function setMode(mode) { currentMode = mode; mainEl.classList.remove('mode-project', 'mode-solution', 'mode-module'); mainEl.classList.add('mode-' + mode); } function openSolution(solKey) { activeSolution = solKey; activeModule = null; // Clear active states document.querySelectorAll('.proj-item.active').forEach(el => el.classList.remove('active')); document.querySelectorAll('.sol-item.active').forEach(el => el.classList.remove('active')); // Mark this solution active const solItem = document.querySelector('.sol-item[data-sol="' + solKey + '"]'); if (solItem) solItem.classList.add('active'); setMode('solution'); renderSolutionOverview(solKey); // Update top bar breadcrumb const proj = SOLUTIONS[solKey]; if (projNameEl) projNameEl.value = proj.name; if (buildStatusEl) { buildStatusEl.textContent = t('studio.deploy.' + proj.deployStatus); buildStatusEl.className = 'build-status ' + (proj.deployStatus === 'live' ? 'healthy' : 'building'); } if (buildMetaEl) buildMetaEl.textContent = 'v' + proj.version + ' · ' + proj.modules.length + ' modules'; } function renderSolutionOverview(solKey) { const sol = SOLUTIONS[solKey]; if (!sol) return; // Header document.getElementById('solIcon').textContent = sol.icon; document.getElementById('solName').textContent = sol.name; document.getElementById('solDesc').textContent = sol.description; document.getElementById('solVersion').textContent = sol.version; document.getElementById('solPackageId').textContent = sol.packageId; document.getElementById('solModuleCount').textContent = sol.modules.length; document.getElementById('solTotalBuilds').textContent = sol.totalBuilds; document.getElementById('solLastUpdate').textContent = sol.lastUpdate; document.getElementById('solDeployUrl').textContent = sol.deployUrl; // Status const statusEl = document.getElementById('solDeployStatus'); statusEl.className = 'sol-deploy-status ' + sol.deployStatus; document.getElementById('solDeployStatusText').textContent = t('studio.deploy.' + sol.deployStatus); // Modules list const modList = document.getElementById('solModulesList'); modList.innerHTML = ''; sol.modules.forEach(m => { const card = document.createElement('div'); card.className = 'module-card'; card.dataset.module = m.id; const statusLabel = t('studio.module.' + m.status); card.innerHTML = '
' + m.icon + '
' + '
' + '' + m.name + '' + '' + m.desc + '' + 'build #' + m.buildNum + ' · ' + m.lastUpdate + '' + '
' + '' + m.runtimeId + '' + '' + statusLabel + ''; card.addEventListener('click', () => openModule(solKey, m.id)); modList.appendChild(card); }); } function openModule(solKey, modId) { const sol = SOLUTIONS[solKey]; const mod = sol.modules.find(m => m.id === modId); if (!mod) return; activeSolution = solKey; activeModule = modId; setMode('module'); // Render in chat panel — minimal greeting message if (messagesEl) { messagesEl.innerHTML = '
' + sol.name + ' › ' + mod.name + ' opened
' + '
AIGAP' + mod.name + '. ' + mod.desc + '. Part of the ' + sol.name + ' package. What would you like to build?
'; messagesEl.scrollTop = messagesEl.scrollHeight; } // Update runtime preview if (runtimeFrame) { runtimeFrame.srcdoc = makePlaceholderRuntime({ name: mod.name, buildNum: mod.buildNum }); } // Update URL bar const rid = document.getElementById('runtimeId'); if (rid) rid.textContent = mod.runtimeId; // Update top bar breadcrumb if (projNameEl) projNameEl.value = mod.name; if (buildStatusEl) { buildStatusEl.textContent = t('studio.module.' + mod.status); buildStatusEl.className = 'build-status ' + (mod.status === 'healthy' ? 'healthy' : (mod.status === 'building' ? 'building' : 'error')); } if (buildMetaEl) buildMetaEl.textContent = 'build #' + mod.buildNum + ' · ' + mod.lastUpdate; // Show breadcrumb back link const bcb = document.getElementById('breadcrumbBack'); if (bcb) { bcb.hidden = false; bcb.querySelector('span').textContent = '← ' + sol.name; } } // Click on existing project items - back to project mode document.querySelectorAll('.proj-item').forEach(item => { const orig = item.onclick; item.addEventListener('click', () => { activeSolution = null; activeModule = null; setMode('project'); // Hide breadcrumb back const bcb = document.getElementById('breadcrumbBack'); if (bcb) bcb.hidden = true; }); }); // Breadcrumb back to package const bcbEl = document.getElementById('breadcrumbBack'); if (bcbEl) { bcbEl.addEventListener('click', (e) => { e.preventDefault(); if (activeSolution) openSolution(activeSolution); }); } // New solution button const newSolutionBtn = document.getElementById('newSolution'); if (newSolutionBtn) { newSolutionBtn.addEventListener('click', () => { showToast(t('studio.btn.newSolution'), 'CHOOSE FROM SOLUTION PACKAGE TEMPLATES'); }); } // Solution overview action buttons ['deployAllBtn','downloadBtn','settingsBtn','archiveBtn','addModuleBtn'].forEach(id => { const btn = document.getElementById(id); if (btn) btn.addEventListener('click', () => { const labels = { deployAllBtn: t('studio.sol.deployAll'), downloadBtn: t('studio.sol.download'), settingsBtn: t('studio.sol.settings'), archiveBtn: t('studio.sol.archive'), addModuleBtn: t('studio.sol.addModule'), }; showToast(labels[id], 'ACTION TRIGGERED'); }); }); // Initial render renderSolutionsList(); applyI18n(currentLang); setMode('project'); // ============= UPGRADE MODAL ============= const upgOverlay = document.getElementById('upgOverlay'); const upgModal = document.getElementById('upgModal'); const upgClose = document.getElementById('upgClose'); function openUpgrade() { upgOverlay.classList.add('open'); upgModal.classList.remove('is-loading', 'is-success'); document.body.style.overflow = 'hidden'; } function closeUpgrade() { upgOverlay.classList.remove('open'); document.body.style.overflow = ''; setTimeout(() => upgModal.classList.remove('is-loading', 'is-success'), 350); } upgClose.addEventListener('click', closeUpgrade); upgOverlay.addEventListener('click', (e) => { if (e.target === upgOverlay) closeUpgrade(); }); document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && upgOverlay.classList.contains('open')) closeUpgrade(); }); document.querySelectorAll('[data-upgrade-open]').forEach(el => { el.addEventListener('click', (e) => { e.preventDefault(); const dd = document.getElementById('userDropdown'); if (dd) dd.classList.remove('open'); openUpgrade(); }); }); let selectedPlan = 'pro'; const PLAN_PRICES = { starter: { base: 0, name: 'Starter' }, pro: { base: 299, name: 'Pro' }, gold: { base: 1499, name: 'Gold' }, }; function updateSummary() { const planName = PLAN_PRICES[selectedPlan].name; const rates = PROVIDER_RATES[activeProvider]; const base = PROVIDER_PRICES[activeProvider][selectedPlan]; const tax = rates.taxIncluded ? 0 : base * rates.taxRate; const total = base + tax; const sym = rates.symbol; document.getElementById('summLabel').textContent = planName + ' Plan · monthly'; document.getElementById('summBase').textContent = sym + base.toFixed(2); document.getElementById('summTax').textContent = rates.taxIncluded ? 'auto by LS' : sym + tax.toFixed(2); // Update tax row label dynamically const summTaxRow = document.getElementById('summTax').parentElement; const taxLabel = summTaxRow.querySelector('span:first-child'); if (taxLabel) taxLabel.textContent = rates.taxName; document.getElementById('summTotal').innerHTML = sym + total.toFixed(2) + '/mo'; document.getElementById('upgConfirmAmount').textContent = sym + total.toFixed(2); if (activeProvider === 'iyzico') { document.getElementById('upgConfirmText').textContent = "Upgrade to " + planName; } } document.querySelectorAll('.upg-plan').forEach(btn => { btn.addEventListener('click', () => { if (btn.disabled) return; document.querySelectorAll('.upg-plan').forEach(b => b.classList.remove('selected')); btn.classList.add('selected'); selectedPlan = btn.dataset.plan; updateSummary(); }); }); const payNumber = document.getElementById('payNumber'); const payExpiry = document.getElementById('payExpiry'); const payCvc = document.getElementById('payCvc'); const payBrand = document.getElementById('payCardBrand'); payNumber.addEventListener('input', (e) => { const raw = e.target.value.replace(/\D/g, '').slice(0, 16); const groups = raw.match(/.{1,4}/g); e.target.value = groups ? groups.join(' ') : ''; if (raw.startsWith('4')) { payBrand.textContent = 'VISA'; payBrand.className = 'ico visa'; payBrand.style.color = ''; } else if (raw.startsWith('5') || raw.startsWith('2')) { payBrand.textContent = 'MC'; payBrand.className = 'ico'; payBrand.style.color = '#eb001b'; } else if (raw.startsWith('3')) { payBrand.textContent = 'AMEX'; payBrand.className = 'ico'; payBrand.style.color = '#006fcf'; } else { payBrand.textContent = 'XXXX'; payBrand.className = 'ico'; payBrand.style.color = ''; } }); payExpiry.addEventListener('input', (e) => { let v = e.target.value.replace(/\D/g, '').slice(0, 4); if (v.length >= 3) v = v.slice(0, 2) + '/' + v.slice(2); e.target.value = v; }); payCvc.addEventListener('input', (e) => { e.target.value = e.target.value.replace(/\D/g, '').slice(0, 4); }); // ============= PAYMENT PROVIDER TOGGLE ============= let activeProvider = 'stripe'; // 'stripe' | 'lemon' | 'iyzico' const PROVIDER_RATES = { stripe: { currency: 'USD', symbol: '$', usdRate: 0.028, taxRate: 0, taxName: 'Tax (Stripe Tax automatic)', taxIncluded: true }, lemon: { currency: 'USD', symbol: '$', usdRate: 0.028, taxRate: 0, taxName: 'Tax (LS automatic)', taxIncluded: true }, iyzico: { currency: 'TRY', symbol: '₺', usdRate: 1, taxRate: 0.20, taxName: 'VAT (20%)', taxIncluded: false }, }; const PROVIDER_PRICES = { stripe: { starter: 0, pro: 9.99, gold: 49.99 }, lemon: { starter: 0, pro: 9.99, gold: 49.99 }, iyzico: { starter: 0, pro: 299, gold: 1499 }, }; // Stripe Checkout — Price IDs (one per plan + interval). // These come from Stripe Dashboard → Products → Plans. // Replace with real values at deploy time (or fetch from /api/billing/price-map). const STRIPE_PRICE_IDS = { pro: { monthly: '__STRIPE_PRICE_PRO_MONTHLY__', annual: '__STRIPE_PRICE_PRO_ANNUAL__' }, gold: { monthly: '__STRIPE_PRICE_GOLD_MONTHLY__', annual: '__STRIPE_PRICE_GOLD_ANNUAL__' } }; function switchProvider(prov) { activeProvider = prov; document.querySelectorAll('.prov-btn').forEach(b => b.classList.toggle('active', b.dataset.prov === prov)); document.querySelectorAll('.prov-pane').forEach(p => p.classList.toggle('active', p.dataset.provPane === prov)); updateSummary(); updateConfirmButton(); } function updateConfirmButton() { const confirmBtn = document.getElementById('upgConfirm'); const text = document.getElementById('upgConfirmText'); confirmBtn.classList.remove('lemon-style', 'stripe-style'); if (activeProvider === 'stripe') { confirmBtn.classList.add('stripe-style'); text.innerHTML = 'SPay with Stripe'; } else if (activeProvider === 'lemon') { confirmBtn.classList.add('lemon-style'); text.innerHTML = '🍋Pay with Lemon Squeezy'; } else { text.textContent = "Upgrade to " + PLAN_PRICES[selectedPlan].name; } } document.querySelectorAll('.prov-btn').forEach(btn => { btn.addEventListener('click', () => switchProvider(btn.dataset.prov)); }); // Trace steps differ per provider const TRACE_STEPS = { stripe: [ 'plan and price confirmed', 'creating Stripe Checkout Session', 'POST /v1/checkout/sessions', 'session_id received: cs_live_…', 'redirecting to checkout.stripe.com', ], lemon: [ 'plan and price confirmed', 'calling Lemon Squeezy checkout API', 'secure payment URL generated', 'user paid at checkout', 'webhook received: subscription_created', 'plan mapped to aigap_user_id', ], iyzico: [ 'card details verified', 'sending to iyzico', '3D Secure completed', 'mapping plan to aigap_user_id', 'creating memberships record', ], }; document.getElementById('upgConfirm').addEventListener('click', () => { // ===== STRIPE CHECKOUT ===== // Hosted-redirect flow: // 1) Backend creates a Checkout Session and returns its URL // 2) Browser is redirected to checkout.stripe.com // 3) After payment: Stripe redirects to success_url // 4) After cancel: Stripe redirects to cancel_url // 5) Backend webhook (checkout.session.completed) updates membership if (activeProvider === 'stripe') { startStripeCheckout(); return; } if (activeProvider === 'iyzico') { const name = document.getElementById('payName').value.trim(); const num = payNumber.value.replace(/\s/g, ''); const exp = payExpiry.value; const cvc = payCvc.value; if (!name || num.length < 13 || !/^\d{2}\/\d{2}$/.test(exp) || cvc.length < 3) { showToast('Please fill in all card details', 'ALL FIELDS REQUIRED'); return; } } // Lemon Squeezy: validation happens on their side after redirect // Update trace steps based on provider const traceEl = upgModal.querySelector('.upg-loading .trace'); const stepsForProvider = TRACE_STEPS[activeProvider]; traceEl.innerHTML = stepsForProvider.map(function(s, i) { return '
' + s + '
'; }).join(''); // Update loading message based on provider const loadingTitle = upgModal.querySelector('.upg-loading h4'); const loadingSub = upgModal.querySelector('.upg-loading p'); if (activeProvider === 'lemon') { loadingTitle.textContent = 'Redirecting to Lemon Squeezy'; loadingSub.innerHTML = 'checkout.lemonsqueezy.com · MoR secure transaction · back in seconds.'; } else { loadingTitle.textContent = 'Processing your payment'; loadingSub.textContent = 'Secure transaction via iyzico · back in seconds.'; } upgModal.classList.add('is-loading'); const stepEls = upgModal.querySelectorAll('.upg-loading .trace .step'); let i = 1; const tick = () => { if (i >= stepEls.length) { finishUpgrade(); return; } stepEls[i].classList.add('done'); i++; setTimeout(tick, 380 + Math.random() * 350); }; setTimeout(tick, 400); }); // ============= STRIPE CHECKOUT SESSION ============= // Calls our backend, which calls Stripe API and returns the session URL. // Then we redirect the browser to that URL. // // Backend endpoint: POST /api/billing/checkout/create // Body: { // plan: 'pro' | 'gold', // billing_interval: 'monthly' | 'annual', // price_id: , // aigap_user_id: // } // Backend pseudo-code: // const session = await stripe.checkout.sessions.create({ // mode: 'subscription', // line_items: [{ price: req.body.price_id, quantity: 1 }], // customer_email: user.email, // client_reference_id: user.aigap_user_id, // success_url: `${ORIGIN}/aigap-payment-success.html?session_id={CHECKOUT_SESSION_ID}&plan=${plan}&billing=${interval}`, // cancel_url: `${ORIGIN}/aigap-payment-canceled.html?session_id={CHECKOUT_SESSION_ID}`, // allow_promotion_codes: true, // automatic_tax: { enabled: true }, // subscription_data: { // trial_period_days: 0, // metadata: { aigap_user_id: user.aigap_user_id } // } // }); // return { ok: true, url: session.url, session_id: session.id }; async function startStripeCheckout() { const planKey = selectedPlan; // 'pro' | 'gold' const interval = 'monthly'; // could be tied to a billing toggle const priceMap = STRIPE_PRICE_IDS[planKey]; if (!priceMap) { showToast('No Stripe price ID defined for this plan', 'CONFIGURATION ERROR'); return; } // Save pending plan so success page can read it as a fallback display hint try { localStorage.setItem('aigap_pending_plan', planKey); localStorage.setItem('aigap_pending_billing', interval); } catch (e) {} // Show loading state with Stripe-specific trace const traceEl = upgModal.querySelector('.upg-loading .trace'); const stepsForProvider = TRACE_STEPS.stripe; traceEl.innerHTML = stepsForProvider.map(function(s, i) { return '
' + s + '
'; }).join(''); const loadingTitle = upgModal.querySelector('.upg-loading h4'); const loadingSub = upgModal.querySelector('.upg-loading p'); loadingTitle.textContent = 'Redirecting to Stripe Checkout'; loadingSub.innerHTML = 'checkout.stripe.com · PCI Level 1 · in seconds…'; upgModal.classList.add('is-loading'); const stepEls = upgModal.querySelectorAll('.upg-loading .trace .step'); let i = 1; const tick = () => { if (i >= stepEls.length) return; stepEls[i].classList.add('done'); i++; setTimeout(tick, 280 + Math.random() * 250); }; setTimeout(tick, 300); try { // ========== REAL FLOW (uncomment when backend ready) ========== // const res = await fetch('/api/billing/checkout/create', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // credentials: 'include', // body: JSON.stringify({ // plan: planKey, // billing_interval: interval, // price_id: priceMap[interval] // }) // }); // const data = await res.json(); // if (!data.ok) throw new Error(data.error || 'Checkout creation failed'); // window.location.href = data.url; // ========== DEV / PREVIEW FALLBACK ========== // If Stripe price IDs are still placeholders, simulate the flow by // routing to the success page directly (so the demo is usable without // a real Stripe account configured). const isPlaceholder = priceMap[interval].startsWith('__'); if (isPlaceholder) { await new Promise(r => setTimeout(r, 1400)); const demoSession = 'cs_demo_' + Math.random().toString(36).slice(2, 14); window.location.href = 'aigap-payment-success.html' + '?session_id=' + demoSession + '&plan=' + encodeURIComponent(planKey) + '&billing=' + encodeURIComponent(interval); return; } throw new Error('Stripe configured but backend not yet wired'); } catch (err) { console.error('Stripe Checkout failed:', err); upgModal.classList.remove('is-loading'); showToast('Could not start payment. Please try again.', 'STRIPE ERROR'); } } function finishUpgrade() { const planInfo = PLAN_PRICES[selectedPlan]; const rates = PROVIDER_RATES[activeProvider]; const base = PROVIDER_PRICES[activeProvider][selectedPlan]; const tax = rates.taxIncluded ? 0 : base * rates.taxRate; const total = base + tax; const today = new Date(); const renewDate = new Date(today.getTime() + 30*24*60*60*1000); const renewLabel = renewDate.toLocaleDateString('tr-TR', { day: 'numeric', month: 'long', year: 'numeric' }); const orderNumStr = activeProvider === 'lemon' ? '#LS_' + Math.random().toString(36).slice(2,8).toUpperCase() + '_' + (Math.floor(Math.random()*9000) + 1000) : '#AGP-2026-' + String(Math.floor(Math.random()*9000000) + 1000000); document.getElementById('orderNum').textContent = orderNumStr; document.getElementById('orderPlan').textContent = planInfo.name + ' · monthly · ' + (activeProvider === 'lemon' ? 'Lemon Squeezy' : 'iyzico'); document.getElementById('orderRenew').textContent = renewLabel; document.getElementById('orderTotal').textContent = rates.symbol + total.toFixed(2); const successPara = upgModal.querySelector('.upg-success p'); if (activeProvider === 'lemon' && successPara) { successPara.innerHTML = "You now have unlimited builds, custom domain, and API access in the Studio.
Receipt sent to your email from Lemon Squeezy."; } upgModal.classList.remove('is-loading'); upgModal.classList.add('is-success'); try { localStorage.setItem('aigap_plan', selectedPlan); localStorage.setItem('aigap_plan_renew', renewDate.toISOString()); localStorage.setItem('aigap_plan_orderNum', orderNumStr); localStorage.setItem('aigap_plan_provider', activeProvider); } catch(e) {} applyPlanToUI(selectedPlan); } function applyPlanToUI(plan) { const planCard = document.querySelector('.plan-card-side'); if (!planCard) return; const tag = planCard.querySelector('.plan-tag'); const name = planCard.querySelector('.plan-name'); const quotaFillEl = planCard.querySelector('#quotaFill'); const quotaRow = planCard.querySelector('.quota-row'); const upgradeLink = planCard.querySelector('.upgrade'); if (plan === 'pro') { planCard.classList.add('is-pro'); tag.innerHTML = 'Plan 02'; name.innerHTML = 'Pro active'; quotaRow.innerHTML = 'Unlimited✓ ACTIVE'; quotaFillEl.style.width = '100%'; quotaFillEl.style.background = 'var(--green)'; upgradeLink.textContent = 'Billing →'; upgradeLink.href = 'aigap-billing.html'; upgradeLink.removeAttribute('data-upgrade-open'); } else if (plan === 'gold') { planCard.classList.add('is-pro'); tag.innerHTML = 'Plan 03'; name.innerHTML = 'Gold ekip'; quotaRow.innerHTML = 'Unlimited✓ ENTERPRISE'; quotaFillEl.style.width = '100%'; quotaFillEl.style.background = 'var(--gold)'; upgradeLink.textContent = 'Billing →'; upgradeLink.href = 'aigap-billing.html'; upgradeLink.removeAttribute('data-upgrade-open'); } } document.getElementById('successClose').addEventListener('click', (e) => { e.preventDefault(); closeUpgrade(); showToast('Pro membership active', 'UNLIMITED BUILDS UNLOCKED IN STUDIO'); }); try { const savedPlan = localStorage.getItem('aigap_plan'); if (savedPlan && savedPlan !== 'starter') applyPlanToUI(savedPlan); } catch(e) {} updateSummary(); // ============= SEARCH FILTER ============= const searchInput = document.getElementById('projSearch'); const searchClear = document.getElementById('searchClear'); const searchWrap = document.getElementById('projSearchWrap'); const projCountEl = document.getElementById('projCount'); const noResultsEl = document.getElementById('noResults'); const allProjItems = document.querySelectorAll('.proj-item'); const totalProjects = allProjItems.length; function highlight(text, term) { if (!term) return text; const tNorm = (text).toLowerCase(); const qNorm = (term).toLowerCase(); const idx = tNorm.indexOf(qNorm); if (idx === -1) return text; return text.slice(0, idx) + '' + text.slice(idx, idx + term.length) + '' + text.slice(idx + term.length); } function applySearchFilter() { const q = searchInput.value.trim(); searchWrap.classList.toggle('has-text', q.length > 0); let visibleCount = 0; allProjItems.forEach(item => { const name = item.dataset.name || ''; const match = !q || (name).toLowerCase().includes((q).toLowerCase()); item.hidden = !match; const b = item.querySelector('.proj-info-block b'); if (b) b.innerHTML = match ? highlight(name, q) : name; if (match) visibleCount++; }); if (q) { projCountEl.textContent = visibleCount + ' / ' + totalProjects; projCountEl.classList.add('filtered'); } else { projCountEl.textContent = totalProjects; projCountEl.classList.remove('filtered'); } noResultsEl.hidden = !(q && visibleCount === 0); } searchInput.addEventListener('input', applySearchFilter); searchClear.addEventListener('click', () => { searchInput.value = ''; applySearchFilter(); searchInput.focus(); }); document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && document.activeElement === searchInput) { searchInput.value = ''; applySearchFilter(); searchInput.blur(); } if ((e.metaKey || e.ctrlKey) && e.key === 'n' && !e.shiftKey) { if (!document.querySelector('.upg-overlay.open') && !document.querySelector('.user-dropdown.open')) { e.preventDefault(); document.getElementById('newProject').click(); } } if ((e.metaKey || e.ctrlKey) && e.key === 'k') { if (!document.querySelector('.upg-overlay.open')) { e.preventDefault(); searchInput.focus(); searchInput.select(); } } }); // ============= PREVIEW ENHANCEMENTS ============= // Fullscreen toggle const fpBtn = document.getElementById('fullscreenBtn'); const fpExit = document.getElementById('fpExit'); function toggleFullscreen() { document.body.classList.toggle('fp-active'); } fpBtn.addEventListener('click', toggleFullscreen); fpExit.addEventListener('click', toggleFullscreen); // ESC exits fullscreen, F toggles document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && document.body.classList.contains('fp-active')) { e.preventDefault(); document.body.classList.remove('fp-active'); } // F to toggle fullscreen (when not typing) if ((e.key === 'f' || e.key === 'F') && !['INPUT','TEXTAREA'].includes(e.target.tagName) && !e.metaKey && !e.ctrlKey && !e.altKey) { e.preventDefault(); toggleFullscreen(); } }); // Open in new tab — actually opens iframe content via blob URL document.getElementById('openTabBtn').addEventListener('click', () => { const srcdoc = runtimeFrame.srcdoc; if (!srcdoc) { showToast('Preview not ready yet'); return; } try { const blob = new Blob([srcdoc], { type: 'text/html;charset=utf-8' }); const url = URL.createObjectURL(blob); const win = window.open(url, '_blank'); if (win) { showToast('Opened in new tab', PROJECTS[activeProj].runtimeId); } else { showToast('Pop-up blocked', 'ENABLE FROM BROWSER SETTINGS'); } // Revoke blob URL after a delay to free memory setTimeout(() => URL.revokeObjectURL(url), 60000); } catch (err) { showToast('Could not open', err.message); } }); // URL copy document.getElementById('urlCopy').addEventListener('click', (e) => { const btn = e.currentTarget; const url = 'https://aigap.com/runtime/' + PROJECTS[activeProj].runtimeId; if (navigator.clipboard) { navigator.clipboard.writeText(url).then(() => { btn.textContent = '✓ copied'; btn.classList.add('copied'); setTimeout(() => { btn.textContent = '↗ kopyala'; btn.classList.remove('copied'); }, 2000); }); } else { showToast('URL', url); } }); })();
PLAN UPGRADE

Unlock the Studio

Unlimited builds, advanced models, custom domain, priority queue. 14-day unconditional refund.

Choose payment provider
S

Pay securely with Stripe Checkout

You complete payment on Stripe's secure page. Card details never reach our site — Stripe charges directly. PCI DSS Level 1 certified, trusted by millions of businesses worldwide.

  • Credit/debit card (Visa, Mastercard, Amex)
  • Apple Pay & Google Pay
  • 3D Secure otomatik
  • Includes subscription management
  • Real-time plan sync via webhook
  • Cancel & refund with one click
VISAMASTERCARDAMEX APPLE PAYGOOGLE PAYSEPA
You will be redirected to checkout.stripe.com · you return to this page after payment · cancel anytime, one click back

Payment method encrypted with iyzico

XXXX
🍋

Pay one click with Lemon Squeezy Merchant of Record

Secure payment via Lemon Squeezy. Card details never reach our site — Lemon Squeezy charges directly and handles all VAT/tax responsibility.

  • Automatic tax compliance in 60+ countries
  • 14-day unconditional refund guarantee
  • Stripe / PayPal / Apple Pay / Google Pay
  • PCI compliance Lemon Squeezy'de
  • Includes subscription management portal
  • Real-time plan sync via webhook
You will be redirected to checkout.lemonsqueezy.com · you return to this page after payment
Pro Plan · monthly$9.99
VAT (20%)$1.99
Total$11.96/mo

14-day unconditional refund · secure payment via iyzico · KVKK compliant

Processing your payment

Secure transaction via iyzico · response in seconds.

card details verified
sending to iyzico
3D Secure completed
mapping plan to aigap_user_id
creating memberships record

Pro active

You now have unlimited builds, custom domain, and API access in the Studio.
Invoice sent to your email.

Order#AGP-2026-0012841
PlanPro · monthly
Next renewal1 June 2026
Charged$11.96