CMF Anleitung
Über diese Anleitung
Dieses CMS funktioniert ohne Datenbank, ohne Build-Tool und ohne technisches Vorwissen. Inhalte werden als strukturierte Blöcke gepflegt – über den visuellen Block-Editor oder direkt als JSON.
Vom Login bis zur fertigen Seite, vom Textblock bis zur Spaltenstruktur – alles auf einer Seite.
Inhalt

1. Erste Schritte


Login
Das Backend erreichst du unter /admin.php. Benutzername und Passwort werden beim Einrichten festgelegt.
Nach dem Login siehst du die Seitenübersicht mit allen Seiten, ihrem Status und den Aktionen Bearbeiten, Duplizieren und Löschen.
Tipp: Unter Benutzer kann das Passwort jederzeit geändert werden.
Backend-Bereiche
- Seiten – Inhalte erstellen und bearbeiten
- Blog – Blogbeiträge verwalten
- Header/Footer – globale Bereiche
- Theme – Farben, Schriften, Custom CSS
- Media – Bilder und Dateien
- Benutzer – Zugänge verwalten
- Einstellungen – Backup, Import
Erste Seite
- Seiten > Neue Seite
- Titel und Slug festlegen
- + Heading für Überschrift
- + Text für einen Absatz
- Status auf published setzen
- Speichern
2. Seitenstruktur
Inhaltsobjekt (JSON)
Jede Seite besteht intern aus zwei Teilen:
{
"meta": {
"title": "Seitentitel",
"description": "Kurzbeschreibung"
},
"content": {
"blocks": [
{ "id": "h1_start", "type": "heading", "data": {...} },
{ "id": "t1_intro", "type": "text", "data": {...} }
]
}
}meta.title ist Pflicht. content.blocks enthält die geordnete Liste aller Inhaltsblöcke.
Seitenobjekt (Verwaltung)
Getrennt vom Inhalt verwaltet das System diese Felder:
- id – interne Seiten-ID
- slug – URL-Teil (z.B.
kontakt→/kontakt) - title – Seitenname
- status –
draftoderpublished - nav.show – im Menue anzeigen
- nav.order – Sortierung (kleiner = weiter links)
- nav.label – optionaler Menütext
- nav.parent – Seiten-ID für Untermenüs
Im Backend stehen diese Felder oberhalb des Editors. Der Slug home wird automatisch zur Startseite.
Tipp: Die Seiten-ID für Untermenüs findest du in der Seitenübersicht – sie steht klein unter dem Seitentitel.
3. Blocktypen


