const { useState, useEffect, useRef } = React; // ========================================================= // DATA // ========================================================= const SERVICIOS = [ { num: "01", name: "Diseño web", desc: "Webs corporativas, landings y portfolios diseñados a medida. Cada pixel cuenta una parte de tu historia.", href: "#contacto" }, { num: "02", name: "Tiendas online", desc: "E-commerce listos para vender desde el día uno. Shopify, WooCommerce o lo que mejor encaje contigo.", href: "#contacto" }, { num: "03", name: "Mantenimiento", desc: "Actualizaciones, copias de seguridad, mejoras de velocidad y soporte continuo. Desde 29 €/mes — ver packs completos.", href: "Mantenimiento.html" }, { num: "04", name: "Marca personal", desc: "Web + identidad para autónomos y profesionales que quieren destacar y convertir visitas en clientes.", href: "#contacto" }, { num: "05", name: "SEO & contenido", desc: "Posicionamiento orgánico, redacción con IA y estrategia de contenidos para crecer mes a mes.", href: "#contacto" }, { num: "06", name: "Automatizaciones", desc: "Formularios, CRMs, chatbots y flujos que ahorran horas a tu equipo cada semana.", href: "#contacto" }, ]; const PROCESO = [ { step: "01", title: "Briefing", desc: "30 minutos para entender tu negocio, tu cliente y dónde quieres estar en 12 meses.", time: "Día 1" }, { step: "02", title: "Estrategia + diseño", desc: "Arquitectura, copys con IA y maqueta visual. Validamos antes de tocar código.", time: "Días 2 – 5" }, { step: "03", title: "Construcción", desc: "Desarrollamos la web con herramientas asistidas por IA. Rápido, sin perder el detalle.", time: "Días 6 – 12" }, { step: "04", title: "Lanzamiento", desc: "Test en dispositivos reales, SEO técnico, analítica, formación y al aire.", time: "Día 14" }, ]; const PRECIOS = [ { name: "Esencial", desc: "Para empezar con una presencia profesional sin complicarte.", price: "490", period: "pago único", features: [ "Web de 1 página (landing)", "Diseño 100 % a medida", "Optimizada para móvil", "Formulario de contacto", "Entrega en 7 días", ], cta: "Empezar", featured: false, }, { name: "Negocio", desc: "El paquete favorito de autónomos y pequeños negocios.", price: "990", period: "pago único", features: [ "Hasta 5 páginas", "Diseño + copy con IA", "SEO técnico básico", "Integración WhatsApp y email", "Panel para editar tu mismo", "Entrega en 14 días", ], cta: "Quiero esta", featured: true, tag: "Más elegida", }, { name: "Tienda", desc: "E-commerce listo para vender, con todo conectado.", price: "1.490", period: "pago único", features: [ "Tienda online completa", "Pasarela de pago y envíos", "Hasta 50 productos cargados", "Email marketing conectado", "Formación 1:1 incluida", "Entrega en 21 días", ], cta: "Vender online", featured: false, }, ]; const TESTIMONIOS = [ { quote: "Tenía la idea desde hacía un año y en menos de dos semanas estaba lanzando mi web. Oumaima entendió el tono que buscaba a la primera.", name: "Laura Méndez", role: "Fundadora · Casa Aurora", initials: "LM", }, { quote: "Pasamos de una web hecha en una plantilla a algo que de verdad parece nuestro. Y lo notamos en las reservas del primer mes.", name: "Daniel Roca", role: "Co-fundador · Cabaña Norte", initials: "DR", }, { quote: "Lo mejor no es solo cómo quedó, sino lo rápido y claro que fue todo el proceso. Nada de meses esperando revisiones.", name: "Mireia Solé", role: "Coach · Mireia Solé Studio", initials: "MS", }, { quote: "Cada mes me manda un pequeño informe de la web y mejoras. Es como tener un equipo técnico pero sin la factura de un equipo técnico.", name: "Carlos Iniesta", role: "Asesor fiscal · Iniesta & Co.", initials: "CI", }, ]; const CLIENTES = [ { name: "Casa Aurora", mark: true }, { name: "Cabaña Norte", mark: false }, { name: "Iniesta&Co", mark: true }, { name: "Mireia Studio", mark: false }, { name: "Bona Fruita", mark: true }, ]; const FAQS = [ { q: "¿En cuánto tiempo entregáis una web?", a: "Una landing sencilla en 7 días, una web de negocio en 14 y una tienda online en 21. Trabajamos con sprints semanales para que siempre sepas qué se está haciendo y cuándo lo verás." }, { q: "¿Para qué usáis la inteligencia artificial?", a: "Para acelerar lo aburrido: primeras versiones de copy, organización de contenido, generación de imágenes de apoyo y QA. El diseño, la estrategia y la conversación contigo siempre las hago yo." }, { q: "¿Puedo editar la web yo después?", a: "Sí. Te dejo un panel sencillo (sin código) donde puedes cambiar textos, imágenes, precios o añadir entradas al blog. Si lo prefieres, lo hago yo dentro del plan de mantenimiento." }, { q: "¿Qué incluye el mantenimiento?", a: "Actualizaciones, copias de seguridad, monitoreo de seguridad, mejoras de velocidad y hasta 2 horas mensuales de cambios pequeños. Plan desde 49 €/mes." }, { q: "¿Trabajáis con dominios y hosting?", a: "Sí, lo gestiono todo. Si ya tienes dominio lo migramos sin que pierdas visitas ni emails. Si no lo tienes, te recomiendo opciones y lo configuramos juntos." }, { q: "¿Y si no me gusta el diseño?", a: "Antes de tocar código validamos una maqueta visual. Si algo no encaja lo ajustamos sin coste hasta que sea exactamente lo que querías." }, ]; const POSTS = [ { tag: "Guía", read: "6 min", title: "Cómo escribir el copy de tu home sin morir en el intento", excerpt: "La fórmula que uso con todos mis clientes para que su web hable claro desde el primer scroll." }, { tag: "IA", read: "4 min", title: "5 prompts para sacar partido a la IA en tu negocio local", excerpt: "Sin promesas mágicas. Tareas concretas que puedes automatizar esta misma semana." }, { tag: "Caso", read: "8 min", title: "Caso Casa Aurora: de 0 reservas a llenar todos los fines de semana", excerpt: "Qué cambiamos en su web y por qué los resultados se vieron en menos de 30 días." }, ]; // ========================================================= // CURSOR // ========================================================= function useCursor(enabled) { useEffect(() => { const cursor = document.getElementById("weblume-cursor"); const dot = document.getElementById("weblume-cursor-dot"); if (!cursor || !dot) return; let mx = window.innerWidth / 2, my = window.innerHeight / 2; let cx = mx, cy = my; let raf; const onMove = (e) => { mx = e.clientX; my = e.clientY; dot.style.transform = `translate(${mx}px, ${my}px) translate(-50%, -50%)`; }; const tick = () => { cx += (mx - cx) * 0.18; cy += (my - cy) * 0.18; cursor.style.transform = `translate(${cx}px, ${cy}px) translate(-50%, -50%)`; raf = requestAnimationFrame(tick); }; const onOver = (e) => { const t = e.target.closest("a, button, .servicio, .testi, .post, .plan, .faq-item, input, textarea, label, .chip"); if (t) cursor.classList.add("hover"); else cursor.classList.remove("hover"); }; document.addEventListener("mousemove", onMove); document.addEventListener("mouseover", onOver); raf = requestAnimationFrame(tick); return () => { document.removeEventListener("mousemove", onMove); document.removeEventListener("mouseover", onOver); cancelAnimationFrame(raf); }; }, []); useEffect(() => { document.body.classList.toggle("no-custom-cursor", !enabled); }, [enabled]); } // ========================================================= // SCROLL REVEAL // ========================================================= function useReveal() { useEffect(() => { const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } }); }, { threshold: 0.12 }); document.querySelectorAll(".reveal").forEach(el => io.observe(el)); return () => io.disconnect(); }, []); } // ========================================================= // NAV // ========================================================= function Nav() { const [scrolled, setScrolled] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 40); onScroll(); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); return ( ); } // ========================================================= // HERO // ========================================================= function Hero() { const today = new Date(); const fecha = today.toLocaleDateString("es-ES", { year: "numeric", month: "long", day: "2-digit" }); return (
EST. 2024 — ESPAÑA / REMOTO ÍNDICE — 01 / 06 {fecha.toUpperCase()}

