import os import zipfile from textwrap import dedent
base_dir = "/mnt/data/mecanica-real" assets_dir = os.path.join(base_dir, "assets") os.makedirs(assets_dir, exist_ok=True)
index_html = dedent("""
<title>Mecánica Real | Taller mecánico en Navarra</title> <script defer src="script.js"></script> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "AutoRepair", "name": "Mecánica Real", "image": "https://tudominio.com/assets/og-cover.jpg", "telephone": "+34 747404236", "address": { "@type": "PostalAddress", "addressLocality": "Navarra", "addressCountry": "ES" }, "url": "https://tudominio.com", "openingHours": "Mo-Fr 09:00-14:00,16:00-19:00", "priceRange": "€€" } </script>Mantenimiento rápido y honesto en Navarra: revisiones, diagnosis, frenos y neumáticos. Pide cita y lo tendrás listo en tiempo récord.
- ✔ Garantía en mano de obra
- ✔ Presupuesto previo
- ✔ Repuestos de calidad
Cambio de aceite y filtros, revisión general y puesta a punto para viajar seguro.
Lectura de errores OBD-II y reparación de averías eléctricas y sensores.
Pastillas, discos y líquido de frenos. Seguridad y rendimiento al máximo.
Montaje, equilibrado y alineado. Las mejores marcas a buen precio.
Comprobamos tu vehículo para que pase la ITV a la primera.
Carga de A/A, diagnosis de fugas y mantenimiento del sistema.
Rellena el formulario y te llamamos. También puedes escribir por WhatsApp o llamar al 747 404 236.
Al enviar aceptas nuestra política de privacidad.
Navarra, España
Tel: 747 404 236
styles_css = dedent(""" /* Paleta: naranja principal, negro, blanco, acento rojo */ :root{ --orange:#ff5a1f; --black:#0f1115; --white:#ffffff; --red:#e11d48; --gray:#f5f6f8; }
*{box-sizing:border-box} html,body{margin:0;padding:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Inter,Arial,sans-serif;color:var(--black);background:var(--white)}
.container{max-width:1100px;margin:0 auto;padding:0 16px} .topbar{position:sticky;top:0;background:rgba(255,255,255,.9);backdrop-filter:saturate(1.2) blur(6px);border-bottom:1px solid #eee;z-index:50} .bar{display:flex;align-items:center;justify-content:space-between;height:64px} .brand{display:flex;align-items:center;gap:10px;font-weight:800;text-decoration:none;color:var(--black)} .logo{height:32px;width:32px} .logo.small{height:24px;width:24px} .nav{display:flex;gap:18px;align-items:center} .nav a{color:var(--black);text-decoration:none;font-weight:600} .nav .cta{background:var(--red);color:var(--white);padding:10px 14px;border-radius:999px} .menu{display:none;border:0;background:transparent;font-size:22px}
.hero{background:linear-gradient(180deg,#fff, #fff2ec 60%, #fff);padding:48px 0 32px;border-bottom:1px solid #ffe3d8} .hero-wrap{display:grid;grid-template-columns:1.1fr .9fr;gap:28px;align-items:center} .hero-text h1{font-size:42px;line-height:1.05;margin:0 0 12px} .hero-text p{font-size:18px;color:#333;margin:0 0 18px} .actions{display:flex;gap:12px;margin-bottom:10px} .btn{display:inline-block;border:2px solid var(--black);padding:12px 16px;border-radius:12px;text-decoration:none;font-weight:700} .btn.primary{background:var(--orange);border-color:var(--orange);color:#111} .btn.ghost{background:transparent} .badges{display:flex;gap:14px;flex-wrap:wrap;padding:0;margin:10px 0 0;list-style:none} .hero-media img{width:100%;height:auto;border-radius:16px;box-shadow:0 10px 30px rgba(255,90,31,.25)}
.section{padding:56px 0} .section.alt{background:var(--gray)} h2{font-size:30px;margin:0 0 20px} .grid.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:18px} .card{background:#fff;border:1px solid #eee;border-radius:14px;padding:18px;box-shadow:0 8px 18px rgba(0,0,0,.03)} .card h3{margin:0 0 8px}
.why{display:grid;grid-template-columns:1.1fr .9fr;gap:22px;align-items:center} .why img{width:100%;border-radius:14px;border:1px solid #eee} .checks{padding-left:0;list-style:none;display:grid;gap:6px}
.grid.reviews{display:grid;grid-template-columns:repeat(3,1fr);gap:18px} blockquote{background:#fff;border-left:6px solid var(--orange);margin:0;padding:14px 16px;border-radius:8px;border:1px solid #eee;box-shadow:0 8px 18px rgba(0,0,0,.03)} blockquote footer{margin-top:8px;color:#555}
.form{display:grid;gap:12px;background:#fff;border:1px solid #eee;border-radius:14px;padding:18px} .form .row{display:grid;grid-template-columns:1fr 1fr;gap:12px} .form label{display:grid;gap:6px;font-weight:600} input,select,textarea{padding:12px 10px;border-radius:10px;border:1px solid #ddd;font:inherit} .form-note{font-size:12px;color:#555} .contact-extras{margin-top:12px;display:flex;gap:10px;flex-wrap:wrap} .whatsapp{display:inline-block;background:#25D366;color:#fff;text-decoration:none;padding:10px 12px;border-radius:10px}
.footer{background:var(--black);color:#cbd5e1} .foot{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;padding:24px 0} .footer a{color:#e2e8f0} .footer .brand{color:#e2e8f0} .legal{text-align:center;border-top:1px solid rgba(255,255,255,.1);padding:12px 0;color:#94a3b8;font-size:14px}
@media (max-width: 900px){ .hero-wrap{grid-template-columns:1fr} .grid.cards{grid-template-columns:1fr 1fr} .grid.reviews{grid-template-columns:1fr} .why{grid-template-columns:1fr} .nav{display:none;position:absolute;right:16px;top:64px;background:#fff;border:1px solid #eee;border-radius:12px;flex-direction:column;padding:12px} .menu{display:block} } """)
script_js = dedent(""" document.getElementById('year').textContent = new Date().getFullYear();
const menuBtn = document.getElementById('menuBtn'); const nav = document.getElementById('nav'); menuBtn.addEventListener('click', () => { if (nav.style.display === 'flex') { nav.style.display = 'none'; } else { nav.style.display = 'flex'; } });
// Cliente-ligero para Formspree (muestra alertas) const form = document.getElementById('contactForm'); if (form) { form.addEventListener('submit', async (e) => { e.preventDefault(); const data = new FormData(form); try { const r = await fetch(form.action, { method:'POST', body:data, headers:{ 'Accept': 'application/json' } }); if (r.ok) { alert('¡Gracias! Te contactamos en breve.'); form.reset(); } else { alert('No se pudo enviar. Prueba de nuevo o llámanos.'); } } catch(err){ alert('Error de conexión. Inténtalo más tarde.'); } }); } """)
logo_svg = dedent(""" MR """)
from PIL import Image, ImageDraw, ImageFont
def placeholder(path, text, color=(255, 90, 31)): img = Image.new("RGB", (1200, 800), color=color) d = ImageDraw.Draw(img) # Basic text placement try: font = ImageFont.truetype("DejaVuSans-Bold.ttf", 56) except: font = ImageFont.load_default() w, h = d.textsize(text, font=font) d.rectangle([(0,0),(1199,60)], fill=(15,17,21)) d.text(((1200-w)//2, (800-h)//2), text, fill=(255,255,255), font=font) img.save(path, "JPEG", quality=85)
placeholder(os.path.join(assets_dir, "hero-car.jpg"), "Mecánica Real - Tu coche a punto", (255, 234, 226)) placeholder(os.path.join(assets_dir, "workbench.jpg"), "Banco de trabajo - Mecánica Real", (245, 246, 248)) placeholder(os.path.join(assets_dir, "og-cover.jpg"), "Mecánica Real", (255, 90, 31))
with open(os.path.join(assets_dir, "favicon.svg"), "w", encoding="utf-8") as f: f.write("""""")
with open(os.path.join(base_dir, "index.html"), "w", encoding="utf-8") as f: f.write(index_html)
with open(os.path.join(base_dir, "styles.css"), "w", encoding="utf-8") as f: f.write(styles_css)
with open(os.path.join(base_dir, "script.js"), "w", encoding="utf-8") as f: f.write(script_js)
with open(os.path.join(assets_dir, "logo.svg"), "w", encoding="utf-8") as f: f.write(logo_svg)
readme_md = dedent("""
Colores: naranja (#ff5a1f), negro (#0f1115), blanco (#ffffff), acento rojo (#e11d48)
Teléfono: 747 404 236
index.html
styles.css
script.js
assets/
(imágenes, logo, favicon)
- Crea una cuenta gratuita en Formspree.
- Crea un formulario y copia el ID del endpoint (formato
https://formspree.io/f/xxxxxxx
). - Abre
index.html
y reemplaza en el<form>
el atributoaction="https://formspree.io/f/XXXXXXXX"
por tu URL real. - Opcional: en Formspree activa reCAPTCHA/anti-spam.
- Entra en tu panel de Nominalia > tu hosting.
- Abre Gestor de Archivos.
- En el directorio
public_html
(ohttpdocs
), pulsa Subir y selecciona el archivomecanica-real-web.zip
. - Una vez subido, selecciónalo y pulsa Extraer. Asegúrate de que
index.html
queda directamente dentro depublic_html
. - Visita tu dominio para comprobar.
- En Nominalia, busca los datos FTP: servidor, usuario, contraseña.
- Abre FileZilla y conecta (Puerto: 21 o 22 según configuración).
- En el panel derecho entra a
public_html
. - Arrastra todo el contenido de la carpeta (no la carpeta en sí) al panel derecho.
- Cuando termine, abre tu dominio en el navegador.
- Cambia
https://tudominio.com
yinfo@tudominio.com
por tus datos. - Cambia imágenes en
assets/
por fotos reales del taller. - Edita textos en
index.html
(servicios, opiniones, horario). - Si tienes dirección exacta, añádela en el JSON-LD (schema.org).
¡Listo! """)
with open(os.path.join(base_dir, "README.txt"), "w", encoding="utf-8") as f: f.write(readme_md)
zip_path = "/mnt/data/mecanica-real-web.zip" with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as z: for root, _, files in os.walk(base_dir): for file in files: full_path = os.path.join(root, file) arcname = os.path.relpath(full_path, base_dir) z.write(full_path, arcname)
zip_path