Skip to content
Code on GitHub (opens in a new tab)

Documentation · Get started

Quick reference

The commands, the structure of a project, the fields, the template functions and the shortcodes, on a single page, with the Spanish names explained.

Version 0.16

What you will need every day, without long explanations. Each section ends with a link to the detail in the format, which is only available in Spanish.

Names at a glance

The format is written in Spanish on purpose, so the names of the folders, the fields, the commands and the template functions are Spanish words. This table says what each one means.

Name Meaning
contenido/, datos/, plantillas/, parciales/, publico/, salida/ The folders: content (the pages), data, templates, partials, public (copied as is) and output (the built site).
sitio.yml, _datos.yml, .secretos.yml The site settings, the data a folder passes on to its pages, and the deployment secrets.
compilar, servir, desplegar The commands: build, serve (preview) and deploy.
titulo, subtitulo, descripcion, fecha The fields title, subtitle, description and date.
etiquetas, plantilla, borrador, listada, orden Tags, template, draft, listed and order.
imagen, imagenAlt, icono Image, its alternative text and icon.
publicar, agrupar, paginar Publish (a date), group (one page per value) and paginate (a list split into pages).
sí, no Yes and no.
pagina, sitio, datos The three variables of a template: the page, the site and the data.
coleccion, orden, limite, invertir, sin, donde, anterior, siguiente, activo Collection, sort, limit, reverse, without, where, previous, next and active.
imagen, video, archivo, dato The shortcodes: image, video, file and data value.

The English names that Eleventy and Lume use for seven fields (title, subtitle, description, date, tags, layout, permalink) are accepted as aliases, so that migrating does not mean rewriting the front matter. Everything else, folders and commands included, is Spanish only.

The commands

Command What it does
php ehundu.phar compilar [folder] Builds the project into its salida/ folder. Without a folder, the current one.
php ehundu.phar servir [folder] Previews it at http://127.0.0.1:8000/ and rebuilds only what changes.
php ehundu.phar desplegar [folder] Builds it and uploads it to the destination in sitio.yml.
--puerto=8000, --borradores, --completo Options of servir: the port, also show the drafts, rebuild everything on every change.
--simular, --todo Options of desplegar: say what it would do without doing it, or upload everything even if it has not changed.
--ayuda, --version The help and the version.

With Composer, vendor/bin/ehundu instead of php ehundu.phar.

A project

my-site/
  sitio.yml          settings: nombre and url are required
  contenido/         pages (.md and .twig) and files that are copied as they are
    _datos.yml       data that the pages in the folder inherit
  datos/             global data: datos.<name> in the templates
  plantillas/        layouts; pagina.twig is the default one
  parciales/         fragments with {% include %}; parciales/atajos/ for the shortcodes
  publico/           copied to the root of the site (CSS, images, favicon)
  .secretos.yml      deployment passwords; not versioned
  salida/  .ehundu/  generated by the engine; not versioned

Detail (in Spanish): the structure of a project.

sitio.yml

Key What it is for
nombre, url Required. The url is the domain, without a path: https://www.example.com.
idioma, idiomas The language of the site, or the list if there are several (es by default).
zonaHoraria Europe/Madrid. Dates are read and written in it.
feed Asks for a feed.xml: feed: { coleccion: blog }.
encabezados Gives an id, and a permanent link if you want, to the headings in Markdown.
imagenes The widths and formats of the image variants, for srcset.
enlacesExternos How the links to other domains that you write in Markdown come out.
generador generador: no removes the generator tag from the pages.
despliegue Where it is published (below).

Detail (in Spanish): sitio.yml.

The front matter of a page

What you write between the two lines of dashes at the start of a .md. These fields have a special meaning; any other one reaches the template as it is.

Field What it is for
titulo, subtitulo, descripcion The title, the standfirst and the description for search engines.
fecha A day, 2026-10-15. It orders the collections and appears in the feed.
url The address of the page, or a pattern. If missing, it comes from the path of the file. false: it generates no file.
plantilla The layout, without folder or extension. false: no layout.
etiquetas The collections it belongs to: [blog, novedades].
listada no: it is published, but does not appear in collections or in the sitemap.
css, js Files in publico/ that this page needs.
imagen, imagenAlt, icono Main image, its alternative text and an SVG icon.
orden A number, to order by hand within a collection.
borrador sí: it is not published.
publicar It is not published before that date.
publicarEnSuFecha sí: it is not published before its fecha. It goes in the _datos.yml of a blog.
pdf sí: the page also comes out as a PDF.
agrupar, paginar One page for each value of a field, or a list split into pages (below).

The yes-or-no fields accept sí, no, true and false, but only the ones in this table: in a field of your own, sí and no are text, and for a true or a false you write true or false (more in Templates and shortcodes). The English names from Eleventy and Lume (title, date, tags, layout, permalink) work as aliases. Detail (in Spanish): reserved fields.

Addresses

contenido/servicios/diseno.md   →  /servicios/diseno/
contenido/servicios/index.md    →  /servicios/
contenido/404.md with url: /404.html   →  /404.html

A pattern uses fields of the page itself and the slug filter:

