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

Version 1.1 (opens in a new tab) · first stable release

Weave static sites with PHP.

Ehundu turns Markdown, YAML data and Twig templates into a plain HTML site. From the terminal or from a web process, on any hosting that runs PHP.

Get started See the code (opens in a new tab)

composer require ehundu/ehundu


How it works

A folder goes in, a site comes out.

  1. Write

    Every page is a Markdown file with a short front matter. What all the pages in a folder share, such as their tag or their URL pattern, is written once in its _datos.yml.

    structure
    mi-sitio/
      sitio.yml
      contenido/
        index.md
        blog/
          _datos.yml
          primer-articulo.md
      plantillas/
        pagina.twig
      publico/
        img/
          portada.jpg
  2. Compose

    Templates are Twig, with collections and dates in each page's language. Shortcodes insert images, videos or documents without writing HTML in the text.

    blog/primer-articulo.md
    ---
    titulo: Primer artículo
    fecha: 2026-10-01
    ---
    
    Texto del artículo en **Markdown**.
    
    [imagen fichero="img/portada.jpg" alt="La portada"]
  3. Publish

    One command builds the site as plain HTML and another uploads it to a folder, over FTP or SFTP, or to any S3-compatible storage. Only what has changed is uploaded.

    terminal
    $ ehundu compilar mi-sitioCompilado: 2 páginas y 1 fichero en 0,09 s. $ ehundu desplegar mi-sitioCompilado: 2 páginas y 1 fichero en 0,07 s.  subido    img/portada.jpg  subido    blog/primer-articulo/index.html  subido    index.html  subido    sitemap.xmlDesplegado en sftp://yo@ejemplo.com/www: 4 ficheros (16 kB) subidos en 0,62 s.

Starters

Begin with the structure already built.

Eight Ehundu projects with their folders, templates and CSS already done, to copy and change: a minimal site, a blog, documentation, a portfolio, a local business, a website in Spanish and Basque, the one for an event and a CV. Each has its own page and its live demo, so you can see it working before downloading anything. The example texts are in Spanish.

See the starters

What sets it apart

It also builds from the web.

The usual generators are designed for the command line. In Ehundu, the command is a thin layer over a library, and a PHP program can use that same library to build the site within a web request, on ordinary shared hosting.

So an editing tool can save a change and publish the site right away. And whoever prefers their text editor gets exactly the same result from the terminal. Errors and warnings point to the file and the line, ready to be shown as they are (for now, in Spanish).

publicar.php
use Ehundu\CompiladorEnProceso;
use Ehundu\Proyecto;

$proyecto = Proyecto::abrir('/ruta/a/mi-sitio');
$informe = (new CompiladorEnProceso())->compilar($proyecto);

echo $informe->resumen();
// Compilado: 2 páginas y 1 fichero en 0,09 s.

foreach ($informe->avisos as $aviso) {
    echo $aviso; // con su fichero y su línea
}

Principles

Few pieces, all yours.

  • Plain PHP

    It runs on PHP 8.4 or later and needs no external programs or unusual extensions. If a hosting runs PHP, it can run Ehundu.

  • Your content is files

    Markdown, YAML, templates and static files. No database and no hidden state; a folder copied to another machine builds the same.

  • No service lock-in

    It relies on free software that can be kept and maintained, never on services whose terms can change overnight. It publishes without any provider's own API.

  • In Spanish

    Folders are called contenido, plantillas or publico, and fields titulo, fecha or etiquetas. The usual English field names are accepted, to make migrating from Eleventy or Lume easier.


Nidel, a tan dog with pointed ears and his tongue out, with the thread of a needle tied to his red collar.

The name

A needle in a haystack.

Ehundu is Basque for “to weave”. That is no accident: a web is literally a woven fabric, and a site generator does just that, interlacing content and templates until they form pages.

It is pronounced roughly “eh-OON-doo”.

The needle in the logo has a name too. Nidel was in a haystack the day I adopted him, and the name sounds like needle. It was, quite literally, finding a needle in a haystack.

Project status

Thread by thread.

Ehundu already builds, previews and publishes real sites, multilingual ones included. Since 1.0 the contract is a promise and not a draft, and every decision is recorded, with its reason, in the decision log (opens in a new tab). The documentation is in Spanish, like the format.

Now

Version 1.1

It promises the format (formato: 1), the console command and a short list of the PHP library. Within version 1 it only grows.

Writing

  • Markdown, data and Twig templates, with shortcodes
  • One page for each tag
  • Long listings split into pages
  • Pages in a folder served without the folder in the URL
  • id and permalink on headings
  • An alphabetical order that ignores ¿ and ¡

Languages and output

  • Multilingual sites, with a feed title for each language
  • PDF for the pages that ask for it
  • srcset for images that come in several widths
  • The width variants of images, with the ehundu imagenes command
  • Each page's CSS and JavaScript in a file named after a hash of its contents
  • A notice for screen readers on links that open a new tab
  • A generator tag on the pages

Publishing

  • A preview that rebuilds only what changes
  • Deployment to a folder, over FTP or SFTP or to S3
  • Entries that go live on their date and are withdrawn when their time is up

Inside a web process

  • Builds and uploads spread over several calls, for processes with a time limit
  • An incremental build that remembers what it did between one process and the next

Next

Version 1.x

Whatever is added within version 1 will be additive, by rule 5 of the contract. A project written today will build the same tomorrow, and anything that is about to stop working is announced for a minor version before it is removed.

Later

What grows

Components with parameters, cropping images to a proportion, and search. The format already leaves room for all of them, and they can arrive within version 1 because it only grows.