# 🎯 MEMORIA COMPLETA DEL PROYECTO - SaaS PageBuilder **Fecha:** 13 Enero 2025 **Hash:** `gkachele-template-system-20250114-v1` **Última actualización:** 14 Enero 2025 - 08:50 ## 🎯 OBJETIVOS ACTUALES (Memorizado) 1. **Template y Menús Profesionales:** - Adaptar al menos un template completo - Sistema de menús dinámicos (header, footer, sidebar) - Múltiples ubicaciones de menú - Estructura modular (header.php, footer.php, sidebar.php) - Sistema de widgets/áreas 2. **Mejorar Landing:** - Diseño más profesional - Mejor UX/UI - Optimización de conversión 3. **Automatización con Gitea:** - Integración Gitea para repos por cliente - Automatización de despliegues - Workflows automáticos - Integración con n8n (futuro - para competir en Argentina) ## ⚠️ REQUISITOS PRINCIPALES (MEMORIZAR) 1. **Sincronización con Hash:** Raspberry y Local deben estar sincronizados con hash 2. **Modularizado:** Código debe estar modularizado 3. **PRIMERO copiar funcionalidad similar:** NO inventar, copiar funcionalidad similar primero en Raspberry, luego ver qué sirve y qué no 4. **Iterar:** Probar → Ver qué sirve → Eliminar lo que no sirve → Mejorar **Ver:** `MEMORIA_SINCRONIZACION.md` para detalles ## 📍 CONEXIÓN RASPBERRY PI **Credenciales SSH:** - **Host:** `komkida.duckdns.org` o `192.168.1.134` - **Puerto:** `2222` - **Usuario:** `pi` - **Password:** `Gdk1983gdk45@` **Comandos de conexión (CON sshpass):** ```bash # Desde WSL - CONECTAR wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134" # COPIAR ARCHIVOS wsl bash -c "sshpass -p 'Gdk1983gdk45@' scp -P 2222 -o StrictHostKeyChecking=no /mnt/c/word/demo/app.py pi@192.168.1.134:/home/pi/gkachele-saas/app.py" # EJECUTAR COMANDO REMOTO wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'comando aqui'" ``` ## 🏗️ ARQUITECTURA ### Stack Tecnológico - **Backend:** Flask (Python 3) - NO Docker, directo - **Base de datos:** SQLite (main.db + cliente-X.db) - **Web Server:** Nginx (reverse proxy) - **Dominio:** `gk-saas.komkida.duckdns.org` - **Puerto Flask:** 5001 - **Puerto Nginx:** 80 ### Estructura en Raspberry Pi ``` /home/pi/gkachele-saas/ ├── app.py # Flask backend principal ├── database/ │ ├── main.db # DB principal (users, sites, requests, media) │ └── sites/ # DBs por cliente │ ├── cliente-1.db │ └── cliente-2.db ├── sites/ # Sitios compilados/publicados ├── themes/ # Templates (como WordPress) │ ├── gimnasio-claro/ │ ├── restaurante-moderno/ │ └── restaurante-elegante/ ├── static/ # CSS, JS, imágenes ├── templates/ # HTML templates │ ├── landing_real.html # Landing GKACHELE™ │ ├── register.html │ ├── login.html │ ├── dashboard.html # Dashboard CLIENTE │ ├── customizer.html # Personalizador WordPress-like │ ├── admin.html # Dashboard PRINCIPAL (tuyo) │ └── client_admin.html # Admin del cliente └── uploads/ # Media subida por clientes ``` ### Estructura en Local (Desarrollo) ``` C:\word\ ├── demo/ # Código del SaaS │ ├── app.py │ ├── database/ │ ├── themes/ │ ├── templates/ │ └── static/ ├── update-raspberry.sh # Script para actualizar Raspberry └── MEMORIA_PROYECTO_COMPLETA.md # Este archivo ``` ## 🔄 FLUJO COMPLETO ``` 1. Cliente → Landing (gk-saas.komkida.duckdns.org) 2. Cliente elige plan + rubro → /register?plan=base&rubro=restaurante 3. Cliente se registra → POST /register ├── Crea usuario en main.db (tabla users) ├── Crea sitio automático (tema según rubro) en main.db (tabla sites) └── Guarda sesión → Redirige a /dashboard (equivalente a wp-admin) 4. Dashboard → Cliente ve SUS sitios 5. Customizer → /customizer/{site_id} (sidebar + preview) 6. Cliente envía → POST /dashboard/submit/{site_id} 7. Admin → /admin (solo user_id=1) aprueba 8. Publicado → /site/{slug} ``` ## 🗄️ BASES DE DATOS ### main.db (SQLite) - TODO EN UNA SOLA BASE DE DATOS (Multi-tenant como WordPress) **✅ Sistema Multi-tenant:** Todos los clientes en una sola base de datos, cada cliente solo ve SUS datos a través de `/dashboard` (equivalente a wp-admin) **Tabla: users** - id, email (UNIQUE), password (hash), plan, rubro, created_at - Todos los usuarios/clientes están aquí **Tabla: sites** - id, user_id (FK), slug (UNIQUE), theme, status (draft/pending/published), content_json, created_at - Todos los sitios, filtrados por user_id (cada cliente solo ve los suyos) **Tabla: requests** - id, site_id (FK), user_id (FK), status (pending/approved/rejected), created_at - Solicitudes de publicación **Tabla: media** - id, user_id (FK), site_id (FK), filename, filepath, file_type, uploaded_at - Archivos subidos por clientes, filtrados por user_id **Tabla: content** - id, user_id (FK), site_id (FK), section, data_json, updated_at - Contenido por sección (futuro uso), filtrado por user_id y site_id **Tabla: settings** - id, user_id (FK), site_id, key, value, created_at, updated_at - Configuraciones (como wp_options en WordPress), filtrado por user_id y site_id **Tabla: menus** - id, user_id (FK), site_id (FK), location (header/footer/sidebar), title, url, order_index, parent_id, created_at - Sistema de menús dinámicos por ubicación, filtrado por user_id y site_id **Tabla: widgets** - id, user_id (FK), site_id (FK), area (sidebar/footer/etc), type, title, content, order_index, created_at, updated_at - Sistema de widgets dinámicos por área, filtrado por user_id y site_id ## 🎨 TEMPLATES (Sistema WordPress-like) ### Templates Disponibles - **gimnasio-claro:** Tema para gimnasios (rojo/negro) - **restaurante-moderno:** Tema moderno (rojo/naranja) - 2 variantes - **restaurante-elegante:** Tema elegante (marrón/dorado) ### Estructura de Template (Sistema Modular GKACHELE™) ``` themes/ ├── _gkachele/ # Sistema base modular (como WordPress) │ ├── header.php # Header con menús dinámicos │ ├── footer.php # Footer con copyright GKACHELE™ │ └── sidebar.php # Sidebar con widgets dinámicos ├── {nombre}/ # Temas específicos │ ├── config.json # Configuración (colores, tipografía, secciones) │ ├── template.html # HTML del template (contenido principal) │ └── style.css # CSS (opcional) ``` **Sistema de Renderizado:** - `render_gkachele_template()` concatena: `header.php` + `template.html` + `sidebar.php` + `footer.php` - Menús y widgets se cargan dinámicamente desde la base de datos - Soporte para múltiples ubicaciones de menú (header, footer, sidebar) - Widgets por área (sidebar, footer, etc.) ### Asignación Automática - **restaurante:** Aleatorio entre `restaurante-moderno` y `restaurante-elegante` - **gimnasio/gimnasios:** `gimnasio-claro` - **Otros:** `default` ## 🔧 CONFIGURACIÓN NGINX **Archivo:** `/etc/nginx/sites-available/gk-saas.komkida.duckdns.org.conf` ```nginx server { listen 80; server_name gk-saas.komkida.duckdns.org; location / { proxy_pass http://localhost:5001; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` **Comandos:** ```bash sudo nginx -t # Verificar configuración sudo systemctl reload nginx # Recargar tail -f /var/log/nginx/gk-saas-error.log # Ver logs ``` ## 🔄 SERVICIO SYSTEMD **Archivo:** `/etc/systemd/system/gkachele-saas.service` ```ini [Unit] Description=GKACHELE SaaS Flask App After=network.target [Service] Type=simple User=pi WorkingDirectory=/home/pi/gkachele-saas Environment="PATH=/usr/bin:/usr/local/bin:/home/pi/.local/bin" ExecStart=/usr/bin/python3 /home/pi/gkachele-saas/app.py Restart=always RestartSec=10 [Install] WantedBy=multi-user.target ``` **Comandos:** ```bash sudo systemctl start gkachele-saas # Iniciar sudo systemctl stop gkachele-saas # Detener sudo systemctl restart gkachele-saas # Reiniciar sudo systemctl status gkachele-saas # Estado journalctl -u gkachele-saas -f # Ver logs ``` ## 🚀 ACTUALIZAR CÓDIGO EN RASPBERRY ### Método Correcto (con sshpass desde WSL): ```bash # 1. Copiar código actualizado wsl bash -c "sshpass -p 'Gdk1983gdk45@' scp -P 2222 -o StrictHostKeyChecking=no /mnt/c/word/demo/app.py pi@192.168.1.134:/home/pi/gkachele-saas/app.py" # 2. Reiniciar app (matar proceso y reiniciar) wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'pkill -f \"python3 app.py\" && cd ~/gkachele-saas && nohup python3 app.py > /tmp/app.log 2>&1 &'" ``` ### Instalar Servicio Systemd (una vez): ```bash # Copiar servicio wsl bash -c "sshpass -p 'Gdk1983gdk45@' scp -P 2222 -o StrictHostKeyChecking=no gkachele-saas.service pi@192.168.1.134:/tmp/" # Instalar servicio wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'sudo mv /tmp/gkachele-saas.service /etc/systemd/system/ && sudo systemctl daemon-reload && sudo systemctl enable gkachele-saas && sudo systemctl start gkachele-saas'" ``` ### Configurar Cron en Raspberry (actualizar automáticamente): ```bash # 1. Crear script de actualización wsl bash -c "sshpass -p 'Gdk1983gdk45@' scp -P 2222 -o StrictHostKeyChecking=no update-app-raspberry.sh pi@192.168.1.134:~/scripts/update-app.sh" # 2. Dar permisos wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'chmod +x ~/scripts/update-app.sh'" # 3. Agregar a crontab (cada hora) - requiere permisos wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'echo \"0 * * * * /home/pi/scripts/update-app.sh\" | crontab -'" # Verificar cron wsl bash -c "sshpass -p 'Gdk1983gdk45@' ssh -p 2222 -o StrictHostKeyChecking=no pi@192.168.1.134 'crontab -l'" ``` **NOTA:** El cron actualiza cada hora. Para actualizar manualmente el código, usar el método de SCP arriba. ## 📋 RUTAS PRINCIPALES ### Públicas - `GET /` - Landing page - `GET /register` - Formulario registro - `POST /register` - Crear usuario (JSON) - `GET /login` - Formulario login - `POST /login` - Iniciar sesión (JSON) - `GET /site/{slug}` - Sitio público publicado ### Cliente (requiere sesión) - `GET /dashboard` - Dashboard del cliente - `GET /customizer/{site_id}` - Personalizador - `POST /api/customizer/save` - Guardar cambios - `GET /api/customizer/preview-frame/{site_id}` - Preview iframe - `POST /dashboard/submit/{site_id}` - Enviar para aprobación - `GET /dashboard/admin` - Admin del cliente (media, config) ### APIs de Menús y Widgets - `GET /api/menus/` - Obtener menús del sitio - `POST /api/menus/` - Guardar/actualizar menús - `GET /api/widgets/` - Obtener widgets del sitio - `POST /api/widgets/` - Guardar/actualizar widgets ### Admin Principal (solo user_id=1) - `GET /admin` - Dashboard principal - `POST /admin/approve/{request_id}` - Aprobar solicitud - `POST /admin/reject/{request_id}` - Rechazar solicitud ## 🔐 SEGURIDAD ### Sesiones - Flask `session` con `secret_key` - Cookie `SESSION_COOKIE_SAMESITE = 'Lax'` - Sesión se guarda después de login exitoso ### Acceso - **Clientes:** Solo ven SUS sitios (filtrado por `user_id` en sesión) - **Admin:** Solo `user_id = 1` puede acceder a `/admin` - **Passwords:** Hash con `werkzeug.security.generate_password_hash` ## 🎯 ESTADO ACTUAL ### ✅ Funcionando - Landing page (GKACHELE™ original) - Registro de clientes → Redirige a `/login` (sin sesión automática) - Login de clientes → Redirige a `/dashboard` - Dashboard del cliente - Customizer básico (sidebar + preview) - Templates: gimnasio-claro, restaurante-moderno, restaurante-elegante - **Sistema modular de templates (_gkachele/header.php, footer.php, sidebar.php)** - **Sistema de menús dinámicos (header, footer, sidebar)** - **Sistema de widgets dinámicos (sidebar, footer, etc.)** - **Función `render_gkachele_template()` para renderizado completo** - **APIs para gestionar menús y widgets** - Base de datos SQLite multi-tenant (main.db con tablas menus y widgets) - Nginx reverse proxy - Systemd service - DuckDNS para dominio remoto - Scripts de gestión: `ver_usuarios.py`, `limpiar_db.py` ### ⚠️ Pendiente - Drag & drop de secciones (SortableJS) - Edición inline (contenteditable) - Gitea para repos por cliente + automatización - Dashboard principal para aprobar solicitudes - Plugins sencillos (colores, tipografía avanzada) - SSL/HTTPS (Let's Encrypt) ### 🎯 PRÓXIMOS OBJETIVOS (PRIORITARIOS) 1. **✅ Template y Menús Profesionales (COMPLETADO):** - ✅ Sistema modular (_gkachele/header.php, footer.php, sidebar.php) - ✅ Sistema de menús dinámicos (header, footer, sidebar) - ✅ Múltiples ubicaciones de menú - ✅ Sistema de widgets/áreas - ⚠️ **PENDIENTE:** UI completa para gestionar menús desde customizer (actualmente solo placeholder) 2. **Mejorar Landing:** - Diseño más profesional - Mejor UX/UI - Optimización de conversión 3. **Automatización con Gitea:** - Integración Gitea para repos por cliente - Automatización de despliegues - Workflows automáticos - Integración con n8n (futuro) ## 📦 DEPENDENCIAS **Python:** - Flask - Werkzeug (password hashing) - SQLite3 (built-in) **Instalación:** ```bash pip3 install Flask Werkzeug ``` ## 🌐 DUCKDNS **Dominios:** - **komkida.duckdns.org:** Token `9c5cff88-b6d7-4704-9b10-4a69afdff797` - **gkachele.duckdns.org:** Token `578331b3-ad7b-4154-835d-e496465257b0` **Actualizar IP:** ```bash python3 update-komkida-duckdns.py ``` ## 🚀 MIGRACIÓN A VPS **Pasos:** 1. Copiar `/home/pi/gkachele-saas/` completo 2. Instalar Python3, Nginx en VPS 3. Copiar configuración Nginx 4. Copiar servicio systemd 5. Cambiar dominio (DuckDNS o dominio real) 6. Configurar SSL (Let's Encrypt) **Ventajas:** - ✅ Mismo código (sin cambios) - ✅ Misma estructura - ✅ Más recursos - ✅ Mejor rendimiento ## 📝 NOTAS IMPORTANTES - **NO usar Docker:** Todo corre directamente (Python + Nginx) - **NO usar GitHub:** Todo es independiente en Raspberry - **SQLite es suficiente:** Para SaaS pequeño, no necesita MySQL - **Raspberry Pi 3:** Recursos limitados, pero suficiente para desarrollo - **VPS recomendado:** Para producción con muchos clientes ## 📦 BACKUP Y VERSIONADO **Hash Actual:** `gkachele-template-system-20250114-v1` **Estado Verificado:** - ✅ Templates _gkachele en Raspberry: header.php, footer.php, sidebar.php - ✅ Función render_gkachele_template en app.py - ✅ Tablas menus y widgets en main.db - ✅ Servicio gkachele-saas activo - ✅ Flujo de registro: Registro → Login → Dashboard → Customizer **Scripts de Gestión:** - `ver_usuarios.py` - Ver usuarios y sitios registrados - `limpiar_db.py` - Limpiar base de datos (con confirmación) - `verificar_raspberry.sh` - Verificar estado en Raspberry --- **Última actualización:** 14 Enero 2025 - 08:50