German (Deutsch) translation by Francesco Schwarz (you can also view the original English article)
Vor einigen Wochen bin ich über einen Artikel von A List Apart mit dem Titel „Managing Your Content Management System“ gestolpert. Darin werden Ratschläge gegeben wie man die Freiheit des Nutzers im Backend eines Content Management Systems (CMS) beschränken und maßschneidern sollte, um es so einfach bedienbar wie möglich zu machen.
Wenn ich mir die Ratschläge durchlese und sie mit den technischen Möglichkeiten der großen Akteure in der CMS-Landschaft vergleiche, sehe ich viele Einschränkungen. Die meisten dieser CMS haben schlicht und ergreifend nicht diese Art von Fähigkeiten und können nicht die Optionsvielfalt bieten um ein User Interface im Backend ideal maßzuschneidern. Aber nachdem ich seit mehreren Jahren mit ProcessWire gearbeitet habe, habe ich glaube ich den heiligen Gral für Entwickler und Nutzer gefunden, die genau das möchten.



ProcessWire ist ein aufstrebendes, kostenloses, open source PHP CMS und Content Management Framework (CMF). Es basiert auf einigen wenigen Konzepten und bietet Tools an, die einfach zu benutzen und gleichzeitig mächtig sind. In diesem Übersichtsartikel möchte ich dir einige dieser Tools und Konzepte vorstellen. Hier sind vier Gründe warum du dich für ProcessWire als dein nächstes CMS entscheiden solltest.
1. Es basiert auf drei einfachen Kernkonzepten: Seiten, Felder und Templates
Die Eingabe und Ausgabe von Daten basiert auf nur drei Kernkonzepten, und sonst auf nichts. Das bedeutet ganz konkret, dass du, sobald du diese Konzepte verstehst, quasi alles über ProcessWire und der Philosophie dahinter verstehst. Ziemlich cool, oder? Los geht’s mit Seiten, Feldern und Templates.
Seiten
Auf der Startseite deiner ProcessWire-Installation siehst du einen einzelnen, hierarchischen Seitenbaum:



Die Links im Seitenbaum heißen Seiten. Seiten im Backend haben üblicherweise eine direkte Entsprechung im Frontend. Beispielsweise ist die „About“-Seite im Screenshot im Frontend erreichbar unter der URL your-domain.com/about/
.
Aber Seiten müssen nicht unbedingt ein Gegenstück im Frontend haben. Sie können auch einfach nur im Backend existieren und als Datencontainer für andere Seiten dienen. Lass dir den Satz, den du gerade gelesen hast, nochmal durch den Kopf gehen: Das Konzept von nur im Backend vorhandenen Seiten ist ziemlich mächtig, da es vielfältige Möglichkeiten eröffnet wie du deine Website strukturieren und mit eingegeben Daten interagieren kannst.
Du kannst – und solltest – Seiten für fast alles verwenden. Beispielsweise kannst du eine versteckte Seite für Einstellungen erstellen, wo sich Dinge wie die Hauptnavigation oder generelle Texte wie Name, Slogan, Copyright-Hinweis, etc. deiner Website befinden. Ein anderes Beispiel sind Schlagworte und Kategorien von Blogartikeln (ähnlich wie Taxonomien in WordPress). Du erstellst einfach Seiten für jedes einzelne Schlagwort oder jede Kategorie eines Blogartikels. Hier lasse ich gerne Joss Sanglier bezüglich Seiten in ProcessWire zu Wort kommen:
Pages in ProcessWire are used for all kinds of things. They can be used as a marker in your pages list. They can be used as a group parent for other pages. They can be used as categories, tags or lists or users. And they can even be used for simple drop-down selects – just to supply a label and value.
Öffnen und bearbeiten wir jetzt die zuvor erwähnte „About“-Seite.