Jeder Block hat drei Felder: id (eindeutig pro Seite), type und data. Im Editor werden Blöcke über die Toolbar angelegt: + Heading, + Text, + Bild, + Liste, + Buttons, + Spalten, + HTML und + Blog Übersicht. Zwischen Block-Editor und JSON-Ansicht kann jederzeit umgeschaltet werden.
heading
Überschriften von h1 bis h6.
{ "level": 1, "text": "Überschrift" }Pro Seite genau ein h1, danach logisch mit h2, h3 weiterarbeiten.
text
HTML-Textblock für Absätze und Formatierungen.
{ "html": "<p>Ein Absatz</p>" }Erlaubte Tags: p, br, strong, em, u, a, ul, ol, li, code, pre, span, small, sup, sub.
image
Bild mit optionaler Bildunterschrift.
{ "src": "/media/2026/03/bild.jpg",
"alt": "Beschreibung",
"caption": "Optional",
"loading": "lazy" }src und alt sind Pflicht. Im Editor: Bild auswählen übernimmt ein hochgeladenes Medium direkt.
list
Einfache Aufzählung oder nummerierte Liste.
{ "ordered": false,
"items": ["Punkt 1", "Punkt 2"] }ordered: true = nummeriert. Einträge sind einfache Strings.
buttons
Verlinkte Buttons für Call-to-Actions.
{ "items": [
{ "label": "Mehr", "href": "/seite",
"style": "primary" }
] }label und href sind Pflicht.
blog_overview
Rendert das Blog-Karten-Grid automatisch.
{ "category": "" }Leer = alle Beiträge. Mit Kategorie wird gefiltert.
4. Spalten und HTML
columns
Strukturblock mit 2–5 Spalten. Jede Spalte enthält normale Blöcke.
{ "columns": 3,
"items": [
[{ "id": "h3_a", "type": "heading", "data": {...} }],
[{ "id": "t_b", "type": "text", "data": {...} }],
[{ "id": "b_c", "type": "buttons", "data": {...} }]
] }items muss exakt so viele Arrays enthalten wie columns angibt. IDs der Unterblöcke müssen global eindeutig sein.
Tipp: Im Editor legst du die Spaltenzahl fest. Jede Spalte hat dann einen eigenen Bereich, in den du Blöcke einfügen kannst. Auf kleinen Bildschirmen werden die Spalten automatisch untereinander dargestellt.
html
Der mächtigste Blocktyp: freier HTML-Code, der direkt ausgegeben wird – ohne Einschränkungen und ohne Sanitizing.
{ "code": "<div class=\"card\">Inhalt</div>" }Damit lässt sich praktisch alles umsetzen, was mit den anderen Blocktypen nicht möglich ist:
- Layouts – Karten, Grids, Flex-Bereiche, individuelle Abschnitte
- Embeds – Videos (YouTube, Vimeo), Karten, Podcasts, Social Media
- Formulare – Kontaktformulare, Newsletter-Anmeldungen
- Tabellen – strukturierte Daten in
<table> - Interaktives – Akkordeons, Tabs, Countdowns per inline
<script> - Gestaltung – Hero-Banner, Statistiken, Zeitleisten, Zitate
Tipp: Eigene CSS-Klassen unter Theme → Custom CSS definieren und hier per class="..." verwenden – statt Inline-Styles. So bleibt der Code sauber und wiederverwendbar.
Beispiel: So sieht ein 5-spaltiger columns-Block aus:
Spalte 1
In jeder Spalte dürfen normale Blöcke liegen: Überschriften, Text, Listen, Bilder oder Buttons.
Die Spalten passen sich auf kleinen Bildschirmen automatisch untereinander an – von fünf nebeneinander bis zu einer einzigen Spalte auf dem Smartphone.
Spalten eignen sich besonders für Vergleiche, Feature-Listen oder Inhalte, die nebeneinander besser wirken als untereinander.
Spalte 2

Spalte 3
Buttons funktionieren auch innerhalb von Spalten. So entstehen kompakte Call-to-Action-Bereiche direkt neben erklärendem Text oder Bildern.
Der Style primary hebt den Button farblich hervor. Ohne Style wird er dezent dargestellt.
Spalte 4
Normale Textblöcke zeigen, dass auch längere Absätze in schmalen Spalten gut lesbar bleiben.
Das System bricht den Text automatisch um. Schriftgröße und Zeilenabstand werden vom Theme gesteuert – hier muss nichts manuell angepasst werden.
- Listen in Spalten
- Funktionieren genauso
- Wie außerhalb
Spalte 5
HTML-Block
Auch freier HTML-Code ist in Spalten möglich. Hier als Beispiel eine Card-Fläche mit eigenem Layout – per class="card" gestaltet.
5. Medien