Webs con luz,
construidas con IA,
listas en meses días.

Ayudamos a autónomos, pequeños negocios y marcas personales a tener una web profesional y lista para captar clientes en cuestión de días, no meses.

Quiero mi web Ver precios
); } function Arrow() { return ( ); } // ========================================================= // MARQUEE // ========================================================= function Marquee() { const items = ["Diseño web", "Tiendas online", "Mantenimiento", "Marca personal", "SEO con IA", "Automatizaciones"]; const row = items.concat(items); return (
{row.map((it, i) => {it})}
); } // ========================================================= // SECTION HEAD // ========================================================= function SectionHead({ num, eyebrow, children }) { return (
{num}
{eyebrow}

{children}

); } // ========================================================= // SERVICIOS // ========================================================= function Servicios() { return (
Todo lo que tu web necesita, en un mismo sitio.
{SERVICIOS.map(s => (
{s.num}
{s.name}
{s.desc}
))}
); } // ========================================================= // PROCESO // ========================================================= function Proceso() { return (
De la idea al lanzamiento, en 14 días.
{PROCESO.map(p => (
PASO {p.step}
{p.title}
{p.desc}
{p.time}
))}
); } // ========================================================= // PRECIOS // ========================================================= function Precios() { return (
Paquetes claros. Sin sorpresas.
{PRECIOS.map(p => (
{p.tag ? {p.tag} : {p.featured ? "—" : "Esencial"}}
{p.name}
{p.desc}
{p.price}
{p.period}
    {p.features.map((f, i) => (
  • {f}
  • ))}
{p.cta} →
))}