Du blickst nun auf das nächste Kernkonzept von ProcessWire: Felder.
Felder
Seiten beinhalten Felder. Aber Felder müssen von zwei unterschiedlichen Blickwinkeln betrachtet werden. Optisch sind sie Teil der Seite, weil du nach dem Öffnen einer Seite Felder siehst, mit denen du arbeiten kannst. Technisch sind diese Felder allerdings Teil des Templates der Seite. Ich werde das Konzept von Templates später beschreiben; lasst uns erst Felder verstehen.
Felder in ProcessWire sind die Container in denen du Daten eingibst oder auswählst, wie z.B. Text, Textareas, Zahlen, E-Mails, Dateiuploads, andere Seiten, etc. Es liegt voll und ganz in deiner Hand wie viele Felder eine Seite hat. Es kann einfach nur ein Feld haben (z.B. ein Feld für den Seitentitel) oder gar kein Feld (nicht sehr praktisch) oder mehr als 50 oder 100 Felder.
ProcessWire hat eigentlich kein spezielles Konzept von Custom Fields wie in WordPress, weil jedes Feld in ProcessWire ein Custom Field ist. Du erstellst ein Feld und entscheidest von welchem Typ das Feld ist (siehe Screenshot unten). Das war’s!



Du kannst einem Feld ein Label, eine Beschreibung und zusätzliche Hinweise geben (die Hinweise erscheinen dezent unterhalb vom Feld). Jeder Feldtyp hat eigene, spezifische Einstellungen. Sehen wir uns drei Feldtypen mit deren Einstellungsmöglichkeiten an, um ein Gefühl dafür zu bekommen:
- Feldtyp Textarea: Du entscheidest, ob die Textarea als simple Textarea gerendert wird oder als WYSIWYG-Variante (standardmäßig CKEditor). Du entscheidest, welche Buttons in der CKEditor-Toolbar erscheinen und du kannst direkt in der Admin-GUI spezifische Einstellungen für Eingabeoptionen vornehmen.
- Feldtyp Seite: Du kannst eine Seite mit einer anderen verknüpfen und somit eine Beziehung zwischen den Seiten herstellen. Du kannst entweder eine Seite (Eins-zu-Eins-Beziehung) oder mehrere Seiten (Eins-zu-Viele-Beziehung) auswählen. Du kannst sogar neue Seiten direkt im Feld erzeugen.
- Feldtyp Bild: Du kannst einstellen, welche Bild-Typen (Dateiendungen) hochgeladen werden dürfen. Du kannst die minimale und/oder maximale Höhe und Breite bestimmen, die für das Hochladen eines Bilds gegeben sein müssen.
Am Ende läuft es auf folgendes hinaus: jedes Feld dass du erzeugst ist hochgradig anpassbar um genau die Bedürfnisse abzudecken, die du als Entwickler und die Menschen, die später die Inhalte kreieren und eingeben, haben.
Aber wie weiß eine Seite eigentlich, welche Felder sie selbst hat? Wir gehen zum nächsten Konzept, den Templates.
Templates
Wenn du eine neue Seite in ProcessWire erzeugst, musst du immer auch ein Template auswählen. Das Template beinhaltet alle Informationen die eine Seite benötigt um zu wissen was für Felder sie hat, wie diese Felder auf der Seite gerendert werden und wie sie sich verhalten sollen.
Unten siehst du die Felder des Templates basic-page
.



Wenn du auf einen Feldeintrag klickst öffnet sich ein Fenster, wo du verschiedene Dinge einstellen kannst, die das Feld in genau diesem Template betreffen.



Ein Template kann eine physische PHP-Datei mit dem selben Namen haben. Diese Templatedateien befinden sich unter /site/templates/
. In so eine Datei schreibst du den PHP-Code und das HTML-Markup, das letztendlich die Seiteninhalte ausgibt und die Elemente rendert, die die Besucher sehen, wenn sie auf diese Seite deiner Website gehen.
Wenn keine Templatedatei mit demselben Namen wie das Template existiert, kann eine mit diesem Template verbundene Seite nicht von sich aus im Frontend gerendert werden. Das bedeutet nicht, dass du dir nicht die Inhalte der Seite holen kannst um sie woanders auszugeben – das kannst du indem du eine existierende Templatedatei einer anderen Seite verwendest.
Lasst uns die technische Beziehung zwischen Seiten, Feldern und Templates nochmal zusammenfassen: Du fügst einem Template Felder hinzu und du wählst ein Template aus, wenn du neue Seiten erzeugst. Die Felder die du siehst, wenn du eine Seite bearbeitest sind die Felder, die du dem ausgewählten Template ursprünglich hinzugefügt hast.
2. Es hat eine API zum Verlieben
Der Code in den Templatedateien besteht meistens aus einfachen PHP-Konstrukten wie z.B. if
-Anweisungen, foreach
-Schleifen und HTML-Markup einerseits, und andererseits arbeitest du mit der API von ProcessWire.
Die API kann man als jQuery für PHP bezeichnen. Es bietet Methoden, Selektoren und Möglichkeiten zur Verkettung (fluent interface) und Traversierung an.
Die API ist wahrscheinlich die eine Sache in ProcessWire, die mich am meisten begeistert: sie ist gleichzeitig einfach zu nutzen, einfach zu verstehen, ausdrucksstark und mächtig. Aber am allerwichtigsten ist, dass man mit ihr einfach und unkompliziert arbeiten kann und du hast tatsächlich Spaß mit ihr zu interagieren. Es macht einfach Sinn.
Das API-Cheatsheet ist eine gute Referenz. Es listet alle verfügbaren Methoden auf.



