Página de Aterrizaje — Orquestador
Directorio de salida: ./generated/{slug}-landing (relativo al directorio de trabajo actual, o configurable mediante la variable de entorno LANDING_PAGE_OUTPUT_DIR)
Paso 1 — Analizar Entrada
Dividir los argumentos por | (recortar):
[0]→company_name(si falta, inventar un nombre creativo y apropiado para el sector)[1]→industry(deducir si falta)[2]→tagline_hint(opcional)[3]→target_audience(opcional)[4]→cta_goal(opcional, predeterminado: "Commencer gratuitement")
slug = company_name en minúsculas, sin acentos, espacios → guiones.
Resolver la ruta de salida:
OUTPUT_DIR="${LANDING_PAGE_OUTPUT_DIR:-./generated}/{slug}-landing"
Paso 2 — Brief de Contenido (landing-page-copy)
Invocar la habilidad landing-page-copy con las entradas analizadas. Esperar la salida completa de CONTENT_BRIEF antes de continuar.
El brief contiene: texto del héroe, características, testimonios, FAQ, acerca de, planes de precios, artículos del blog, casos de estudio, etiquetas de navegación. Este texto es la fuente de verdad para todo el contenido del sitio generado — no inventes texto durante la generación de código.
Paso 3 — Diseño + SEO (ejecutar en paralelo)
3-A. Inteligencia de Diseño (ui-ux-pro-max)
Ejecutar estos 3 comandos en paralelo:
python3 ~/.claude/skills/ui-ux-pro-max/scripts/search.py "{industry}" --design-system -p "{company_name}"
python3 ~/.claude/skills/ui-ux-pro-max/scripts/search.py "{industry}" --domain color -n 3
python3 ~/.claude/skills/ui-ux-pro-max/scripts/search.py "{industry} landing page" --domain typography -n 3
Nota: requiere la habilidad ui-ux-pro-max instalada. Si no está disponible, sintetiza un brief de diseño directamente desde el contexto de la industria y la marca.
Sintetizar en un brief de diseño:
- Estado de ánimo visual (3-5 adjetivos)
- Paleta de colores: primario, secundario, acento, fondo, fondo-suave, fondo-tarjeta, superficie, texto, texto-atenuado, texto-inverso, borde, borde-sutil, punto
- Tipografía: fuente de encabezados + fuente de cuerpo (deben existir en Google Fonts)
- Decisiones de diseño: tipo de héroe, diseño de características, estilo de testimonios
- Estilo de animación: sutil / moderado / expresivo
- Detalle distintivo: un elemento visual único que haga memorable esta página
3-B. Plan SEO (landing-page-seo)
Invocar la habilidad landing-page-seo con company_name, industry y el CONTENT_BRIEF. Esperar la salida completa de SEO_PLAN.
El plan contiene: metaetiquetas por página, tipos de marcado schema, configuración del sitemap, sugerencias de compilación para Core Web Vitals, sugerencias SEO para IA.
Paso 4 — Escribir Todos los Archivos
Crear {OUTPUT_DIR}, luego escribir cada archivo desde cero usando la herramienta de escritura. Usar CONTENT_BRIEF para todo el texto y SEO_PLAN para todos los meta/schema. Sin plantillas, sin texto de marcador de posición.
4-A. Infraestructura
package.json:
{
"name": "{slug}-landing",
"version": "0.1.0",
"private": true,
"scripts": { "dev": "next dev", "build": "next build", "start": "next start" },
"dependencies": {
"next": "^16.2.7",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"lucide-react": "^0.474.0",
"framer-motion": "^12.40.0"
},
"devDependencies": {
"@next/mdx": "^16.2.7",
"@mdx-js/loader": "^3.0.0",
"@mdx-js/react": "^3.0.0",
"@types/mdx": "^2.0.0",
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"tailwindcss": "^3.4.1",
"postcss": "^8.5.10",
"autoprefixer": "^10.0.1"
}
}
Versiones: stack validado Next 16 + React 19 + framer-motion 12 + lucide-react 0.474 (build
output: 'export'OK). NO fijesnexta14.2.0nireact/react-doma^18(versiones vulnerables — aviso crítico de Next del 2025-12-11).lucide-reactdebe ser>= 0.474(las versiones0.378y< 0.474no declaran el peer React 19 y rompennpm install).
next.config.js:
const withMDX = require('@next/mdx')()
module.exports = withMDX({
output: 'export',
images: { unoptimized: true },
pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
})
tsconfig.json: tsconfig estándar de Next.js con el alias de ruta @/* para ./ y "jsx": "react-jsx" (Next 16 usa el runtime automático de React — "preserve" se reescribe automáticamente al compilar)
tailwind.config.ts:
darkMode: 'class'fontFamily: variables CSS de encabezado + cuerpoanimation:marquee,float,line-growkeyframes: marqueetranslateX(0%)→translateX(-50%), float, lineGrow
postcss.config.js: tailwind + autoprefixer
mdx-components.tsx: mapear h1 h2 h3 p ul li strong blockquote a elementos estilizados usando variables CSS
app/globals.css:
@tailwind base/components/utilities- Variables CSS en
:root— todos los tokens de diseño del brief de diseño html.dark { ... }— sobrescribir TODAS las variables para el modo oscurobodyusando variables CSS, con transición en background-color + color- Utilidades personalizadas:
.text-gradient,.dot-grid,.glass-card,.bracket-card,.clip-diagonal-bottom,.clip-diagonal-top - REGLAS: cada referencia de color en los componentes usa variables CSS — cero hexagesimales escritos directamente
4-B. Componentes
Escribir cada uno como .tsx. Cada componente lee el texto de lib/data.ts. Todos los colores mediante variables CSS.
components/DarkModeToggle.tsx:
'use client', leelocalStorageal montar, alterna la clasedarken<html>- Persiste la preferencia, iconos Sun/Moon de lucide-react
components/LogoCarousel.tsx:
'use client', carrusel CSS puro (animate-marquee), sin desplazamiento JS- Nombres de marca de
lib/data.ts, duplicados para un bucle sin costuras
components/ContactForm.tsx:
'use client', estado:'idle' | 'sending' | 'sent' | 'error'<form data-netlify="true" name="contact">conform-nameoculto- Campos: nombre, email, empresa, mensaje
- Enviar:
fetch('/', { method: 'POST', body: new URLSearchParams(new FormData(form)) })
components/Navbar.tsx: fija, sensible al scroll, menú móvil, <DarkModeToggle />
components/Hero.tsx:
- Animación de entrada con Framer Motion y verificación de
useReducedMotion - Fila de estadísticas con
<data value="{stat.value}">(SEO para IA) - Detalle de diseño distintivo del brief de diseño
components/Features.tsx: whileInView Framer Motion, retardo escalonado
components/Testimonials.tsx: whileInView Framer Motion por tarjeta
components/FAQ.tsx:
'use client', acordeón- Marcado semántico
<dl>/<dt>/<dd>(schema FAQPage + SEO para IA)
components/Pricing.tsx:
'use client', alternancia de facturación mensual/anual con distintivo −20%- Cambio entre
priceyprice_annual
components/About.tsx: historia + valores
components/Footer.tsx: eslogan + navegación + copyright
Reglas de componentes:
'use client'solo en componentes interactivos o que usen APIs del navegadorimport type { X }para importaciones solo de tipo- Iconos dinámicos de lucide:
import type { LucideIcon } from 'lucide-react', luego(Icons as any)[name] as LucideIcon | undefined. Tipar las props del icono comoLucideIcon— NO comoReact.ComponentType<{size?:number}>(elsizede lucide esstring|number, por lo que el tipo estricto falla en la verificación de tipos denext build). - Todos los colores mediante variables CSS — cero hexagesimales escritos directamente
- Framer Motion para animaciones (sin IntersectionObserver)
- Todo el texto de
lib/data.ts
4-C. Páginas
app/layout.tsx:
- Google Fonts mediante
next/font/google - Metadatos del meta de la página de inicio de SEO_PLAN
- JSON-LD: Organization + WebSite (o SoftwareApplication) de SEO_PLAN
- Anti-parpadeo de modo oscuro en
<head>:try{if(localStorage.getItem('theme')==='dark'||(localStorage.getItem('theme')===null&&window.matchMedia('(prefers-color-scheme: dark)').matches)){document.documentElement.classList.add('dark')}}catch(e){} suppressHydrationWarningen<html><link rel="preconnect" href="https://fonts.googleapis.com">
app/page.tsx: Navbar + Hero + LogoCarousel + Features + Testimonials + Pricing + FAQ + ContactForm + Footer
app/tarifs/page.tsx: Metadatos + JSON-LD (Offer + FAQPage) de SEO_PLAN + Navbar + Pricing + FAQ + ContactForm + Footer
app/a-propos/page.tsx: Metadatos + JSON-LD (AboutPage + Organization) + Navbar + About + Footer
app/blog/layout.tsx + app/blog/page.tsx: listado de lib/blog.ts
app/blog/{slug-1}/page.mdx + app/blog/{slug-2}/page.mdx:
- Contenido de CONTENT_BRIEF
blog[] - Envoltura semántica
<article>+<time datetime="..."> - TL;DR en el primer párrafo (citable por SEO para IA)
app/cas-clients/layout.tsx + app/cas-clients/page.tsx: listado de lib/case-studies.ts
app/cas-clients/{slug-1}/page.mdx + app/cas-clients/{slug-2}/page.mdx:
- Contenido de CONTENT_BRIEF
case_studies[] - Estructura H2 explícita
## Desafío / ## Solución / ## Resultados(SEO para IA) - BreadcrumbList JSON-LD de SEO_PLAN
app/sitemap.ts: sitemap_config de SEO_PLAN para todas las páginas, entradas de blog y casos de estudio
app/robots.ts: permitir todo, URL del sitemap
4-D. Archivos de Datos
lib/data.ts — todo el texto de CONTENT_BRIEF:
export const siteData = {
nav: { links: [...], cta: "..." },
hero: { badge, headline_a, subheadline, cta_primary, cta_secondary, social_proof_bar, stats },
logoCarousel: { section_label, brands: [...] },
features: { badge, heading, sub, items: [...] },
testimonials: [...],
faq: { items: [...] },
about: { headline, story, values: [...] },
pricing: { heading, sub, plans: [...] },
contact: { heading, sub, form_cta },
footer: { tagline }
}
lib/blog.ts: registro del blog de CONTENT_BRIEF
lib/case-studies.ts: registro de casos de estudio de CONTENT_BRIEF
Imagen del héroe — elegir de estos marcadores de posición de Unsplash:
- Tecnología/SaaS/Fintech:
https://images.unsplash.com/photo-1518770660439-4636190af475?w=1600&q=80 - Salud/Bienestar:
https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b?w=1600&q=80 - Alimentación/Bio:
https://images.unsplash.com/photo-1504674900247-0877df9cc836?w=1600&q=80 - Deporte/Fitness:
https://images.unsplash.com/photo-1517836357463-d25dfeac3438?w=1600&q=80 - Moda/Lujo:
https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=1600&q=80 - Bienes raíces:
https://images.unsplash.com/photo-1560518883-ce09059eeffa?w=1600&q=80 - Educación:
https://images.unsplash.com/photo-1522202176988-66273c2fd55f?w=1600&q=80 - Predeterminado:
https://images.unsplash.com/photo-1497366216548-37526070297c?w=1600&q=80
Paso 5 — Compilar
cd {OUTPUT_DIR}
npm install
npm run build
Errores de TypeScript — corregir y reintentar:
import { X }→import type { X }para importaciones solo de tipo- Icono dinámico:
(Icons as any)[name] as LucideIcon | undefined(importar tipo desdelucide-react); tipar props de icono comoLucideIcon, nuncaComponentType<{size?:number}> - Corregir todos los errores de TypeScript antes de reportar éxito
Paso 6 — Reportar
🏢 Empresa: {company_name} — {industry}
🎨 Diseño: {mood} | {heading font} / {body font}
✨ Detalle: {detalle distintivo}
📝 Titular: "{headline_a}"
📄 Páginas: / · /tarifs · /a-propos · /blog · /cas-clients
🔍 SEO: {title de la página} | {tipos de schema}
📁 Salida: {OUTPUT_DIR}
Vista previa local: cd {OUTPUT_DIR} && npm run dev