# Acai Modular System ## Modules Modules are the visual building blocks of Acai websites. Each module lives in `template/estandar/modulos//`. ### File Structure ``` / ├── index-base.tpl # Source template (EDIT THIS) ├── index.tpl # Compiled output (auto-generated, do NOT edit) ├── index-twig.tpl # Compiled Twig output (auto-generated, do NOT edit) ├── builder.json # Compiled builder vars (auto-generated, do NOT edit) ├── style.css # Module-scoped styles ├── script.js # Module JavaScript ├── hook.php # Module hook (optional — only if this module needs server-side logic) ├── assets/ # Vue components and other JS assets for this module └── minified/ ├── script-{hash}.js # JS minificado (servido al browser, do NOT edit) └── style-{hash}.css # CSS minificado (servido al browser, do NOT edit) ``` ### Template Syntax Templates use a hybrid of **Twig** and **Acai attributes**. The source file is always `index-base.tpl`. ```html

Title here

Description text

Call to action
``` ### Including Modules from Other Modules ```html ``` Parameters are received as variables inside the included module. ### Global Variables See [twig-reference.md — Global Variables](twig-reference.md#global-variables) for the full list of variables available in all templates. ## General Sections General sections are database-backed templates used for record views, headers, footers, and reusable layouts. They use the same template engine as modules. ### Key Differences from Modules - Access record data via the `thisrecord` variable - Upload fields return **arrays**: `thisrecord.image[0].urlPath` - Additional upload metadata: `info1` (alt text), `info2`, `info3`, `info4` - Foreign key field names match the schema exactly (may or may not have `_num` suffix — always check the `.ini.php`) - Saved via `save_general_section()` (not `save_module()`) - Parser type 2 = Twig (recommended), 0 = Acai legacy syntax ### Example: Record Template ```html
{{ thisrecord.imagen[0].info1 }}

{{ thisrecord.nombre }}

{{ thisrecord.descripcion | raw }}

{{ thisrecord.precio }}€
``` ### Variable Assignment Use `` tag to create variables from queries: ```html ``` ## Repeatable Content (multiv2) The `multiv2` builder field type creates repeatable groups of fields: ```html

{{ item.title }}

{{ item.description }}

``` Access individual items: `record.items[0].title`, `record.items[1].image`, etc. --- ## Workflow Local (Docker) Al editar módulos en desarrollo local con Docker, los archivos compilados no se regeneran automáticamente. Hay que copiar manualmente: ```bash # 1. Editar HTML y JS por separado vim modulos/MODULE_ID/index-base.tpl # Solo HTML vim modulos/MODULE_ID/script.js # Todo el JS # 2. Copiar para que Docker los sirva cp modulos/MODULE_ID/index-base.tpl modulos/MODULE_ID/index.tpl cp modulos/MODULE_ID/script.js modulos/MODULE_ID/minified/script.js ``` ### Herramientas de debug - **`?compiletwig`** — Añadir a cualquier URL. Regenera los `index-twig.tpl` pero con un pipeline diferente al auto-compile. Útil para forzar recompilación, pero puede romper en ciertos contextos. Usar con precaución. - **`?pruebas`** — Bypass de modo mantenimiento. Añadir a cualquier URL establece `$_SESSION["pruebas"]=true`. Solo hay que hacerlo una vez por sesión. --- ## General Sections — Deploy Las general sections se identifican como `custom-{nombre_tabla}` (ej: `custom-productos`). Se despliegan con `save_general_section`, NO con `save_module`: - `table`: nombre de la tabla (ej: `"productos"`) - `content`: HTML del template - `javascript`: JS - `css`: CSS --- ## Páginas CMS (Apartados) ### Campo `controlador` obligatorio para builder Si una página debe renderizar módulos del builder (drag-and-drop), necesita estos campos configurados: ``` controlador = "cms/lib/plugins/builder_saas/controlador.php" precontrolador = "cms/lib/plugins/builder_saas/controlador_tabla.php" ``` Sin estos campos, la página muestra solo la general section (`custom-apartados`) en vez de los módulos asignados.