Lass mich dir jetzt zwei Variablen vorstellen die die API bereitstellt und mit denen zu während der Templateentwicklung am meisten nutzen wirst: $page
und $pages
.
Die $page-Variable
Die $page
-Variable beinhaltet alle Felder, die einer gerade angezeigten Seite gehören. Das schließt sowohl interne Felder ein, die jeder Seite zur Verfügung stehen, als auch Felder, die nur dieser einen Seite hinzugefügt wurden.
Aber wie kannst du Felder einer Seite ansprechen? Die folgenden einfachen Beispiele sollten dir einen ersten Eindruck vermitteln.
Zeige den Inhalt des Textfelds title
an:
1 |
echo $page->get("title"); |
2 |
// or
|
3 |
echo $page->title; |
Zeigen den Namen des Templates der Seite an:
1 |
echo "This page is using the template: " . $page->template->name; |
2 |
// or
|
3 |
echo "This page is using the template: {$page->template->name}"; |
Erzeuge eine Brotkrumennavigation:
1 |
echo "<ul>"; |
2 |
foreach ($page->parents as $parent) |
3 |
echo "<li><a href='{$parent->url}'>{$parent->title}</a></li>"; |
4 |
echo "</ul>"; |
Seit Version 2.5.27 kann man das obere Beispiel auch so schreiben:
1 |
echo "<ul>"; |
2 |
echo $page->parents->each("<li><a href='{url}'>{title}</a></li>"); |
3 |
echo "</ul>"; |
Zeige ein Bild an, und zwar nur falls es tatsächlich hochgeladen wurde:
1 |
if ($page->image) echo "<img src='{$page->image->url}'>"; |
Hinweis: Damit das obere Beispiel so funktioniert, musst du in den Einstellungen des Bildfelds angeben, dass nur maximal ein Bild hochgeladen werden darf.
Im Folgenden einige Beispiele, wenn in einem Bildfeld mehrere Bilder hochgeladen werden dürfen.
Hole dir das erste Bild und zeige es an:
1 |
$image = $page->images->first(); |
2 |
|
3 |
if ($image) echo "<img src='{$image->url}'>"; |
Hole dir ein zufälliges Bild und zeige es an:
1 |
$image = $page->images->getRandom(); |
2 |
|
3 |
if ($image) echo "<img src='{$image->url}'>"; |
Iteriere durch alle Bilder, erzeuge ein großes Bild mit 500 Pixel Breite und proportionaler Höhe, ein Vorschaubild mit den Maßen 100×100 und bestimmten Qualitäts- und Zuschneideinformationen und verlinke vom Vorschaubild zur großen Bildvariante:
1 |
$options = array( |
2 |
"quality" => 90, |
3 |
"cropping" => "southeast" |
4 |
);
|
5 |
|
6 |
foreach ($page->images as $image) { |
7 |
$large = $image->width(500); |
8 |
$thumb = $image->size(100, 100, $options); |
9 |
echo "<a href='{$large->url}'><img src='{$thumb->url}'></a>"; |
10 |
}
|
Hinweis: ProcessWire erstellt selbständig Bilder jedweder Größe und legt einen Cache für jedes Bild an.
Die $pages-Variable
Die $pages
-Variable ist eine Referenz auf alle Seiten deiner ProcessWire-Installation. Das ermöglicht dir den Zugang zu allen Inhalten und Seiten von überall.
Für die nächsten Beispiele möchte ich auf die Standard-Demoseite von ProcessWire verweisen, eine Sammlung von Hochhäusern in den Vereinigten Staaten.
Hole dir eine bestimmte Seite und zeige den Titel an:
1 |
echo $pages->get("/cities/chicago/sears-tower/")->title; |
Hinweis: /cities/chicago/sears-tower/
ist der komplette Pfad der zur Sears-Tower-Seite im hierarchischen ProcessWire-Seitenbaum zeigt.
Finde alle Hochhäuser mit einer Höhe größer als 500 Fuß und kleiner oder gleich 1.000 Fuß:
1 |
$skyscrapers = $pages->find("template=skyscraper, height>500, height<=1000"); |
Hinweis: height
ist ein Feld das dem Template skyscraper
zugewiesen ist.
Finde alle vor 1950 erbauten Hochhäuser mit 10+ Stockwerken, absteigend sortiert nach Erbauungsjahr, dann absteigend sortiert nach Anzahl der Stockwerke:
1 |
$skyscrapers = $pages->find("template=skyscraper, year<1950, floors>=10, sort=-year, sort=-floors"); |
Hinweis: year
und floors
sind Felder die dem Template skyscraper
zugewiesen sind.
Finde alle Hochhäuser in Chicago mit 60+ Stockwerken, aufsteigend sortiert nach Anzahl der Stockwerke:
1 |
$skyscrapers = $pages->get("/cities/chicago/")->find("floors>=60, sort=floors"); |
Finde alle Hochhäuser der Architekten David Childs oder Renzo Piano, absteigend sortiert nach Höhe.
1 |
$david = $pages->get("/architects/david-childs/"); |
2 |
$renzo = $pages->get("/architects/renzo-piano/"); |
3 |
$skyscrapers = $pages->find("template=skyscraper, architects=$david|$renzo, sort=-height"); |
Hinweis: architects
ist ein Feld das dem Template skyscraper
zugewiesen ist.
3. Es ist auf einer modularen und einfach erweiterbaren Architektur aufgebaut
ProcessWire selbst besteht aus einem schlanken Kern-Framework (das ist quasi die Essenz von ProcessWire, die die Basis-Funktionalitäten ermöglicht) und eine Menge an vorgepackten Modulen, die bei jeder Installation mit dabei sind. Manche dieser Kernmodule sind bereits vorinstalliert, und manche sind standardmäßig nicht vor installiert. Module in ProcessWire sind wie Plugins in WordPress: Sie erweitern das System und passen es an.
Die modulare Natur von ProcessWire hat einige schöne Vorteile:
- Die Codebasis ist wartbarer weil Kernfunktionalitäten von anderen Teilen des Systems isoliert und entkoppelt sind. Das hat auch positive Nebeneffekte in Sachen Sicherheit.
- Es ist einfacher neue Features zu entwickeln und Fehler im Code können sehr viel schneller und effektiver ausgemacht und verbessert werden.
- Upgrades zu neueren ProcessWire-Versionen oder einzelnen Modulen sind üblicherweise problemlos möglich und ohne Magenschmerzen verbunden, d.h. du musst dir keine Sorgen machen, dass nach einem Upgrade alles kaputt ist.
Module installieren
Module zu installieren ist sehr einfach. Ziehe einfach den Ordner des Modules bzw. die Dateien des Modules in den /site/modules/
-Ordner und klicke auf Installieren in der Admin-GUI. Aber es gibt tatsächlich noch andere Wege Module vom Modules Directory zu installieren.
Beispielsweise kannst du den Modules Manager installieren, der es dir ermöglicht Module direkt in der Admin-GUI zu durchsuchen, herunterzuladen und zu installieren.
Modul-Anzahl: Qualität vor Quantität
Zum Zeitpunkt des Schreibens des Artikels gibt es ca. 370 Module für ProcessWire. Der Vergleich zu den ca. 40.500 WordPress-Plugins ist interessant und aufschlussreich. Man kann davon einige Dinge ableiten, die die allgemeine Natur von ProcessWire und den Modulen betreffen, und wie sich das alles zu Plugins von anderen CMS verhält:
- ProcessWire ist nicht im Ansatz so populär und weit verbreitet wie WordPress, Joomla, Drupal und andere.
- ProcessWire-Module sind überlicherweise qualitativ sehr hochwertig. Sie machen eine Sache und diese eine Sache machen sie gut.
- Der Kern von ProcessWire ist von sich aus so mächtig und flexibel, dass es schlicht und ergreifend nicht notwendig ist, ihn um sehr viele Module zu erweitern. Beispielsweise brauchst du keine Module um Bildergallerie-Slideshows zu erstellen, um die erste Kindsseite von einer Seite anzusprechen, um Vorschaubilder zu generieren, etc. Das alles (und noch viel mehr) deckt ProcessWire bereits in der Grundfunktionalität ab.
Hooks
Hooks sind ein eher fortgeschrittenes Thema, aber sie sind nichtsdestotrotz erwähnenswert und zeigen, dass die Funktionalität, die ProcessWire anbietet, sehr einfach änder- und erweiterbar ist. ProcessWire besitzt hunderte Methode, in die du dich einhängen kannst, um sie zu modifizieren und ihr Verhalten zu ändern.
Ein Beispiel: Wir haben uns ein einfaches Formular mithilfe der API oder des Form Builders gebaut und einige Felder sind im Backend von uns als benötigt markiert. Wir möchten nun auch das entsprechende HTML5-Markup für benötigte Felder im Frontend ausgeben. Mit ProcessWire geht das tatsächlich sehr einfach. Wir hängen uns in die Render-Methode von Inputfeldern ein und definieren, was wir tun möchten: Fragen, ob ein Felder benötigt wird, das gewünschte Frontend-Attribut hinzufügen und am Ende des Labels ein Sternchen hinzufügen.
1 |
$forms->addHookBefore("Inputfield::render", function ($event) { |
2 |
$field = $event->object; |
3 |
|
4 |
if ($field->required) { |
5 |
$field->attr("required", "required"); |
6 |
$field->label .= "*"; |
7 |
}
|
8 |
});
|
4. Es steht dir nicht im Weg und bietet dir Tools an, um maßgeschneiderte, nutzerfreundliche Interfaces zu schaffen
Eine Sache die ProcessWire definitiv auszeichnet: Es steht dir nicht im Weg. Es verhält sich so wie du möchtest und passt sich deinem Stil beim Entwickeln einer Website an.
Beispielsweise hast du volle Kontrolle über die Ausgabe des HTML-Codes und du wirst nicht gezwungen auf eine bestimmte Art und Weise deine Templates auf Dateisystemebene zu entwickeln. Wenn du mit dem WordPress-Stil Templates zu entwickeln vertraut bist, kannst du so weitermachen, wie du es schon immer gewohnt bist. Oder wenn du mit einer ausgefeilteren Architektur entwickeln möchtest, kannst du einen MVC-inspirierten Ansatz wählen, das wird genausogut funktionieren.
Wie ich zuvor schon erwähnt habe, haben Seiten keine Menge an benötigten Feldern die ProcessWire unbedingt benötigt um die Struktur einer Seite zu verstehen (Zumindest keine sichtbaren. Es gibt einige eingebaute Felder wie Referenzen zur Elternseite oder die Anzahl an Kindern, etc.). Du kannst 100 Felder auf eine Seite packen, sie ordnen wie du es möchtest, angeben welche benötigt sind und welche nicht, und du kannst sie in verschiedene Felder oder Tabs aufteilen, um die UI-Experience zu verbessern.
Die andere Sache, die ProcessWire auszeichnet: Es bietet dir Tools an, um maßgeschneiderte, nutzerfreundliche Interfaces zu schaffen. Ich habe dir im vorigen Paragraf einen Eindruck davon vermittelt. Die Möglichkeiten um Templates maßzuschneidern ist unglaublich. Wenn du das mal selbst erlebt hast, wirst du verstehen warum ProcessWire eher ein CMF als ein CMS ist.
Beispiel: Jedes Feld trägt in sich einen Template-spezifischen Kontext. Das bedeutet: Du kannst einstellen das ein und dasselbe Feld ein bestimmtes Label, eine Beschreibung und ein Verhalten in einem Template hat, und ein komplett anderes Label, eine andere Beschreibung und ein anderes Verhalten in einem anderen Template hat.
Ein weiteres Beispiel sind Inputfield Dependencies: Sie ermöglichen es dir die Bedingungen anzugeben, wonach bestimmte Felder in der UI erscheinen und als benötigt gekennzeichnet werden.
Und noch ein weiteres Beispiel ist das Modul PageTableExtended: es lässt den Nutzer bestimmte Teile einer Seite (die du als Entwickler definierst) sehen und bearbeiten, und das auf eine visuelle und intuitive Art und Weise.
Das ist für mich die Definition von elegant und befähigend.
Schluss
Dieser Artikel kann nur an der Oberfläche kratzen was ProcessWire alles zu bieten hat und was man damit alles machen kann. Die Liste der tollen Features ist schlicht und ergreifend zu lang und würde den Rahmen dieses Artikels sprengen. Hier ein kurzer Einblick in einige dieser Features:
- ProcessWire hat tolle Caching-Mechanismen (z.B. Template- und Markup-Cache oder ProCache) und performt sehr gut. Außerdem ist die Skalierbarkeit beeindruckend. ProcessWire-Installationen mit mehreren Millionen Seiten sind kein Problem.
- ProcessWire hat eine kleine aber fantastische Community. Das Forum ist die zentrale Anlaufstelle um sich über Fragen und Probleme auszutauschen.
- ProcessWire hat sehr gute Unterstützung von Mehrsprachigkeit. Die Module für Mehrsprachigkeit sind Teil der vorgepackten Kernmodule. Mehrsprachigkeit aufzusetzen und zu managen ist ein Kinderspiel.
- ProcessWire hat tolle Nutzermanagement-Features mit Einstellungsmöglichkeiten die gleichzeitig feingranular und einfach zu managen sind. Du kannst z.B. eine Rolle für Nutzer erstellen, die nur dazu berechtigt sind Felder in französischer Sprache zu editieren, und in keiner anderen Sprache.
- Es stehen dir einige Admin-Themes zur Auswahl, um das Erscheinungsbild der Admin-GUI zu ändern.
- Sicherheit ist eine Top-Priorität für ProcessWire.
- ProcessWire hat eine transparente Roadmap und die Weiterentwicklung ist sehr aktiv. Quasi wöchentlich erscheinen neue Releases.
Je mehr du ProcessWire nutzt und je mehr du die Kernkonzepte, die API und die modulare Architektur verinnerlichst, desto mehr Spaß wirst du haben es zu benutzen. Du wirst erkennen wie mächtig die Tools und Workflows von ProcessWire tatsächlich sind. Man könnte sagen, dass das einzige Hindernis bestimmte Ziele mit ProcessWire zu erreichen deine eigene Vorstellungskraft ist.
Am Ende möchte ich den Macher von ProcessWire, Ryan Cramer, zitieren:
ProcessWire is a system that rewards you by being curious. We aim to show you how to fish so that you can catch the big fish.
Wie du weitermachen kannst
Nützliche Links und Tools rund um ProcessWire:
- Die Dokumentation auf der ProcessWire-Website ist ein toller Weg um mehr über ProcessWire zu lernen. Du findest hier u.a. Informationen über die API, die Ordnerstruktur, Templatedateien, Selektoren, Unterstützung von Mehrsprachigkeit und Sicherheit.
- ProcessWire Weekly ist die wöchentliche Quelle für ProcessWire-News und -Updates.
- ProcessWire.tv ist eine durchsuchbare Sammlung von Tutorial-Videos.
- wireshell ist Kommandozeileninterface für ProcessWire, das auf der Symfony-Console-Komponente basiert.
- Padloper ist eine E-Commerce-Plattform, die auf ProcessWire aufbaut.
- Mit dem ProcessWire Module Generator kannst du visuell geführt und mit vielen Best-Practices-Tipps mit der Modulentwicklung starten.
- ProcessWire Recipes ist ein Verzeichnis von Mini-Tutorials für geläufige und nicht-so-geläufige ProcessWire-Aufgaben und -Problemen, um dein ProcessWire-Können zu erweitern.
- Das ProcessWire Cheatsheet ist eine sehr nützliche Seite für alle verfügbaren API-Methoden.
- Besuche grap.pw um dir die neueste stabile Version von ProcessWire herunterzuladen.
- Im offiziellen ProcessWire-Forum gibt es eine Ansicht der beliebtesten Inhalte, wo du viele nützliche und interessante Inhalte findest.
- Schau dir an was andere über ProcessWire in den ProcessWire Reviews schreiben.
- Sieh dir Seiten an, die mit ProcessWire gemacht wurden.