url: "/blog/{{ titulo|slug }}/"
url: "/{{ nombreDeFichero }}/"

Detail (in Spanish): URL.

Data and inheritance

A file in datos/ is available in the templates under its name: datos/cliente.yml is datos.cliente. A _datos.yml inside a folder of contenido/ is inherited by all its pages; the value closest to the file wins, except etiquetas, css and js, which are added together.

# contenido/blog/_datos.yml
plantilla: articulo
etiquetas: [blog]
url: "/blog/{{ titulo|slug }}/"

Detail (in Spanish): data.

Templates

Templates are Twig. They are named by their path from the root of the project.

{% extends 'plantillas/base.twig' %}
{% include 'parciales/cabecera.twig' %}
{% block cuerpo %}{{ pagina.contenido }}{% endblock %}

Three variables: sitio (what is in sitio.yml), datos (the files in datos/) and pagina (the fields of the page, plus pagina.url, pagina.contenido, pagina.idioma, pagina.traducciones and pagina.encabezados).

{{ coleccion('blog') }}              {# the pages with that tag, from the oldest to the newest #}
{{ lista|orden('fecha desc') }}      {# sorts by one or more fields: 'orden, titulo' #}
{{ lista|limite(6) }}                {# the first six #}
{{ lista|invertir }}                 {# reverses the list #}
{{ lista|sin(pagina) }}              {# removes a page, usually the current one #}
{{ lista|donde('etiquetas', 'x') }}  {# the ones with that value in that field #}
{{ lista|anterior(pagina) }}         {# the previous page, or siguiente(pagina) #}
{{ titulo|slug }}                    {# a text turned into a piece of address #}
{{ pagina.fecha|fecha('j F Y') }}    {# a date with the months in the language of the page #}
{{ campo|markdown }}                 {# formatted text, converted to HTML #}
{{ svg('img/logo.svg') }}            {# embeds an SVG from publico/ #}
{{ dimensiones('img/foto.jpg') }}    {# gives the width and the height of an image #}
{{ activo('/blog/') }}               {# am I on that page or inside it? #}
{{ version('css/estilo.css') }}      {# the address with a fingerprint, so that it is cached #}
{{ css('css/base.css') }}            {# declares CSS; {{ css() }} writes it all where you put it #}
{{ js('js/app.js') }}                {# the same with JavaScript; also css_fichero() and js_fichero() #}

Detail (in Spanish): templates and collections.

Markdown and shortcodes

Ordinary Markdown, plus tables, footnotes, strikethrough and automatic links. A link to another domain opens in another tab. Shortcodes are what Markdown lacks, with no logic in the text:

Shortcode What it gives
[imagen fichero="img/foto.jpg" alt="…" pie="…"] A figure with its caption and its dimensions.
[video url="https://www.youtube.com/watch?v=…" titulo="…"] A YouTube or Vimeo video, or one from publico/ with fichero.
[archivo fichero="docs/tarifas.pdf" texto="Prices"] A link with the type and the size of the file.
[dato clave="cliente.nombre"] A value from datos/.

The shortcodes you define yourself can wrap text, with the opening ([aviso tipo="importante"]) and the closing ([/aviso]) each on its own line. To change the HTML of a shortcode, or to create one, write parciales/atajos/<name>.twig. Detail (in Spanish): Markdown and shortcodes.

One page for each value, and split lists

# contenido/etiqueta.md: one page for each tag of the posts
agrupar:
  coleccion: blog
  campo: etiquetas
  excluir: [blog]
url: "/etiqueta/{{ grupo|slug }}/"
# contenido/blog/index.md: the listing, ten at a time
paginar:
  coleccion: blog
  porPagina: 10
  orden: fecha desc

In the template, pagina.paginas are the pages of the group or of the chunk, and pagina.paginacion brings actual, total, entradas, anterior, siguiente and enlaces (current, total, entries, previous, next and links). Detail (in Spanish): group and paginate.

Several languages

# sitio.yml: the first one is the default
idiomas:
  - codigo: es
    nombre: Castellano
  - codigo: eu
    nombre: Euskara

The language goes in the name of the file: contacto.md is in Spanish and contacto.eu.md, in Basque. Data follows the same rule (menus.eu.yml). Templates have pagina.traducciones and sitio.idiomas to write the language selector. Detail (in Spanish): multilingual sites.

Drafts and scheduled publication

borrador: sí does not publish the page. publicar: 2026-12-01 publishes it that day, and publicarEnSuFecha: sí makes no page in the folder come out before its fecha. It is a static site: it comes out when you build again after that date. With servir --borradores you see everything.

Deployment

Destination Fields of despliegue
carpeta ruta: a folder on your machine, outside the project.
ftp servidor, usuario, ruta, and puerto or cifrado: no if needed.
sftp servidor, usuario, ruta and huella (the fingerprint of the server's key).
s3 servidor, region, cubo, usuario and ruta.

Secrets go in .secretos.yml, never in sitio.yml: clave (the password, or clavePrivada, the path of a key file) and frase (the passphrase). Ehundu records what it uploads in a .ehundu.json file at the destination, and only deletes what it uploaded itself. Detail (in Spanish): deployment.