Manuel · 10

Pages dynamiques (Catch-All)

Vous voulez une liste sous /blog et l’article sous /blog/mein-artikel – sans créer une page distincte pour chaque article ? C’est à cela que sert Catch-All.

  1. Créer la page /blog et cocher Catch-All sous Paramètres.
  2. Dans la Collection blog, créer un champ slug (la partie d’URL de chaque article).
  3. HTML de la page /blog :
{% if route.slug %}
  {% with post=item("blog", "slug", route.slug) %}
    {% if not post %}{{ not_found() }}{% endif %}
    <article>
      <h1>{{ post.titel }}</h1>
      <p class="datum">{{ post.datum }}</p>
      {{ image(post.bild, "(min-width: 900px) 60vw, 100vw") }}
      {{ post.text|markdown }}
      <a href="/blog">← Alle Artikel</a>
    </article>
  {% endwith %}
{% else %}
  <h1>Blog</h1>
  {% for post in data("blog", "sort", "-datum") %}
    <a class="teaser" href="/blog/{{ post.slug }}">
      <h2>{{ post.titel }}</h2>
      <p>{{ post.text|truncatechars:160 }}</p>
    </a>
  {% endfor %}
{% endif %}
  1. Titre SEO de la page :
{% if route.slug %}{{ item("blog", "slug", route.slug).titel }} – {% endif %}Blog

Voici comment cela fonctionne :

  • /blog → route.slug est vide → liste.
  • /blog/mein-artikel → il n’existe pas de page mein-artikel → la page Catch-All répond avec route.slug = "mein-artikel".
  • /blog/gibts-nicht → item() ne trouve rien → not_found() renvoie la page 404 avec le statut 404.
  • Les vraies sous-pages sont prioritaires : si vous créez /blog/archiv comme page normale, c’est elle qui s’affiche.
  • Chemins à plusieurs niveaux : /blog/2025/rueckblick donne route.slug = "2025/rueckblick", route.rest.0 = "2025", route.rest.1 = "rueckblick".

Pour les tests, l’aperçu des pages Catch-All dispose du champ Sous-chemin. Si le template appelle not_found() (p. ex. sans sous-chemin), l’aperçu affiche, au lieu d’une erreur, une remarque avec des sous-chemins existants – issus de la source du sitemap ou de la Collection détectée.

Sitemap : si le HTML, le titre SEO ou le champ Head de la page Catch-All contient item("<collection>", "<feld>", route.slug), IllusionCMS inclut toutes les entrées publiées de cette Collection comme pages de détail dans /sitemap.xml (pas les brouillons ni les entrées sans valeur dans le champ). Les vraies sous-pages sont prioritaires.

Pages de détail issues d’autres sources : si la page lit ses données autrement – depuis IllusionDB, une source REST ou via un Workflow –, définissez la source dans les Paramètres de la page Catch-All, sous Pages de détail pour le sitemap et l’export statique :

  • Table IllusionDB : connexion, table, la colonne contenant la partie d’URL (p. ex. slug), éventuellement une colonne avec la date de modification (<lastmod>) et des règles ou une vue enregistrée comme filtre – p. ex. uniquement aktiv = true.
  • Workflow : l’entrée HTTP d’un Workflow (comme pour workflow()) qui renvoie une liste – des objets avec le champ d’URL ou simplement des textes. Il reçoit sitemap=1 dans msg.payload. Ainsi, les sources REST et les listes calculées arrivent elles aussi dans le sitemap.
  • Vérifier indique combien de pages de détail en résultent, ainsi que les premières adresses. Les valeurs contenant / donnent des chemins à plusieurs niveaux (berlin/zahnarzt → /leistungen/berlin/zahnarzt).
  • Depuis IllusionDB, seules la colonne contenant la partie d’URL et la date sont interrogées.
  • La liste est mise en cache pendant 10 minutes. Si la source est momentanément inaccessible, le dernier état reste dans le sitemap, au lieu que des milliers d’adresses disparaissent.
  • À partir de 50 000 adresses, /sitemap.xml devient automatiquement un index de sitemaps avec /sitemap-1.xml, /sitemap-2.xml, … (limite des moteurs de recherche par fichier).
  • L’export statique inclut les mêmes pages de détail – même si aucun lien n’y mène.

Données depuis IllusionDB : les pages de détail peuvent aussi récupérer leurs enregistrements directement dans une base de données – via un Workflow avec le node IllusionDB, voir Workflows → IllusionDB.