Hochladen
Im Backend unter Media können Dateien per Drag & Drop oder Dateiauswahl hochgeladen werden. Uploads landen automatisch unter /media/YYYY/MM/. Bei doppelten Dateinamen wird automatisch ein eindeutiger Name erzeugt.
Erlaubte Typen: jpg, png, webp, gif, svg, pdf, mp4, mp3, wav.
Tipp: Bilder werden beim Upload nicht verkleinert. Für schnelle Ladezeiten empfiehlt sich, Bilder vorher auf die benötigte Größe zu bringen.
Einbinden
Im Bildblock gibt es die Schaltfläche Bild auswählen. Damit wird ein hochgeladenes Bild direkt übernommen – kein Pfad manuell eintippen.
Im JSON wird der Pfad als src im image-Block verwendet:
"src": "/media/2026/03/bild.jpg"Löschen
In der Media-Übersicht zeigt jede Datei ihre Einbindungen – also wo sie auf Seiten oder in Blog-Posts verwendet wird.
Eingebundene Medien sind gesperrt und können nicht gelöscht werden. Nur Dateien ohne Einbindung zeigen einen Löschen-Button.
Über Auf Einbindung prüfen wird die Zuordnung aller Medien aktualisiert.
6. Navigation und globale Bereiche
Navigation
Die Navigation wird automatisch aus allen veröffentlichten Seiten erzeugt:
- Nur Seiten mit
status: publishedundnav.show: true - Sortiert nach
nav.order(kleinere Zahl = weiter links) nav.labelüberschreibt den Menü-Textnav.parentmit einer Seiten-ID erzeugt ein Untermenü (Klappmenü)
Tipp: Die Seite mit dem Slug home wird als Startseite unter / angezeigt. Seiten mit nav.show: false sind erreichbar, aber nicht im Menü sichtbar.
Header und Footer
Header und Footer verwenden das gleiche Block-Schema wie Seiten. Sie werden global auf allen Seiten angezeigt.
Im Backend unter Header/Footer bearbeiten. Zwischen Block-Editor und JSON umschalten funktioniert wie bei normalen Seiten.
7. Theme und Custom CSS
Theme-Konfiguration
Im Backend unter Theme wird das Design als JSON konfiguriert: Container, Abstände, Farben, Schriftgrößen und Schriften.
Farben: Hex-Werte im colors-Objekt. primary = Akzentfarbe für Buttons/Links.
Schriften: Fontname unter fonts.body / fonts.heading eintragen (Teil vor dem Bindestrich im Dateinamen). Gewicht: light, regular oder bold.
Nach dem Speichern ist die CSS sofort aktiv – kein Build-Schritt nötig.
Tipp: Verfügbare Fonts werden unterhalb des Theme-Editors angezeigt. 10 Schriftfamilien mit je 3 Schnitten (Light, Regular, Bold) sind vorinstalliert.
Custom CSS
Unter Theme → Custom CSS kann eigenes CSS geschrieben werden. Die Datei wird nach theme.css geladen und kann alles überschreiben oder ergänzen.
Eigene Klassen dort definieren und dann in html-Blöcken per class="..." verwenden – statt Inline-Styles.
8. Blog


Das CMF enthält ein integriertes Blog-System. Blogbeiträge werden als eigener Inhaltstyp verwaltet – getrennt von Seiten, aber mit dem gleichen Block-Editor. Der Blog hat im Backend einen eigenen Bereich mit Beitragsliste, Einstellungen und Drag-and-Drop-Sortierung.
Beiträge erstellen
Im Backend unter Blog findest du die Beitragsliste. Über + Neuer Beitrag wird ein neuer Post angelegt.
Jeder Beitrag hat diese Felder:
- Titel – Name des Beitrags
- Slug – URL-Teil (wird aus dem Titel generiert)
- Status –
draftoderpublished - Kategorie – aus den definierten Kategorien wählbar
- Bild-Pfad – Vorschaubild für die Übersicht
- Beschreibung – Kurztext für die Karten-Vorschau
Der eigentliche Inhalt wird darunter im Block-Editor gepflegt – genau wie bei normalen Seiten.
Verwaltung und Einstellungen
Reihenfolge: In der Beitragsliste können Posts per Drag-and-Drop umsortiert werden. Die Reihenfolge bestimmt die Anzeige auf der Übersichtsseite.
Duplizieren: Jeder Beitrag kann über den Button Duplizieren kopiert werden – praktisch für ähnliche Inhalte.
Blog-Einstellungen stehen unterhalb der Beitragsliste:
- Blog-URL-Prefix – bestimmt die URL-Struktur. Standard ist
blog, kann aber geändert werden (z.B.news). Beiträge sind dann unter/news/beitrag-slugerreichbar. - Kategorien – kommagetrennt eingeben (z.B. Neuigkeiten, Tutorials, Updates). Diese stehen dann beim Erstellen eines Beitrags als Dropdown zur Verfügung.
Im Frontend
Die Blog-Übersicht zeigt alle veröffentlichten Beiträge als Karten-Grid. Jede Karte zeigt das Beitragsbild, den Titel und die Beschreibung. Das Layout ist responsiv (5/4/3/2/1 Spalten je nach Bildschirmbreite).
Blog-Seite einrichten: Die Blog-Übersicht ist eine normale Seite mit einem blog_overview-Block. Dieser Block rendert das Karten-Grid automatisch. Optional kann über category nach einer Kategorie gefiltert werden.
Einzelne Posts sind unter /prefix/post-slug erreichbar (z.B. /news/mein-beitrag). Der Prefix wird in den Blog-Einstellungen festgelegt.
Hinweis: Blogbeiträge erscheinen nicht in der Navigation – sie sind ausschließlich über die Übersichtsseite und direkte Links erreichbar.
9. Backup und Import


