Templates & Themes bauen
Ein Orblio-Theme ist ein Ordner voller Vue-3-Vorlagen. Du gestaltest damit das komplette Aussehen einer Webseite und definierst die Block-Elemente, die Redakteure später zusammenstecken. Dieses Kapitel erklärt Struktur, Datei-Aufbau und die verbindlichen Regeln.
Mit KI schneller ans Ziel
Für den Bau von Themes gibt es einen fertigen KI-Skill. Er enthält alle Regeln dieses Kapitels in maschinenlesbarer Form — damit ChatGPT, Claude & Co. korrekte Orblio-Templates erzeugen.
Was ist ein Theme?
Ein Theme (technisch: ein Template-Ordner) bestimmt Farben, Schriften, Kopf- und Fusszeile sowie den gesamten Satz an Block-Elementen. Orblio nutzt dafür ein mehrschichtiges, Gutenberg-artiges System. Wichtig: Das Design muss handwerklich gut sein und die Orblio-Datenstruktur exakt einhalten — ein optisch perfektes Template, das die Verdrahtung verletzt, rendert nicht.
Ordnerstruktur eines Templates
Jedes Theme liegt unter templates/<NAME>/ und hat diese verbindliche Struktur:
templates/<NAME>/
├── components/ Block-Elemente (component1.vue, component2.vue, …)
├── files/ Datei-Icons fürs Theme
│ ├── default.svg Standard-Datei-Icon
│ ├── doc.svg pdf.svg ppt.svg xls.svg zip.svg
│ └── font/ (optional) eingebundene Schriften
├── dynamiclists.vue Vorlagen für den "Dynamische Liste"-Block
├── langswitcher.vue Sprachumschalter
├── lightbox.vue Lightbox / Galerie
├── navigation.vue Navigation (ID-basiert)
├── search.vue Seitensuche
└── theme.vue Theme-Wrapper (Header/Main/Footer)
Anatomie einer .vue-Vorlage
Jede Vorlagedatei besteht aus drei Blöcken — immer in dieser Reihenfolge:
<config>
{ /* JSON — Theme vs. Block unterscheiden */ }
</config>
<script>
orblio.NAME = Vue.defineComponent({
props: [[orblio_inject_props]], /* vom System ersetzt — NIE selbst füllen */
template: ` … `,
/* data / computed / methods / mounted nach Bedarf */
});
</script>
<style>
/* Nested CSS mit & — KEIN SASS/SCSS */
</style>
NAME ist der Dateiname ohne Endung (theme, navigation, component5 …). Block-Komponenten registriert das System als orblio.componentN.
System-Platzhalter
Diese Platzhalter ersetzt das System zur Laufzeit — sie bleiben wörtlich stehen:
| Platzhalter | Ort | Bedeutung |
|---|---|---|
[[orblio_inject_props]] | props: | Vom System gelieferte Props. Nie selbst befüllen (Ausnahme: navigation). |
[[orblio_template_contents]] | <main> in theme.vue | Hier rendert das System die Seiteninhalte (die Blöcke). |
[[orblio_template_mounted]] | mounted() in theme.vue | System-Mount-Logik. Eigener Code davor/danach erlaubt. |
[[orblio_editorbutton]] | Sub-Templates | Editier-Button im CMS-Bearbeitungsmodus, direkt nach dem Wurzelelement. |
Der <config>-Block
Theme (theme.vue):
{ "title": "Mein Theme", "author": "...", "lastupdate": "2026-05-24" }Block-Komponente (components/componentN.vue):
{
"name": { "default": "Hero", "en": "Hero" },
"description": { "default": "Titel, Text, Bild" },
"author": "...",
"date": "2026-05-24",
"dbKeys": { /* deklariert die DB-Struktur — siehe Content-Elemente */ }
}navigation, search und langswitcher nutzen die einfache Block-Form ohne dbKeys. lightbox und dynamiclists haben keinen <config>-Block.
Die harten Regeln
Diese Punkte sind nicht verhandelbar — verletzt eine Vorlage sie, rendert sie nicht oder zerstört das Layout:
- Kommentare nur
/* */— niemals//, weder in JS noch in CSS. - CSS (darf auch nested sein mit
&), kein SASS/SCSS. Nur natives verschachteltes CSS plus Custom-Properties (--token). - Vue 3 Options API über
Vue.defineComponent({…}). Kein<script setup>, keineimport/export, keine Composition-API. - Zentrale Elemente sind unveränderlich:
vtext,htmltext,oimage,ovideo,ofolder,repeatable,repeatcontents,fromdatabaseexakt wie dokumentiert verwenden. vtextfür designfixe Texte,htmltextnur für freien Fliesstext. Überschriften, Labels, Button-Beschriftungen immer mitvtext.
Verboten
//-Kommentare · <script setup> / import / export · fetch()/axios · props: [[orblio_inject_props]] selbst füllen · zentrale Elemente umschreiben · htmltext für Überschriften · hartcodierte <a href>/<button> in Blöcken · SASS · reines #000/#fff als Fläche.
Naming-Konventionen
.orb_header, .orb_nav_main). Lightbox: .orblb-*.component5.vue → .c5_section). So bleiben Styles kollisionsfrei.theme.vue unter :root definieren; Komponenten konsumieren mit Fallback: var(--r-md, 10px).Sub-Templates & der $root-Vertrag
Neben Blöcken hat ein Theme feste Sub-Templates, die das Laufzeitsystem ansteuert. Ihre Skript-Logik ist System-Plumbing — übernimm sie unverändert aus den Skeletten und gestalte nur Markup-Klassen und CSS.
| Sub-Template | Aufgabe | Style-Präfix |
|---|---|---|
theme.vue | Wrapper: Header, <main> mit den Inhalten, Footer. Ort für Tokens, Reset, Buttons. | orb_* |
navigation.vue | Menüs, per ID gesteuert. DOM: nav > ul > li(a + sub-ul), Zustände .active/.has_sub. | orb_nav_* |
search.vue | Volltextsuche mit Ergebnis-Dropdown. | orb_search_* |
langswitcher.vue | Sprachauswahl; rendert nur bei > 1 Sprache. | orb_lang_* |
lightbox.vue | Galerie/Overlay. Muss als <lightbox/> im Theme eingebunden sein. | orblb-* |
dynamiclists.vue | Sonderfall: keine Komponente, sondern ein JS-Array von Listen-Vorlagen. | dl-* |
Der $root-Zustandsvertrag
Sub-Templates lesen und schreiben nur diese dokumentierten Felder:
| Zugriff | Zweck |
|---|---|
$root.page (r/w) | Aktuelle Seiten-URL. Schreiben = Navigation (SPA). '/' = Startseite. |
$root.contentLang (r/w) | Aktuelle Inhaltssprache ('default', 'en' …). |
$root.contentLangs (r) | Map verfügbarer Sprachen { key: Anzeigename }. |
Lightbox nicht vergessen
Bindet das Theme <lightbox/> nicht ein (am Ende des Wrappers, nach dem Footer), sind alle a[data-link-open="lightbox"]-Links tot — auch wenn die Datei existiert.
Kompilierung
Deine .vue-Quelldateien werden von Orblio zu ausgelieferten Bundles kompiliert. Bearbeite immer die Quelldateien im Template-Ordner, nie die generierten Bundle-Dateien (z. B. *.foot.js unter defs/) — die sind reine Artefakte und werden beim nächsten Build überschrieben.