P
Recherches récentes

El page builder Punky, bajo el capó

22 vues

Construir tu propio page builder es una locura. También es la mejor decisión que hemos tomado. Ya existen decenas, en todos los lenguajes — entonces, ¿por qué reinventar la rueda? Porque la rueda que queríamos no existía. Así funciona el nuestro, y esto es lo que esa decisión nos aporta de verdad.

El concepto: una página es un dato

Todo parte de una idea simple: una página no es un archivo que se programa a mano, es un dato que se manipula. Separamos radicalmente el contenido (qué mostrar, en qué orden) del renderizado (cómo convertirlo en HTML).

Ese dato es JSON: un árbol de bloques. El editor visual solo edita ese árbol — arrastrar un bloque, cambiar una propiedad, reordenar. Nada más. Y como es un dato, es portable, versionable (vive en Git como todo lo demás) e importable de un sitio a otro. Una sección que nos gusta, la copiamos y pegamos.

El árbol: secciones → columnas → bloques

El árbol tiene tres niveles, siempre los mismos. Una sección (la banda a todo el ancho, con su fondo, su padding y su grid) contiene columnas (la maquetación en 12 columnas), que contienen bloques (el contenido: título, texto, imagen, slider, acordeón, posts…).

page.json
[
  {
    "type": "section",
    "container": "max-w-6xl",
    "columns": [
      {
        "gridColumn": "col-span-6",
        "blocks": [
          { "type": "heading", "level": 2, "content": "Hola" },
          { "type": "text", "content": "<p>Un párrafo.</p>" }
        ]
      }
    ]
  }
]

Eso es todo. Esta regularidad es deliberada: tres niveles, nunca más. Se puede anidar un bloque group para los casos avanzados, pero el modelo mental se mantiene constante — sección → columna → bloque. Un desarrollador que abre el JSON entiende la estructura de la página en diez segundos, sin documentación.

De JSON a HTML: la generación de Blade

Al guardar, el builder no se limita a almacenar el JSON: genera un archivo Blade en disco. La página servida al visitante es HTML casi estático, sin coste de interpretar el JSON al vuelo. Pagamos el coste de transformación una sola vez, al guardar — no en cada visita. Rápido por construcción.

Cada tipo de bloque tiene su generador — HeadingGenerator, ImageGenerator, SliderGenerator… — cuyo único trabajo es convertir un nodo JSON en markup limpio. Añadir un tipo de bloque es añadir un generador; el resto de la cadena no se mueve. El JSON anterior produce, por ejemplo:

página generada (extracto)
<section id="section-a1b2" class="py-12">
  <div class="container max-w-6xl">
    <div class="col-span-6">
      <h2 class="font-display text-3xl">Hola</h2>
      <p>Un párrafo.</p>
    </div>
  </div>
</section>

Una consecuencia práctica que conviene conocer: si modificas un generador, hay que volver a desplegar Y volver a guardar la página en el builder para regenerar el Blade. El HTML en disco no se actualiza solo. Es el precio de la velocidad, y lo asumimos.

El punto delicado: el scoping CSS

La parte más sutil es el CSS personalizado por sección. Si dejáramos las reglas tal cual, una .ma-classe escrita en una sección se desbordaría sobre todas las demás. Por eso prefijamos automáticamente cada selector con el id de la sección.

scoping
/* Lo que escribes en el panel de la sección */
.ma-classe { color: #FF5310; }

/* Lo que se genera, prefijado por el id de la sección */
#section-xyz .ma-classe { color: #FF5310; }

/* Los @keyframes permanecen globales; el & se reemplaza por el id del bloque */
@keyframes pulse { from { opacity: .5 } to { opacity: 1 } }

Algunas sutilezas: los @keyframes se preservan (deben permanecer globales), y el & al estilo SCSS se gestiona — reemplazado por el id del bloque, para escribir reglas autorreferenciadas. Son detalles invisibles, pero son los que evitan que una hoja de estilos se pise a sí misma.

¿Por qué hacerlo uno mismo?

Queda la verdadera pregunta: ¿por qué todo esto, cuando existen Gutenberg, Elementor, Webflow, Builder.io, GrapesJS, Puck… en todos los lenguajes? Estas herramientas son excelentes, y para la mayoría de los proyectos, son ellas las que hay que elegir. Pero todas imponen el mismo trato: adoptas su modelo, su markup, su ecosistema — y te pliegas a él.

Pero para nosotros, el builder no es un accesorio: es el núcleo del producto. Impulsa todos los sitios de clientes y la propia agencia. A esa escala, tres cosas importan, y ninguna herramienta de terceros nos las daba juntas: el control total del markup generado (y por tanto del rendimiento y la accesibilidad), la integración nativa con el resto del stack (CodeIgniter, la mediateca, la autenticación, el multilingüe, el sitemap, la caché Redis), y la libertad de evolución — una necesidad de cliente se convierte en un nuevo bloque, no en un apaño.

CriterioBuilder de tercerosBuilder propio
Markup generadoimpuesto, a menudo verbosocontrolado línea a línea
Rendimientovariableoptimizado por diseño
Integración con el stackvia plugins / APInativa
Evolución del productosu roadmapla nuestra
Coste inicial & mantenimientobajoalto
Elígelo si…sitio único, time-to-marketel builder = núcleo del producto

Y está el candado: un builder de terceros es una suscripción, una dependencia, una roadmap que no controlas. El día en que sube los precios, cambia su modelo de licencia (los recientes giros de licencia por todas partes no dan confianza) o cierra, lo sufres. Del nuestro, respondemos nosotros.

Cuándo NO hacerlo

Seamos honestos: no es un consejo universal. Escribir tu propio builder es caro — al principio, y para siempre, porque hay que mantenerlo de por vida. Para un sitio único, un blog, un proyecto puntual, es absurdo: coge Gutenberg, Webflow o un GrapesJS / Puck open source, y avanza.

El cálculo solo se inclina hacia el «propio» cuando el builder se convierte en un activo estratégico: lo reutilizas en decenas de proyectos, lo conviertes en producto, necesitas un control que nada más ofrece. Es nuestro caso. Para la mayoría de la gente, no es el suyo — y está muy bien así.

La lección: poder decir que sí

Un builder propio nos da lo que ninguna solución cerrada dará jamás: el control del markup, del rendimiento y de la evolución del producto. Cuando un cliente tiene una necesidad concreta, añadimos un bloque. No esquivamos un límite impuesto por un proveedor externo.

Eso es la independencia tecnológica: poder decir que sí.

Partager