Unter Einstellungen findest du Export, Import und die Versionsprüfung. Damit lassen sich Webseiten sichern, zwischen Servern verschieben oder Vorlagen verteilen.
Export
Erstellt ein ZIP-Backup der Webseite. Per Checkboxen wählst du aus, was enthalten sein soll:
- Header – globaler Header-Inhalt
- Footer – globaler Footer-Inhalt
- Seiten – alle Seiten mit Seitenindex
- Medien – alle hochgeladenen Dateien
Nach dem Klick auf ZIP exportieren wird die Datei als cmf-backup-YYYY-MM-DD.zip heruntergeladen.
Tipp: Regelmäßige Backups vor größeren Änderungen schützen vor Datenverlust.
Import
Der Import läuft in zwei Schritten:
- ZIP analysieren – ZIP-Datei hochladen. Das System zeigt den Inhalt: Anzahl Seiten (mit Titeln), Medien, Header/Footer.
- Import starten – per Checkboxen wählen, was importiert werden soll. Dann bestätigen.
Wichtig: Vorhandene Seiten werden aktualisiert (gleiche ID), neue Seiten erstellt. Es wird nichts gelöscht. Medien werden in die bestehende Ordnerstruktur kopiert.
System-Update
Oben auf der Einstellungsseite wird die installierte Version mit der verfügbaren Version verglichen.
Wenn ein Update bereitsteht, kann es direkt aus dem Backend heruntergeladen und eingespielt werden. Die eigenen Inhalte, Medien und Konfiguration bleiben dabei erhalten – nur der Systemcode wird aktualisiert.
10. Regeln und Validierung
Inhaltsregeln
- Pro Seite genau ein h1
- Logische Überschriftenhierarchie (h2, h3, ...)
- Block-IDs sprechend und stabil halten
- Bilder immer mit Alt-Text
- Im text-Block nur sauberes HTML
- html-Block nur für Sonderfälle
Validierung
- meta.title darf nicht leer sein
- content.blocks muss ein Array sein
- Jeder Block braucht id, type und data
- IDs müssen eindeutig sein (auch in Spalten)
- Nur bekannte Blocktypen erlaubt
- columns.items = exakte Spaltenzahl
- image: src und alt Pflicht
- buttons: label und href Pflicht
11. FAQ
Seiten und Inhalte
Wie veröffentliche ich eine Seite?
Status auf published setzen und speichern. Seiten mit draft sind nur im Backend sichtbar.
Wie erstelle ich ein Untermenü?
Im Seitenformular bei Unterpunkt von die Seiten-ID der Elternseite eintragen.
Muss jede Seite ein h1 haben?
Ja, genau ein inhaltliches h1 pro Seite. Danach logisch mit h2, h3 weiterarbeiten.
Darf ich freie Felder im JSON ergänzen?
Nein. Unbekannte Felder werden ignoriert. Das Schema ist bewusst klein gehalten.
Block-Editor
Wie lösche ich einen Block?
Über das Löschen-Symbol am Block. Es gibt kein Undo.
Wie verschiebe ich einen Block?
Über die Pfeil-Schaltflächen am Block nach oben oder unten.
Kann ich zwischen Editor und JSON wechseln?
Ja – über die Umschalter oben auf der Seite. Änderungen werden beim Wechsel übernommen.
Ersetzt der Editor das JSON?
Nein. Er ist die Eingabeoberfläche – gespeichert wird immer JSON.
Medien und Theme
Wie lade ich Bilder hoch?
Media → Dateiauswahl oder Drag & Drop. Dann im Bildblock über Bild auswählen einbinden.
Wie ändere ich die Schrift?
Theme → fonts.body oder fonts.heading auf den Fontnamen setzen. Gewicht: light, regular oder bold.
Wie ändere ich Farben?
Theme → im colors-Objekt die Hex-Werte anpassen. primary ist die Akzentfarbe für Buttons und Links.
Kann ich eigenes CSS schreiben?
Ja. Unter Theme → Custom CSS. Eigene Klassen definieren und per class="..." in html-Blöcken verwenden.