Für Entwickler & Gestalter

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
│   ├── icons/               SVG-Icon-Bibliothek für <oicon> (neu)
│   └── font/                (optional) eingebundene Schriften
├── cookies.vue              Cookie-Banner (neu)
├── dynamiclists.vue         Vorlagen für den "Dynamische Liste"-Block
├── emptycomp.vue            Anzeige für Seiten ohne Blöcke
├── 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>
    { "name": { "default": "Hero" }, "dbKeys": { "title": "text" } }
</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:

PlatzhalterOrtBedeutung
[[orblio_inject_props]]props:Vom System gelieferte Props. Nie selbst befüllen. Hängt bei Sub-Templates auch deren Logik an.
[[orblio_template_contents]]<main> in theme.vueHier rendert das System die Seiteninhalte (die Blöcke).
[[orblio_template_mounted]]mounted() in theme.vueSystem-Mount-Logik. Eigener Code davor/danach erlaubt.
[[orblio_editorbutton]]Sub-TemplatesEditier-Button im CMS-Bearbeitungsmodus, direkt nach dem Wurzelelement.

Der <config>-Block

Jede Datei braucht einen <config>-Block, und er muss gültiges JSON sein: doppelte Anführungszeichen, keine Kommentare, kein Komma am Ende. Bei Blöcken meldet erst dbKeys den Block in der Block-Auswahl an. Fehlt dbKeys oder ist das JSON fehlerhaft, taucht der Block dort einfach nicht auf.

Theme (theme.vue):

{ "name": "Mein Theme", "description": "Kurzbeschreibung", "author": "...", "date": "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 */ }
}

Sub-Templates (navigation, search, langswitcher, lightbox, cookies, emptycomp, dynamiclists) haben eine einfache <config> mit name und description, ohne dbKeys.

Die harten Regeln

Diese Punkte sind nicht verhandelbar — verletzt eine Vorlage sie, rendert sie nicht oder zerstört das Layout:

  1. Kommentare nur /* */ — niemals //, weder in JS noch in CSS.
  2. CSS (darf auch nested sein mit &), kein SASS/SCSS. Nur natives verschachteltes CSS plus Custom-Properties (--token).
  3. Vue 3 Options API über Vue.defineComponent({…}). Kein <script setup>, keine import/export, keine Composition-API.
  4. Zentrale Elemente sind unveränderlich: vtext, htmltext, oimage, ovideo, oicon, ofolder, repeatable, repeatcontents, fromdatabase exakt wie dokumentiert verwenden.
  5. vtext für designfixe Texte, htmltext nur für freien Fliesstext. Überschriften, Labels, Button-Beschriftungen immer mit vtext.
  6. Jedes Tag auf eine Zeile. Orblio entfernt beim Bauen alle Zeilenumbrüche und Tabs. Attribute, die über mehrere Zeilen verteilt sind, kleben danach zusammen. Darum: ein Tag mit allen Attributen auf eine Zeile, nur Leerzeichen zum Einrücken.
  7. Kein ": " in sichtbarem Template-Text. Orblio macht daraus ":". Texte mit Doppelpunkt gehören als Inhalt ins Feld, nicht ins Markup.
  8. Externe Dienste nur über das Cookie-Banner. Videos über ovideo. Karten und fremde Skripte mit data-orb-cc="medien" (bzw. statistik, marketing) und data-src statt src — Orblio lädt sie erst nach der Zustimmung.

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_*System-, Theme- und Sub-Template-Klassen (.orb_header, .orb_nav_main). Lightbox: .orblb_*, Cookie-Banner: .orb_cc_*.
c{N}_*Block-Komponenten, passend zur Dateinummer (component5.vue → .c5_section). So bleiben Styles kollisionsfrei.
--tokenCSS-Tokens projektweit im 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 Logik (Menüeinträge auflösen, suchen, Sprache wechseln, Lightbox bedienen, Zustimmung speichern) liefert Orblio selbst: Über [[orblio_inject_props]] wird sie automatisch angehängt. In der Datei stehen also nur Markup und CSS.

Ältere Themes laufen weiter

Bringt eine Datei eigene Methoden mit, haben diese Vorrang vor der Logik von Orblio. Ältere Themes funktionieren so unverändert. Sie verpassen dann aber Verbesserungen aus Updates, zum Beispiel bei der Lightbox. Wer ein Theme überarbeitet, sollte die eigene Logik in Sub-Templates deshalb entfernen.

Sub-TemplateAufgabeStyle-Präfix
theme.vueWrapper: Header, <main> mit den Inhalten, Footer. Ort für Tokens, Reset, Buttons.orb_*
navigation.vueMenüs, per ID gesteuert. DOM: nav > ul > li(a + sub-ul), Zustände .active/.has_sub.orb_nav_*
search.vueVolltextsuche mit Ergebnis-Dropdown.orb_search_*
langswitcher.vueSprachauswahl; rendert nur bei > 1 Sprache.orb_lang_*
lightbox.vueGalerie/Overlay. Muss als <lightbox/> im Theme eingebunden sein.orblb_*
cookies.vueCookie-Banner. Muss als <cookies/> im Theme stehen. Wieder geöffnet wird es über <cookieoptions>…</cookieoptions> (siehe Cookie-Banner).orb_cc_*
emptycomp.vueErscheint auf Seiten, die noch keinen Block haben. Fehlt die Datei, bleibt eine leere Seite weiss.frei
dynamiclists.vueSonderfall: keine Komponente, sondern ein JS-Array von Listen-Vorlagen.dl-*

Der $root-Zustandsvertrag

Sub-Templates lesen und schreiben nur diese dokumentierten Felder:

ZugriffZweck
$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 und Cookie-Banner 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. Dasselbe gilt für <cookies/>: Ohne die Zeile erscheint kein Banner.

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.