Insertar datos de tus tablas
Las etiquetas son cómo tu HTML habla con tus tablas. Están inspiradas en Handlebars (parecen {{...}}) pero solo hay unas pocas.
Etiquetas básicas
{{campo_sufijo}} — mostrar un valor
Inserta el valor de una columna, escapado para HTML (seguro contra XSS):
<h1>{{nombre_producto}}</h1>
<p>{{descripcion_producto}}</p>
Fíjate: el nombre de la etiqueta incluye el sufijo del módulo. Si tu módulo se llama productos con sufijo producto, las columnas se llaman nombre_producto, precio_producto, etc.
{{money campo_x}} — formatear como dinero
Muestra un número como precio con símbolo y separadores:
<strong>{{money precio_producto}}</strong>
Se muestra como $4.500 (según el formato regional configurado).
{{fecha campo_x}} — formatear como fecha legible
Muestra una fecha en formato claro:
<time>{{fecha fecha_visita}}</time>
Se muestra como 24 de julio, 2026 (o el formato que tengas configurado).
{{date campo_x}} hace exactamente lo mismo; es el mismo tag escrito en inglés.
{{img campo_x}} — obtener la URL de una imagen
Devuelve la dirección de la imagen. Se usa dentro de <img src="">:
<img src="{{img imagen_producto}}" alt="{{nombre_producto}}" />
{{html campo_x}} — mostrar un texto con su formato
Para los campos que se escriben con el editor de texto enriquecido del panel (negritas, títulos, listas, enlaces): un artículo, una ficha, una biografía.
<article>{{html contenido_articulo}}</article>
Con {{contenido_articulo}} a secas verías las etiquetas escritas (<p>,
<strong>) en vez del formato. {{html}} muestra el formato y deja fuera lo
peligroso: scripts, formularios incrustados y enlaces que ejecutan código.
Para un nombre, un precio o cualquier texto corto, usa {{campo}}.
{\{#cada}}...{{/cada}} — repetir por cada registro
Repite el contenido interno por cada fila de la tabla:
<ul>
{{#cada}}
<li>{{nombre_producto}} — {{money precio_producto}}</li>
{{/cada}}
</ul>
Si tu tabla tiene 20 productos, se generan 20 <li>.
{\{#si campo}}...{{/si}} — mostrar solo si tiene valor
Renderiza el bloque interno solo si la columna tiene valor (para booleanos, campos opcionales, etc.):
{{#si activo_producto}}
<span class="badge bg-success">Disponible</span>
{{/si}}
Muy útil para etiquetas condicionales, banners de oferta, avisos de agotado.
{\{#no campo}}...{{/no}} — mostrar solo si NO tiene valor
El inverso exacto del anterior: el bloque aparece cuando la columna está vacía o en cero.
{{#no activo_producto}}
<span class="badge bg-secondary">Agotado</span>
{{/no}}
Combinando los dos cubres el caso completo sin escribir nada de lógica:
{{#si stock_producto}}<button>Agregar al carro</button>{{/si}}
{{#no stock_producto}}<span class="text-muted">Sin stock por ahora</span>{{/no}}
{\{#imagenes campo}}...{{/imagenes}} — galería
Recorre las imágenes de un campo tipo Múltiples imágenes:
<div class="galeria">
{{#imagenes fotos_producto}}
<img src="{{url}}" alt="Foto" />
{{/imagenes}}
</div>
Dentro del bloque, {{url}} es la URL de cada imagen individual. Ver Galerías de imágenes.
Datos del registro único (detalle)
Las etiquetas que están fuera de un {{#cada}} no recorren nada: muestran un solo
registro. Cuál, depende de cómo se abra la página:
- Sin
?id=en la dirección → usa el primer registro de la tabla. Sirve para páginas de configuración o información institucional que sacas de una tabla con una sola fila. - Con
?id=en la dirección → usa ese registro. Esta es la página de detalle.
Páginas de detalle con ?id=
No necesitas crear una página por producto. Una sola página de detalle sirve para todos:
<!-- detalle-producto.php -->
<h1>{{nombre_producto}}</h1>
<img src="{{img imagen_producto}}" alt="{{nombre_producto}}" />
<p>{{descripcion_producto}}</p>
<strong>{{money precio_producto}}</strong>
Y desde el listado enlazas a ella pasando el id de cada registro:
{{#cada}}
<a href="detalle-producto.php?id={{id_producto}}">{{nombre_producto}}</a>
{{/cada}}
El comando php tools/make-web-page.php crea el listado y el detalle ya enlazados entre
sí. Ver CLI y MCP.
Editar un registro desde la página pública
Si la página es privada (con acceso por login) y se abre con ?id=, un bloque
{{#form}} deja de crear registros y pasa a actualizar el registro indicado, con los
campos ya rellenos. Es la forma de dar a un cliente o proveedor una ficha que pueda
corregir él mismo.
En una página pública el {{#form}} siempre crea un registro nuevo, aunque lleve
?id=. Es deliberado: sin login, cualquiera podría modificar registros ajenos.
Ver Login y acceso para hacer privada una página.
Si usas el módulo de Inventario, sus tablas Ítems y Categorías de ítems están disponibles como origen de datos: puedes armar una página que muestre tu catálogo con nombre, precio y foto, y se actualiza sola cuando cambias un producto. Lo que no se publica nunca es el costo ni el stock por local. Ver Inventario → Vender el catálogo en línea.
Varias tablas en una misma página
Además del {{#cada}} normal, existe la variante con nombre para recorrer otra tabla
distinta a la principal:
{{#cada:sucursales}}
<li>{{nombre_sucursal}} — {{direccion_sucursal}}</li>
{{/cada:sucursales}}
Las fuentes con nombre (qué tabla, con qué orden y qué límite) no se configuran todavía
desde el generador visual: se definen en la configuración de la página que produce
tools/make-page.php. Si no eres técnico, pide que te la dejen armada — después el HTML
lo editas normal.
Ejemplo completo — carta con etiquetas condicionales
<div class="container my-5">
<h1>Nuestra carta</h1>
<div class="row">
{{#cada}}
<div class="col-md-4 mb-4">
<div class="card h-100">
<img src="{{img imagen_producto}}" class="card-img-top" />
<div class="card-body">
<h5>{{nombre_producto}}</h5>
<p>{{descripcion_producto}}</p>
<div class="d-flex justify-content-between align-items-center">
<strong class="fs-4">{{money precio_producto}}</strong>
{{#si activo_producto}}
<span class="badge bg-success">Disponible</span>
{{/si}}
</div>
</div>
</div>
</div>
{{/cada}}
</div>
</div>
Ejemplo completo — visitas próximas (Aseo Brillo)
<div class="container my-4">
<h2>Próximas visitas programadas</h2>
<table class="table">
<thead>
<tr>
<th>Fecha</th>
<th>Unidad</th>
<th>Servicio</th>
<th>Supervisor</th>
</tr>
</thead>
<tbody>
{{#cada}}
<tr>
<td>{{fecha fecha_visita}}</td>
<td>{{unidad_visita}}</td>
<td>{{servicio_visita}}</td>
<td>{{supervisor_visita}}</td>
</tr>
{{/cada}}
</tbody>
</table>
</div>
Autoescape (seguridad)
Todas las etiquetas {{campo_x}} escapan HTML por defecto. Si un valor contiene <script>, se muestra como texto y no se ejecuta. Esto protege contra XSS sin que hagas nada.
Etiquetas de formularios
Para crear un formulario que guarde registros al enviar:
| Etiqueta | Qué genera |
|---|---|
{{#form}}...{{/form}} | Envuelve un formulario que crea un registro |
{{input campo_x}} | <input type="text"> según el tipo de columna |
{{textarea campo_x}} | <textarea> |
{{file campo_x}} | <input type="file"> para subir archivo/imagen |
{{submit "Enviar"}} | Botón de envío con el texto que le pases |
Ver Formularios públicos para el detalle.
¿Qué sigue?
- Galerías de imágenes — más detalle sobre
{{#imagenes}}. - Formularios públicos — captar datos del visitante.
- SEO y metadatos — para que Google encuentre tus páginas.