lf-pagebuilder-vue

Constructor de páginas visual basado en Vue.js que permite crear y diseñar páginas web de forma intuitiva mediante componentes arrastrables y configurables
18,701
Install
npm install lf-pagebuilder-vue
Latest Version:0.1.10
Vue:3
License:MIT
Last Updated:Jul 21, 2026
Links: npm
Maintainer: lf-blanchart

lf-pagebuilder-vue

Editor visual para construir páginas HTML usando los componentes de libreria-astro-lefebvre.


⚡ Referencia rápida — Todas las opciones

Modo 1 — Componente Vue

npm install lf-pagebuilder-vue
<template>
  <Pagebuilder
    :isProduction="false"
    :debugMode="false"
    :submitForm="false"
    inputId="mi-input-hidden"
    :excludeComponentTypes="['SEO', 'Footer']"
    :excludeComponentTags="['boton', 'destacado']"
    :includeOnlyComponentTags="['articulo']"
    :visibleSections="['Header', 'Body', 'Footer']"
    allowRenderMode="open"
    limboToken="eyJ..."
    ateneaToken="eyJ..."
    :ledithorAiTools="['improve', 'improve-stream']"
    client:only="vue"
  />
</template>

<script setup>
import { Pagebuilder } from 'lf-pagebuilder-vue';
import 'lf-pagebuilder-vue/styles';
</script>
Prop Tipo Default Descripción
isProduction boolean false true = API producción · false = API desarrollo
debugMode boolean false Muestra panel de import/export JSON y botón de carga desde localStorage
submitForm boolean false Al guardar, busca el <form> padre y hace .submit() automáticamente
inputId string | null null ID del <input hidden> donde se vuelca el JSON al guardar y del que se lee el estado inicial
excludeComponentTypes string[] [] Categorías de componentes que NO aparecerán en el selector. "Repetidor" siempre se excluye.
excludeComponentTags string[] [] Tags de componentes a excluir (lista negra). Un componente con cualquiera de estos tags no aparecerá.
includeOnlyComponentTags string[] [] Solo muestra componentes que tengan al menos uno de estos tags (lista blanca). La exclusión tiene prioridad.
visibleSections string[] — Secciones visibles. Si no se indica, se muestran todas. Valores: Header, Body, Footer, Sidebar
allowRenderMode 'open' | 'fullpage' | 'onlybody' 'open' open = el usuario elige · fullpage = forzado página completa · onlybody = forzado solo body
limboToken string — Token JWT para el gestor de imágenes Limbo. Obtenerlo server-side con fetchLimboToken()
ateneaToken string — Token JWT de Atenea para las funcionalidades de IA en el editor de texto (LedithorEditor). Obtenerlo server-side con fetchAteneaToken(). Sin este token el botón de IA no aparece.
ledithorAiTools string[] — Herramientas de IA a habilitar en el editor de texto. Solo se aplican si también se proporciona ateneaToken. Ej: ['improve', 'improve-stream']
viewOnly boolean false Modo solo visualización: oculta toda la UI de edición (toolbar, panel de componentes). Usar para la vista pública.

Categorías disponibles para excludeComponentTypes: Call to Action, Contenido, Separador, Texto, Cabecera, Footer, Imagen, Repetidor, Formulario, Título, SEO


Modo 2 — Script IIFE (Symfony / Twig / cualquier backend)

<link rel="stylesheet" href="/build/lf-pagebuilder-iife.css">
<script src="/build/lf-pagebuilder-iife.iife.js"></script>

<!-- EDITOR (crear) -->
<input
  type="hidden"
  class="js-lf-pagebuilder-vue-input"
  name="pagebuilder[pageConfig]"
  id="pagebuilder-new"
  value=""
  data-is-production="false"
  data-debug-mode="true"
  data-submit-form="true"
  data-allow-render-mode="open"
  data-limbo-token="eyJ..."
  data-atenea-token="eyJ..."
  data-ledithor-ai-tools='["improve","improve-stream"]'
/>

<!-- EDITOR (editar) -->
<input
  type="hidden"
  class="js-lf-pagebuilder-vue-input"
  name="pagebuilder[pageConfig]"
  id="pagebuilder-123"
  value="{JSON existente del pageConfig}"
  data-is-production="false"
  data-submit-form="true"
  data-exclude-component-types="SEO,Footer,Cabecera"
  data-limbo-token="eyJ..."
/>