¿Necesitas algo más a medida? Habla conmigo y lo ajustamos.

); } // ========================================================= // TESTIMONIOS // ========================================================= function Testimonios() { return (
Negocios reales que ya brillan online.
{TESTIMONIOS.map((t, i) => (
{t.quote}
{t.initials}
{t.name}
{t.role}
))}
{CLIENTES.map((c, i) => (
{c.mark ? : null} {c.name}
))}
); } // ========================================================= // QUIÉNES SOMOS // ========================================================= function Quienes() { return (
Detrás de Weblume hay una persona, no una agencia gigante.
Ilustración de Oumaima Erraji, fundadora de Weblume FUNDADORA

Soy Oumaima Erraji, emprendedora y creadora de páginas web con inteligencia artificial.

Ayudo a autónomos, pequeños negocios y marcas personales a tener una web profesional, moderna y lista para captar clientes desde el primer día.

Me gusta trabajar de forma cercana, rápida y práctica, cuidando tanto el diseño como el mensaje para que cada proyecto transmita confianza desde el primer momento.

PROYECTOS LANZADOS
ENTREGA MEDIA
CLIENTES CONTENTOS
); } function Counter({ to, suffix = "" }) { const [n, setN] = useState(0); const ref = useRef(null); useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver((entries) => { if (entries[0].isIntersecting) { const dur = 1200; const start = performance.now(); const step = (now) => { const t = Math.min(1, (now - start) / dur); const eased = 1 - Math.pow(1 - t, 3); setN(Math.round(to * eased)); if (t < 1) requestAnimationFrame(step); }; requestAnimationFrame(step); io.disconnect(); } }, { threshold: 0.4 }); io.observe(el); return () => io.disconnect(); }, [to]); return {n}{suffix}; } // ========================================================= // FAQ // ========================================================= function FAQ() { const [open, setOpen] = useState(0); return (
Lo que casi todo el mundo quiere saber.
{FAQS.map((f, i) => (
setOpen(open === i ? -1 : i)}>
{String(i + 1).padStart(2, "0")}
{f.q}
{f.a}
))}
); } // ========================================================= // BLOG // ========================================================= function Blog() { return (
Aprende a hacer crecer tu web sin complicarte.
{POSTS.map((p, i) => (
{p.tag}{p.read} lectura
{p.title}
{p.excerpt}
))}
); } // ========================================================= // CONTACTO // ========================================================= function Contacto() { const [form, setForm] = useState({ nombre: "", email: "", empresa: "", presupuesto: "", mensaje: "" }); const [servicios, setServicios] = useState([]); const [toast, setToast] = useState(""); const set = (k) => (e) => setForm(f => ({ ...f, [k]: e.target.value })); const toggle = (s) => setServicios(arr => arr.includes(s) ? arr.filter(x => x !== s) : [...arr, s]); const submit = (e) => { e.preventDefault(); if (!form.nombre || !form.email || !form.mensaje) { setToast("Faltan campos por rellenar"); setTimeout(() => setToast(""), 2500); return; } const subject = encodeURIComponent(`Nuevo proyecto: ${form.nombre} (${form.empresa || "sin empresa"})`); const lines = [ `Nombre: ${form.nombre}`, `Email: ${form.email}`, `Empresa: ${form.empresa || "—"}`, `Presupuesto: ${form.presupuesto || "—"}`, `Servicios de interés: ${servicios.join(", ") || "—"}`, ``, `Mensaje:`, form.mensaje, ]; const body = encodeURIComponent(lines.join("\n")); window.location.href = `mailto:errajioumaima@gmail.com?subject=${subject}&body=${body}`; setToast("Abriendo tu correo…"); setTimeout(() => setToast(""), 3000); }; const SERVICES_LIST = ["Web nueva", "Rediseño", "Tienda online", "Mantenimiento", "Marca personal", "SEO"]; const PRESUPUESTOS = ["< 500 €", "500 – 1.000 €", "1.000 – 2.000 €", "> 2.000 €"]; return (
Cuéntame tu proyecto. Te respondo en 24h.

