Rezepte
Hauptmenü mit aktivem Punkt
Snippet navigation:
<nav class="hauptmenue">
<a href="/" {% if page.path == "/" %}aria-current="page"{% endif %}>Start</a>
{% for p in nav() %}
<a href="{{ p.path }}" {% if p.path == page.path %}aria-current="page"{% endif %}>{{ p.title }}</a>
{% endfor %}
</nav>
Die Reihenfolge entspricht dem Seitenbaum, Entwürfe erscheinen nicht. Im CSS: .hauptmenue [aria-current] { font-weight: 700; }.
Untermenü einer Rubrik
{% for p in children() %}
<a href="{{ p.path }}">{{ p.title }}</a>
{% endfor %}
Team-Seite aus einer Collection
Collection team mit name, rolle, foto (Bild), text (Markdown), dazu eine Komponente person:
{# Snippet "person" #}
<figure class="person">
{{ image(foto, "(min-width: 800px) 25vw, 50vw") }}
<figcaption><strong>{{ name }}</strong><br>{{ rolle }}</figcaption>
{% slot %}{% endslot %}
</figure>
<div class="team">
{% for p in data("team") %}
{% component "person" name=p.name rolle=p.rolle foto=p.foto %}{{ p.text|markdown }}{% endcomponent %}
{% empty %}
<p>Das Team stellt sich bald vor.</p>
{% endfor %}
</div>
Produkte aus einem Shop
REST-Quelle produkte: URL https://shop.example.com/api/products?category={kat}&limit=12, Header Authorization: Bearer {env.SHOP_TOKEN}, Listen-Pfad data.items, Cache 600.
<form>
<select name="kat" onchange="this.form.submit()">
<option value="">Alle</option>
<option value="schuhe" {% if route.query.kat == "schuhe" %}selected{% endif %}>Schuhe</option>
</select>
</form>
{% for p in data("produkte", "kat", route.query.kat) %}
<article>
<img src="{{ p.image_url }}" alt="{{ p.name }}" loading="lazy">
<h3>{{ p.name }}</h3>
<p>{{ p.price|floatformat:2 }} €</p>
</article>
{% endfor %}
Jede Kategorie ist ein eigener Cache-Eintrag – sowohl beim REST-Abruf als auch im Seiten-Cache.
Nur kommende Termine
Mit today und einem Datumsvergleich verschwinden vergangene Einträge von selbst – ohne sie zu löschen:
{% for e in data("events", "datum__gte", today, "sort", "datum") %}
<h3>{{ e.titel }}</h3>
<p>{{ e.datum|slice:"8:10" }}.{{ e.datum|slice:"5:7" }}.{{ e.datum|slice:"0:4" }}</p>
{% empty %}
<p>Aktuell sind keine Termine geplant.</p>
{% endfor %}
Ein Archiv zeigt dieselbe Collection mit "datum__lt", today, "sort", "-datum".
Blätternde Liste
Rechnen ist direkt in Ausdrücken möglich (seite - 1, (seite - 1) * 10); |integer macht aus dem Query-Parameter eine Zahl.
{% with seite=route.query.seite|default:"1"|integer %}
{% for post in data("blog", "sort", "-datum", "limit", 10, "offset", (seite - 1) * 10) %}
…
{% endfor %}
{% if seite > 1 %}<a href="?seite={{ seite - 1 }}">Neuer</a>{% endif %}
<a href="?seite={{ seite + 1 }}">Älter</a>
{% endwith %}
Seitenbaukasten aus Blöcken
Am bequemsten geht das mit dem eingebauten Seitenbaukasten aus Bausteinen und {% blocks page.blocks %} (siehe 7.6). Ohne Schema klappt es auch mit einer Collection: Collection bloecke mit seite (Text), typ (Auswahl: text, bild, zitat), inhalt (Markdown), bild (Bild). Für jeden Typ ein Snippet block/text, block/bild, block/zitat, die ihre Parameter verwenden. Auf der Seite:
{% for b in data("bloecke", "seite", page.slug) %}
{% component "block/"|add:b.typ inhalt=b.inhalt|markdown bild=b.bild %}{% endcomponent %}
{% endfor %}
JSON für JavaScript bereitstellen
<script>
const termine = {{ data("termine", "sort", "datum")|json }};
</script>
Mehrsprachigkeit
Alles Wichtige steht unter Mehrsprachige Websites: Sprache am Seitenbaum setzen (vererbt sich), Fassungen verknüpfen, hreflang und Sitemap kommen automatisch, den Sprachumschalter baust du mit translations(), das Menü je Sprache mit children(lang_root().id).
Kontaktformulare
IllusionCMS verarbeitet keine Formulare selbst. Verwende einen Formular-Dienst oder eine eigene API als action-Ziel und binde dessen Skript als JS-Datei ein.