# 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 `` o antes de ``). 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.json` - `template/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: "" }) ``` `set_layout_field` ejecuta una pipeline atómica: 1. Escribe el source en `layout.json.{field}`. 2. Sincroniza `layout.json.{field}ModuleCustom.htmlParsed`. 3. Regenera los `.tpl` de `custom-{field}-twig/`. 4. 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: // 2. Modificar localmente y reescribir entero set_layout_field({ field: "footer", content: "" }) ``` #### 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: "
" }) ``` #### 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 `` | CSS, fonts (Google Fonts), JS crítico (preload) | | `bottom` | Antes de `` | La mayoría de JS (jQuery, Vue, sliders, etc.) | ### Tools #### Listar — `list_global_libraries` ``` list_global_libraries() ``` Devuelve: ```json { "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_libraries` permite 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 1. **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. 2. Para header/footer/style/javascript globales, **única vía**: `get_layout_field` + `set_layout_field`. 3. `set_layout_field` es **destructivo** — siempre lee primero, modifica, escribe. 4. Para librerías globales: `list_global_libraries` → `add_global_library` / `remove_global_library`. `set_global_libraries` solo para reordenar/reemplazar masivamente. 5. Inyección automática: `top` va en ``, `bottom` antes de ``. Decide según el tipo de asset. 6. El orden de las librerías importa para dependencias.