<!-- VISTA PÚBLICA (solo lectura) -->
<div id="lf-pagebuilder-render"></div>
<script>
  window.LfPagebuilder.render({
    el: '#lf-pagebuilder-render',
    pageConfig: {{ pageConfig|raw }},  {# string JSON o objeto #}
    isProduction: true
  });
</script>
Atributo data-* Valores Default Descripción
data-is-production "true" | "false" "false" Entorno de la API de renderizado
data-debug-mode "true" | "false" "false" Muestra panel de import/export JSON y botón de carga desde localStorage
data-submit-form "true" | "false" "false" Al guardar, busca el <form> padre y hace .submit() automáticamente
data-exclude-component-types string (comas) — Categorías de componentes a excluir. Ej: "SEO,Footer,Cabecera"
data-exclude-component-tags string (comas) — Tags de componentes a excluir (lista negra). Ej: "boton,destacado"
data-include-only-component-tags string (comas) — Solo muestra componentes con estos tags (lista blanca). La exclusión tiene prioridad.
data-visible-sections string (comas) — Secciones visibles. Ej: "Header,Body"
data-allow-render-mode "open" | "fullpage" | "onlybody" "open" Controla el modo de renderizado
data-limbo-token string — Token JWT de Limbo para el gestor de imágenes
data-atenea-token string — Token JWT de Atenea para las funcionalidades de IA. Sin este token el botón de IA no aparece.
data-ledithor-ai-tools string (JSON array) — Herramientas de IA a habilitar. Solo se aplican si hay data-atenea-token. Ej: '["improve","improve-stream"]'

El id del input se usa como clave de localStorage y como referencia interna. Si no tiene id, se genera uno automáticamente.

Compatibilidad de atributos: El componente acepta también los tokens como atributos planos (sin prefijo data-): limboToken="...", ateneaToken="...", ledithorAiTools='[...]'. La forma recomendada es siempre data-*.


API global window.LfPagebuilder

Método Descripción
LfPagebuilder.init(config?) Inicializa el editor en todos los elementos .js-lf-pagebuilder-vue-input de la página
LfPagebuilder.render({ el, pageConfig, isProduction? }) Renderiza la página en modo solo visualización (sin UI de edición)
LfPagebuilder.destroyAll() Destruye todas las instancias activas
LfPagebuilder.getInstances() Devuelve todas las instancias activas
LfPagebuilder.setComponents(components) Reemplaza la lista de componentes disponibles
LfPagebuilder.addComponent(component) Añade un componente a la lista disponible

El IIFE se auto-inicializa en DOMContentLoaded si hay elementos con el selector .js-lf-pagebuilder-vue-input en el DOM. No es necesario llamar a init() manualmente.


Integración con Symfony/Twig — Contrato completo

Cómo funciona el intercambio de datos con el formulario

El componente actúa como un "enhanced textarea":

  1. Lee su valor inicial de input.value — en onMounted, el editor lee el JSON del value del input y lo carga como estado inicial del canvas. Si está vacío, el editor empieza en blanco (modo crear). Si contiene JSON, lo inicializa con esa configuración (modo editar).

  2. Escribe en input.value al guardar — cuando el usuario pulsa "Guardar" dentro del editor, el JSON actualizado se escribe en input.value.

  3. Envía el formulario si data-submit-form="true" — después de escribir en input.value, busca el <form> padre y llama a .submit(). Esto permite que Symfony valide y persista el pageConfig.

{# Crear #}
<form method="post" action="{{ path('landing_create') }}">
  <input type="hidden"
         id="pagebuilder-new"
         name="pagebuilder[pageConfig]"
         class="js-lf-pagebuilder-vue-input"
         value=""
         data-is-production="{{ app.environment == 'prod' ? 'true' : 'false' }}"
         data-submit-form="true"
         data-limbo-token="{{ limboToken }}"
         data-atenea-token="{{ ateneaToken }}"
         data-ledithor-ai-tools='["improve","improve-stream"]'
  />
  {# El CSRF token y otros campos del formulario van aquí #}
</form>

{# Editar #}
<form method="post" action="{{ path('landing_edit', {id: landing.id}) }}">
  <input type="hidden"
         id="pagebuilder-{{ landing.id }}"
         name="pagebuilder[pageConfig]"
         class="js-lf-pagebuilder-vue-input"
         value="{{ landing.pageConfig|json_encode }}"
         data-is-production="{{ app.environment == 'prod' ? 'true' : 'false' }}"
         data-submit-form="true"
         data-exclude-component-types="SEO,Footer,Cabecera"
         data-limbo-token="{{ limboToken }}"
  />
</form>

{# Vista pública #}
<div id="lf-pagebuilder-render"></div>
<script>
  window.LfPagebuilder.render({
    el: '#lf-pagebuilder-render',
    pageConfig: {{ landing.pageConfig|raw }},
    isProduction: {{ app.environment == 'prod' ? 'true' : 'false' }}
  });
</script>

Instalación

npm i lf-pagebuilder-vue

Luego en tu package.json, cambia la versión a latest para tener siempre la última:

{
  "dependencies": {
    "lf-pagebuilder-vue": "latest"
  }
}

¿Qué es?

El Pagebuilder permite al usuario arrastrar y configurar componentes de la librería de componentes Astro de Lefebvre para diseñar páginas de forma visual.

El Pagebuilder NO renderiza la página final. Genera un JSON de configuración que se envía a una API externa renderizadora, que es la encargada de generar el HTML final.


Integración con Limbo (gestión de imágenes)

Si se quiere usar el sistema de imágenes Limbo desde el Pagebuilder:

Variables de entorno (.env):

PUBLIC_LIMBO_PUBLIC_KEY=pk_tu_public_key
IS_PROD=FALSE

Obtener token server-side y pasarlo al componente:

---
import { Pagebuilder } from 'lf-pagebuilder-vue';
import { fetchLimboToken } from 'lf-pagebuilder-vue/limbo';

let limboToken = '';
try {
  const result = await fetchLimboToken({
    publicKey: import.meta.env.PUBLIC_LIMBO_PUBLIC_KEY || '',
    isProduction: import.meta.env.IS_PROD === 'TRUE'
  });
  limboToken = result.token;
} catch (e) {
  console.error('[Pagebuilder] Error obteniendo token de Limbo:', e);
}
---

<Pagebuilder
  limboToken={limboToken}
  isProduction={import.meta.env.IS_PROD === 'TRUE'}
  inputId="mi-input"
  client:only="vue"
/>

El token se obtiene en el frontmatter (server-side), evitando exponer la Public Key al cliente.

fetchLimboToken — opciones

import { fetchLimboToken } from 'lf-pagebuilder-vue/limbo';

const { token, expires_in } = await fetchLimboToken({
  publicKey: 'pk_xxx',       // requerido
  isProduction: false,        // opcional, default: false
  limboApiUrl: 'https://...' // opcional, sobreescribe isProduction
});

Integración con Atenea (IA en el editor de texto)

Si se quiere usar las funcionalidades de IA de LedithorEditor (botón "Improve", etc.):

Variables de entorno (.env):

ATENEA_USERNAME=ledithor
ATENEA_APIKEY=tu_apikey_aqui
IS_PROD=FALSE

Obtener token server-side y pasarlo al componente:

---
import { Pagebuilder } from 'lf-pagebuilder-vue';
import { fetchAteneaToken } from 'lf-pagebuilder-vue/atenea';

let ateneaToken = '';
try {
  const result = await fetchAteneaToken({
    username: import.meta.env.ATENEA_USERNAME || '',
    apiKey:   import.meta.env.ATENEA_APIKEY || '',
    isProduction: import.meta.env.IS_PROD === 'TRUE'
  });
  ateneaToken = result.token;
} catch (e) {
  console.error('[Pagebuilder] Error obteniendo token de Atenea:', e);
}
---

<Pagebuilder
  ateneaToken={ateneaToken}
  :ledithorAiTools="['improve', 'improve-stream']"
  client:only="vue"
/>

Si ateneaToken no se proporciona (o está vacío), el botón de IA no aparece en el editor de texto. ledithorAiTools solo tiene efecto si hay token.

fetchAteneaToken — opciones

import { fetchAteneaToken } from 'lf-pagebuilder-vue/atenea';

const { token, expiresAt } = await fetchAteneaToken({
  username: 'ledithor',       // requerido
  apiKey: 'tu_apikey',        // requerido
  isProduction: false,         // opcional, default: false
  ateneaApiUrl: 'https://...' // opcional, sobreescribe isProduction
});
// expiresAt: Unix timestamp (segundos) del claim `exp` del JWT
Parámetro Tipo Default Descripción
username string — Usuario de Atenea
apiKey string — API Key del usuario
isProduction boolean false true → https://atenea.lefebvre.es · false → URL de desarrollo
ateneaApiUrl string — URL base personalizada (sobreescribe isProduction)

Funcionalidades del editor

Color de fondo en filas y columnas

Cada fila y cada columna del editor puede tener un color de fondo personalizado con soporte de canal alpha (opacidad). El color se configura desde el panel de configuración de la fila o columna y se exporta junto al resto de la configuración del layout.

El color se almacena en el JSON de configuración como un valor rgba(r, g, b, a) dentro de la propiedad backgroundColor:

{
  "rows": [
    {
      "config": {
        "backgroundColor": "rgba(255, 200, 100, 0.75)"
      },
      "columns": [
        {
          "config": {
            "backgroundColor": "rgba(240, 240, 240, 1)"
          },
          "components": []
        }
      ]
    }
  ]
}

Resaltado de elemento en edición

Cuando se abre el panel de configuración de una fila, columna o componente, el elemento correspondiente se resalta visualmente con un borde ámbar y un halo de sombra. El resaltado desaparece al cerrar el panel.


Build

El proyecto tiene dos builds:

Build estándar (librería npm)

npm run build

Genera en dist/:

  • index.js — ES Module
  • index.cjs — CommonJS
  • index.d.ts — Tipos TypeScript
  • limbo.js / limbo.cjs — Utilidades de Limbo (server-side)
  • atenea.js / atenea.cjs — Utilidades de Atenea (server-side)
  • styles.css — Estilos

Build Symfony (IIFE)

npm run build:symfony

Genera en dist-symfony/:

  • lf-pagebuilder-iife.iife.js — Script autocontenido (incluye Vue y todas las dependencias)
  • lf-pagebuilder-iife.css — Estilos con utilidades Tailwind prefijadas (mecano:)

Build completo

npm run build:all

Ejecuta ambos builds.


⚠️ Desarrollo local

IMPORTANTE: Lee esta sección completa antes de trabajar con este proyecto localmente.

Trabajar con npm link

Para probar cambios localmente en otro proyecto sin publicar:

# 1. En lf-pagebuilder-vue
cd /ruta/a/lf-pagebuilder-vue
npm link

# 2. En tu proyecto consumidor
cd /ruta/a/tu-proyecto
npm link lf-pagebuilder-vue

⚠️ CRÍTICO: Múltiples librerías con npm link

Este proyecto depende de libreria-astro-lefebvre. Si necesitas trabajar con ambas librerías localmente:

# ❌ INCORRECTO - El segundo comando ROMPE el primero
npm link lf-pagebuilder-vue
npm link libreria-astro-lefebvre

# ✅ CORRECTO - Linkear TODAS en UN SOLO comando
npm link lf-pagebuilder-vue libreria-astro-lefebvre
Flujo completo para trabajar con ambas librerías
# 1. En lf-pagebuilder-vue
cd /ruta/a/lf-pagebuilder-vue
npm link

# 2. En libreria-astro-lefebvre
cd /ruta/a/libreria-astro-lefebvre
npm link

# 3. En tu proyecto consumidor — AMBAS EN UN SOLO COMANDO
cd /ruta/a/tu-proyecto
npm link lf-pagebuilder-vue libreria-astro-lefebvre
Deshacer los enlaces
cd /ruta/a/tu-proyecto
npm unlink lf-pagebuilder-vue libreria-astro-lefebvre
npm install

Watch mode

npm run dev

Ejecuta vite build --watch y recompila automáticamente cuando hay cambios.


📘 Publicar en npm

Para publicar una nueva versión:

  1. Subir la versión en package.json
  2. Compilar y publicar:
    npm run build:all
    npm publish --access public
    
Configurar acceso a npm (primera vez)
  1. Solicitar acceso al equipo desarrollowebteamlef en npm
  2. Crear un token de acceso en tu perfil de npm → Access Tokens
  3. Añadir el token en ~/.npmrc:
    //registry.npmjs.org/:_authToken=TU_TOKEN_AQUI
    

Instalación y dependencias

Dependencias requeridas en el proyecto padre

npm install lf-pagebuilder-vue@latest vue@^3.3.0 vuedraggable@^4.1.0

Configuración en proyectos Astro

npm install @astrojs/vue tailwindcss @tailwindcss/vite

En astro.config.mjs:

import { defineConfig } from 'astro/config';
import vue from '@astrojs/vue';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  integrations: [vue()],
  vite: {
    plugins: [tailwindcss()],
    ssr: {
      noExternal: ['libreria-astro-lefebvre', 'lf-pagebuilder-vue'],
    },
  },
});

Related Packages

vue-page-composer

Visual page editor and renderer for Vue. Register the components you already shi...

2,064 0
gissen

Headless visual editor and renderer for Vue 3.

1,791 35
mechanica

Build Vue 3 websites with a visual block editor

8,918 0
@vuelume/vite-plugin

Dev-only Vite plugin: canvas ↔ source instrumentation, local editing API and the...

408 2
@revenexx/editor

revenexx hard fork of blökkli — interactive page building experience for Nuxt. I...

3,495

Version History

Version Released Vue License
0.1.10 >=3.4.0 <4.0.0 MIT
0.1.9 >=3.4.0 <4.0.0 MIT
0.1.8 >=3.4.0 <4.0.0 MIT
0.1.7 >=3.4.0 <4.0.0 MIT
0.1.6 >=3.4.0 <4.0.0 MIT