¿Listos para darle luz a tu próximo proyecto?

EMAILerrajioumaima@gmail.com
HORARIOLun – Vie · 09:00 – 19:00 (CET)
UBICACIÓNEspaña · trabajamos en remoto
{SERVICES_LIST.map(s => ( ))}
{PRESUPUESTOS.map(p => ( ))}
Al enviar abriremos tu app de correo con todo listo para errajioumaima@gmail.com
{toast ?
{toast}
: null}
); } // ========================================================= // FOOTER // ========================================================= function Footer() { return ( ); } // ========================================================= // COOKIE BANNER // ========================================================= const COOKIE_KEY = "weblume_cookie_consent"; function CookieBanner() { const [visible, setVisible] = useState(false); const [animIn, setAnimIn] = useState(false); const [decided, setDecided] = useState(true); // assume decided until we check storage useEffect(() => { try { const prev = localStorage.getItem(COOKIE_KEY); if (!prev) { setDecided(false); // small delay so it doesn't fight the hero reveal setTimeout(() => { setVisible(true); requestAnimationFrame(() => setAnimIn(true)); }, 900); } else { setDecided(true); } } catch (e) { setDecided(false); setVisible(true); setAnimIn(true); } }, []); const decide = (choice) => { try { localStorage.setItem(COOKIE_KEY, JSON.stringify({ choice, ts: Date.now() })); } catch (e) {} setAnimIn(false); setTimeout(() => { setVisible(false); setDecided(true); }, 400); }; const reopen = () => { setDecided(false); setVisible(true); requestAnimationFrame(() => setAnimIn(true)); }; return ( <> {visible ? (
🍪

Usamos cookies

Usamos cookies técnicas (necesarias) y, con tu permiso, analíticas para entender cómo se usa la web. Puedes consultar nuestra Política de Cookies.

) : null} {decided && !visible ? ( ) : null} ); } const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "palette": "cream", "cursor": true, "italicAccent": true }/*EDITMODE-END*/; function Tweaks({ onTweak }) { const { TweaksPanel, useTweaks, TweakSection, TweakSelect, TweakToggle } = window; if (!TweaksPanel) return null; const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); useEffect(() => { document.documentElement.setAttribute("data-palette", t.palette); onTweak({ cursor: t.cursor }); }, [t.palette, t.cursor, onTweak]); return ( setTweak("palette", v)} options={[ { value: "cream", label: "Crema · Terracota" }, { value: "ink", label: "Crema · Negro" }, { value: "forest", label: "Crema · Bosque" }, { value: "night", label: "Modo noche" }, ]} /> setTweak("cursor", v)} /> ); } // ========================================================= // APP // ========================================================= function App() { const [cursorOn, setCursorOn] = useState(!!TWEAK_DEFAULTS.cursor); useCursor(cursorOn); useReveal(); const handleTweak = React.useCallback((edits) => { if ("cursor" in edits) setCursorOn(!!edits.cursor); }, []); return ( <>