Spaces:
Running
Running
Commit ·
72d7bb2
1
Parent(s): 8da132a
Interfaz a pantalla completa y clonado exacto
Browse files- app.py +12 -19
- index.html +28 -39
app.py
CHANGED
|
@@ -15,38 +15,32 @@ class GenerateRequest(BaseModel):
|
|
| 15 |
@app.post("/api/generate")
|
| 16 |
async def generate_site(data: GenerateRequest):
|
| 17 |
try:
|
| 18 |
-
|
| 19 |
-
r = requests.get(data.url, headers={'User-Agent': 'Mozilla/5.0'}, timeout=10)
|
| 20 |
soup = BeautifulSoup(r.text, 'html.parser')
|
| 21 |
-
texto_original = soup.get_text()[:
|
| 22 |
|
| 23 |
-
# 2. La IA actúa como Diseñador Web Pro
|
| 24 |
prompt = (
|
| 25 |
-
f"Actúa como un
|
| 26 |
-
f"
|
| 27 |
-
f"REGLAS
|
| 28 |
-
f"1.
|
| 29 |
-
f"2.
|
| 30 |
-
f"3.
|
| 31 |
-
f"4.
|
| 32 |
-
f"5.
|
| 33 |
-
f"IMPORTANTE: Devuelve SOLO el código HTML con Tailwind (usando el CDN de Tailwind). No des explicaciones."
|
| 34 |
)
|
| 35 |
|
| 36 |
payload = {
|
| 37 |
"model": "llama-3.3-70b-versatile",
|
| 38 |
-
"messages": [{"role": "system", "content": "Eres un
|
| 39 |
-
{"role": "user", "content": prompt}]
|
| 40 |
-
"max_tokens": 4000
|
| 41 |
}
|
| 42 |
|
| 43 |
headers = {"Authorization": f"Bearer {GROQ_API_KEY}"}
|
| 44 |
r_ia = requests.post("https://api.groq.com/openai/v1/chat/completions", json=payload, headers=headers)
|
| 45 |
html_generado = r_ia.json()["choices"][0]["message"]["content"]
|
| 46 |
|
| 47 |
-
# Limpiar posibles etiquetas de markdown que ponga la IA
|
| 48 |
html_final = re.sub(r'```html|```', '', html_generado).strip()
|
| 49 |
-
|
| 50 |
return {"status": "success", "html": html_final}
|
| 51 |
except Exception as e:
|
| 52 |
return JSONResponse({"status": "error", "detail": str(e)}, status_code=400)
|
|
@@ -54,4 +48,3 @@ async def generate_site(data: GenerateRequest):
|
|
| 54 |
@app.get("/", response_class=HTMLResponse)
|
| 55 |
async def index():
|
| 56 |
with open("index.html", "r", encoding="utf-8") as f: return f.read()
|
| 57 |
-
|
|
|
|
| 15 |
@app.post("/api/generate")
|
| 16 |
async def generate_site(data: GenerateRequest):
|
| 17 |
try:
|
| 18 |
+
r = requests.get(data.url, headers={'User-Agent': 'Mozilla/5.0'}, timeout=12)
|
|
|
|
| 19 |
soup = BeautifulSoup(r.text, 'html.parser')
|
| 20 |
+
texto_original = soup.get_text()[:4000]
|
| 21 |
|
|
|
|
| 22 |
prompt = (
|
| 23 |
+
f"Actúa como un clonador de webs experto en HTML y Tailwind CSS. \n"
|
| 24 |
+
f"Tu objetivo es crear una página que tenga la MISMA ESTRUCTURA Y SECCIONES que esta información original: {texto_original}. \n"
|
| 25 |
+
f"REGLAS ESTRICTAS:\n"
|
| 26 |
+
f"1. Sustituye el nombre del negocio original por: {data.nuevo_nombre}.\n"
|
| 27 |
+
f"2. Cambia todos los colores principales para usar la paleta: {data.color_primario} (ej: bg-{data.color_primario}-600, text-{data.color_primario}-500).\n"
|
| 28 |
+
f"3. Mantén los mismos servicios, textos y el mismo enfoque de ventas que la web original, no te inventes cosas nuevas.\n"
|
| 29 |
+
f"4. Diseño profesional, a pantalla completa.\n"
|
| 30 |
+
f"5. Devuelve SOLO el código HTML completo con Tailwind embebido, sin Markdown, sin explicaciones previas ni posteriores."
|
|
|
|
| 31 |
)
|
| 32 |
|
| 33 |
payload = {
|
| 34 |
"model": "llama-3.3-70b-versatile",
|
| 35 |
+
"messages": [{"role": "system", "content": "Eres un experto en clonación y diseño web."},
|
| 36 |
+
{"role": "user", "content": prompt}]
|
|
|
|
| 37 |
}
|
| 38 |
|
| 39 |
headers = {"Authorization": f"Bearer {GROQ_API_KEY}"}
|
| 40 |
r_ia = requests.post("https://api.groq.com/openai/v1/chat/completions", json=payload, headers=headers)
|
| 41 |
html_generado = r_ia.json()["choices"][0]["message"]["content"]
|
| 42 |
|
|
|
|
| 43 |
html_final = re.sub(r'```html|```', '', html_generado).strip()
|
|
|
|
| 44 |
return {"status": "success", "html": html_final}
|
| 45 |
except Exception as e:
|
| 46 |
return JSONResponse({"status": "error", "detail": str(e)}, status_code=400)
|
|
|
|
| 48 |
@app.get("/", response_class=HTMLResponse)
|
| 49 |
async def index():
|
| 50 |
with open("index.html", "r", encoding="utf-8") as f: return f.read()
|
|
|
index.html
CHANGED
|
@@ -5,47 +5,32 @@
|
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>IA Web Re-Designer</title>
|
| 7 |
<script src="https://cdn.tailwindcss.com"></script>
|
|
|
|
| 8 |
</head>
|
| 9 |
-
<body class="bg-slate-
|
| 10 |
|
| 11 |
-
<div class="
|
| 12 |
-
<div class="text-center
|
| 13 |
-
<
|
| 14 |
-
<
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
<
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
<div>
|
| 25 |
-
<label class="block text-xs font-bold text-slate-500 uppercase mb-2">Nuevo Nombre</label>
|
| 26 |
-
<input type="text" id="nombre" placeholder="Mi Nueva Clínica" class="w-full p-3 rounded-xl bg-slate-900 border border-slate-600 outline-none focus:border-blue-500">
|
| 27 |
-
</div>
|
| 28 |
-
<div>
|
| 29 |
-
<label class="block text-xs font-bold text-slate-500 uppercase mb-2">Color (Tailwind: blue, red, emerald...)</label>
|
| 30 |
-
<input type="text" id="color" placeholder="blue" class="w-full p-3 rounded-xl bg-slate-900 border border-slate-600 outline-none focus:border-blue-500">
|
| 31 |
-
</div>
|
| 32 |
-
<button onclick="generarWeb()" id="btn" class="w-full bg-blue-600 p-4 rounded-2xl font-bold hover:bg-blue-500 transition-all shadow-lg shadow-blue-900/20">
|
| 33 |
-
REDISEÑAR AHORA
|
| 34 |
-
</button>
|
| 35 |
-
</div>
|
| 36 |
-
</div>
|
| 37 |
-
|
| 38 |
-
<div class="md:col-span-2">
|
| 39 |
-
<div class="bg-white rounded-3xl overflow-hidden shadow-2xl h-[600px] border-4 border-slate-800">
|
| 40 |
-
<iframe id="preview" class="w-full h-full" srcdoc="<div style='display:flex; height:100%; align-items:center; justify-content:center; font-family:sans-serif; color:#94a3b8'>La nueva web aparecerá aquí...</div>"></iframe>
|
| 41 |
-
</div>
|
| 42 |
-
</div>
|
| 43 |
</div>
|
| 44 |
</div>
|
| 45 |
|
|
|
|
|
|
|
| 46 |
<script>
|
| 47 |
async function generarWeb() {
|
| 48 |
const btn = document.getElementById('btn');
|
|
|
|
| 49 |
const preview = document.getElementById('preview');
|
| 50 |
|
| 51 |
const data = {
|
|
@@ -54,9 +39,9 @@
|
|
| 54 |
color_primario: document.getElementById('color').value
|
| 55 |
};
|
| 56 |
|
| 57 |
-
if(!data.url || !data.nuevo_nombre) return alert("
|
| 58 |
|
| 59 |
-
btn.innerHTML = "
|
| 60 |
btn.disabled = true;
|
| 61 |
|
| 62 |
try {
|
|
@@ -68,14 +53,18 @@
|
|
| 68 |
const result = await res.json();
|
| 69 |
|
| 70 |
if(result.status === "success") {
|
|
|
|
|
|
|
|
|
|
| 71 |
preview.srcdoc = result.html;
|
| 72 |
} else {
|
| 73 |
-
alert("Error
|
|
|
|
|
|
|
| 74 |
}
|
| 75 |
} catch(e) {
|
| 76 |
-
alert("Error de conexión");
|
| 77 |
-
|
| 78 |
-
btn.innerHTML = "REDISEÑAR AHORA";
|
| 79 |
btn.disabled = false;
|
| 80 |
}
|
| 81 |
}
|
|
|
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>IA Web Re-Designer</title>
|
| 7 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
+
<style> body { overflow: hidden; } </style>
|
| 9 |
</head>
|
| 10 |
+
<body class="bg-slate-50">
|
| 11 |
|
| 12 |
+
<div id="setup-panel" class="absolute inset-0 flex items-center justify-center z-50 p-4">
|
| 13 |
+
<div class="bg-white p-8 md:p-12 rounded-[40px] shadow-2xl shadow-blue-100 w-full max-w-md text-center border border-slate-100">
|
| 14 |
+
<div class="w-16 h-16 bg-emerald-500 rounded-2xl mx-auto mb-6 flex items-center justify-center text-white text-3xl font-bold shadow-lg shadow-emerald-200">🎨</div>
|
| 15 |
+
<h1 class="text-3xl font-bold text-slate-900 mb-2">Web Re-Designer</h1>
|
| 16 |
+
<p class="text-slate-500 mb-8 font-medium">Clona y cambia de color cualquier web</p>
|
| 17 |
+
|
| 18 |
+
<input type="text" id="url" placeholder="URL original (Ej: https://...)" class="w-full p-4 rounded-2xl bg-slate-50 border border-slate-200 mb-4 outline-none focus:ring-2 focus:ring-emerald-500">
|
| 19 |
+
<input type="text" id="nombre" placeholder="Nuevo Nombre del Negocio" class="w-full p-4 rounded-2xl bg-slate-50 border border-slate-200 mb-4 outline-none focus:ring-2 focus:ring-emerald-500">
|
| 20 |
+
<input type="text" id="color" placeholder="Color (blue, red, emerald, purple...)" class="w-full p-4 rounded-2xl bg-slate-50 border border-slate-200 mb-6 outline-none focus:ring-2 focus:ring-emerald-500">
|
| 21 |
+
|
| 22 |
+
<button onclick="generarWeb()" id="btn" class="w-full bg-emerald-500 text-white py-4 rounded-2xl font-bold shadow-xl shadow-emerald-200 hover:bg-emerald-600 transition-all">
|
| 23 |
+
CLONAR Y REDISEÑAR
|
| 24 |
+
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
</div>
|
| 26 |
</div>
|
| 27 |
|
| 28 |
+
<iframe id="preview" class="w-full h-screen border-none hidden absolute top-0 left-0 z-10"></iframe>
|
| 29 |
+
|
| 30 |
<script>
|
| 31 |
async function generarWeb() {
|
| 32 |
const btn = document.getElementById('btn');
|
| 33 |
+
const panel = document.getElementById('setup-panel');
|
| 34 |
const preview = document.getElementById('preview');
|
| 35 |
|
| 36 |
const data = {
|
|
|
|
| 39 |
color_primario: document.getElementById('color').value
|
| 40 |
};
|
| 41 |
|
| 42 |
+
if(!data.url || !data.nuevo_nombre) return alert("Faltan datos por rellenar");
|
| 43 |
|
| 44 |
+
btn.innerHTML = "⏳ Escaneando y programando...";
|
| 45 |
btn.disabled = true;
|
| 46 |
|
| 47 |
try {
|
|
|
|
| 53 |
const result = await res.json();
|
| 54 |
|
| 55 |
if(result.status === "success") {
|
| 56 |
+
// Ocultar panel y mostrar web a pantalla completa
|
| 57 |
+
panel.style.display = 'none';
|
| 58 |
+
preview.style.display = 'block';
|
| 59 |
preview.srcdoc = result.html;
|
| 60 |
} else {
|
| 61 |
+
alert("Error al clonar la web.");
|
| 62 |
+
btn.innerHTML = "CLONAR Y REDISEÑAR";
|
| 63 |
+
btn.disabled = false;
|
| 64 |
}
|
| 65 |
} catch(e) {
|
| 66 |
+
alert("Error de conexión con la IA.");
|
| 67 |
+
btn.innerHTML = "CLONAR Y REDISEÑAR";
|
|
|
|
| 68 |
btn.disabled = false;
|
| 69 |
}
|
| 70 |
}
|