7.8 KiB
Layout Global y Librerías Globales
Este documento explica cómo gestionar los 4 campos globales del proyecto (style CSS global, javascript JS global, header Twig del header del sitio, footer Twig del footer) y las librerías globales (CSS/JS/fonts inyectadas en <head> o antes de </body>). Cubre la regla crítica de NO editar nunca cms/lib/plugins/builder_saas/layout.json ni los .tpl de custom-header-twig / custom-footer-twig directamente, las tools get_layout_field / set_layout_field (única vía válida para editar header/footer/style/javascript) y las tools list_global_libraries / add_global_library / remove_global_library / set_global_libraries para gestionar las URLs de librerías. Léelo antes de tocar cualquier cosa relacionada con header, footer, CSS global o librerías externas (jQuery, Vue CDN, Google Fonts, etc.).
Layout global
Los 4 campos globales del proyecto viven en cms/lib/plugins/builder_saas/layout.json:
| Campo | Contenido |
|---|---|
style |
CSS global del proyecto (se inyecta en todas las páginas) |
javascript |
JS global del proyecto (se inyecta en todas las páginas) |
header |
Twig del header del sitio (se renderiza arriba de cada página) |
footer |
Twig del footer del sitio (se renderiza al final de cada página) |
Los campos header y footer son Twig — se beneficias de filtros (| get, | translate, etc.) y atributos (c-if, c-for).
REGLA CRÍTICA — Nunca edites estos archivos directamente
Está prohibido usar acai-view, acai-line-replace, acai-write ni acai-delete sobre:
cms/lib/plugins/builder_saas/layout.jsontemplate/estandar/modulos/custom-header-twig/*template/estandar/modulos/custom-footer-twig/*template/estandar/modulos/custom-header/*template/estandar/modulos/custom-footer/*
Estos ficheros son artefactos generados a partir de layout.json. Editarlos directamente provoca:
- Desincronización con
layout.json.{header,footer}ModuleCustom.htmlParsed. - Sobrescritura de tus cambios cuando el usuario abre el builder visual y guarda.
- Comportamiento inconsistente entre el render público y el builder.
El backend protege estas rutas — las tools de archivo devolverán error si intentas tocarlas.
Workflow correcto
Leer
get_layout_field({ field: "header" }) // Twig source del header
get_layout_field({ field: "footer" }) // Twig source del footer
get_layout_field({ field: "style" }) // CSS global
get_layout_field({ field: "javascript" }) // JS global
Escribir
set_layout_field({
field: "footer",
content: "<footer class='bg-gray-900 text-white py-10'>…nuevo HTML/Twig…</footer>"
})
set_layout_field ejecuta una pipeline atómica:
- Escribe el source en
layout.json.{field}. - Sincroniza
layout.json.{field}ModuleCustom.htmlParsed. - Regenera los
.tpldecustom-{field}-twig/. - Compila el Twig a PHP.
Es destructivo — sobrescribe el contenido completo. Pair con get_layout_field primero para leer el actual y modificarlo, no escribirlo desde cero.
Ejemplos de uso
Cambiar el copyright del footer
// 1. Leer
get_layout_field({ field: "footer" })
// devuelve: <footer><p>© 2024 Mi Sitio</p>…</footer>
// 2. Modificar localmente y reescribir entero
set_layout_field({
field: "footer",
content: "<footer><p>© 2025 Mi Sitio. Todos los derechos reservados.</p>…</footer>"
})
Añadir un menú al header
// 1. Leer source actual
get_layout_field({ field: "header" })
// 2. Escribir nueva versión con el menú añadido
set_layout_field({
field: "header",
content: "<header>…<nav>{% for item in 'apartados' | get('parentNum=0 AND visible_en_el_menu=1', 'globalOrder ASC') %}<a href='{{ item.enlace }}'>{{ item.name }}</a>{% endfor %}</nav>…</header>"
})
Añadir CSS global
// 1. Leer
get_layout_field({ field: "style" })
// 2. Reescribir con la regla añadida
set_layout_field({
field: "style",
content: ":root { --main-color: #2563eb; }\n.btn-primary { … }\n…"
})
Librerías globales
layout.json["libraries"] define una lista de URLs (CSS, JS, fonts) que el CMS inyecta en cada página. Hay dos secciones:
| Sección | Posición | Uso típico |
|---|---|---|
top |
Dentro de <head> |
CSS, fonts (Google Fonts), JS crítico (preload) |
bottom |
Antes de </body> |
La mayoría de JS (jQuery, Vue, sliders, etc.) |
Tools
Listar — list_global_libraries
list_global_libraries()
Devuelve:
{
"top": [
{ "num": 1, "url": "https://fonts.googleapis.com/css2?family=Inter" },
{ "num": 2, "url": "/css/extras.css" }
],
"bottom": [
{ "num": 1, "url": "https://unpkg.com/vue@3/dist/vue.global.prod.js" },
{ "num": 2, "url": "/js/main.js" }
],
"layoutExists": true
}
Llama a esta tool antes de añadir/quitar para no duplicar entradas.
Añadir — add_global_library
Idempotente: si la URL ya existe en esa sección, devuelve added: false.
add_global_library({
section: "bottom",
url: "https://unpkg.com/vue@3/dist/vue.global.prod.js"
})
add_global_library({
section: "top",
url: "https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap"
})
// Rutas relativas al proyecto también valen
add_global_library({
section: "bottom",
url: "/js/custom.js"
})
Eliminar — remove_global_library
Idempotente: si la URL no existe, devuelve removed: false.
remove_global_library({
section: "bottom",
url: "https://unpkg.com/vue@3/dist/vue.global.prod.js"
})
Reemplazar entera — set_global_libraries
Destructivo — sobrescribe la lista completa de la sección. Úsalo solo para reordenar masivamente o reemplazar el conjunto. Para cambios incrementales prefiere add_global_library / remove_global_library.
set_global_libraries({
section: "bottom",
libraries: [
{ url: "/js/jquery.min.js" },
{ url: "/js/main.js" },
{ url: "https://unpkg.com/vue@3/dist/vue.global.prod.js" }
]
})
Convenciones
- Para librerías populares, prefiere CDN oficial (
unpkg.com,cdn.jsdelivr.net,cdnjs.cloudflare.com). - Para assets propios del proyecto, usa rutas relativas (
/js/main.js,/css/extras.css). - Si añades una librería que ya tiene equivalente cargada (ej. dos versiones de jQuery), elimina la antigua antes de añadir la nueva.
- El orden importa: las dependencias deben ir antes que sus consumidores.
set_global_librariespermite reordenar.
Decisión: ¿layout global o módulo?
| Caso | Solución |
|---|---|
| Header/footer del sitio | Layout global (set_layout_field con header/footer) |
| CSS aplicado a todo el sitio | Layout global (set_layout_field con style) o librería global |
| JS aplicado a todo el sitio | Layout global (set_layout_field con javascript) o librería global |
| Componente reutilizable en páginas | Módulo en template/estandar/modulos/ |
| Detalle de un registro | Sección general custom-{tableName} |
| Bloque visual específico | Módulo |
Reglas críticas
- NUNCA edites directamente
layout.json,custom-header-twig/*,custom-footer-twig/*,custom-header/*,custom-footer/*. Las tools de archivo te devolverán error si lo intentas. - Para header/footer/style/javascript globales, única vía:
get_layout_field+set_layout_field. set_layout_fieldes destructivo — siempre lee primero, modifica, escribe.- Para librerías globales:
list_global_libraries→add_global_library/remove_global_library.set_global_librariessolo para reordenar/reemplazar masivamente. - Inyección automática:
topva en<head>,bottomantes de</body>. Decide según el tipo de asset. - El orden de las librerías importa para dependencias.