Zum Inhalt springen
openplate

Die App

Inhaltsseiten

Die rechtlichen Seiten als Markdown-Dateien, die du einbindest (CONTENT_DIR): der Ordner, das Dateiformat, was abgewiesen wird und die benannten Abschnitte der beiden gesetzlichen Button-Seiten

Diese Seite wurde maschinell aus der englischen Dokumentation übersetzt.

openplate lädt rechtliche Seiten aus Markdown-Dateien, die du in den Container einbindest. Das Repository enthält selbst keine rechtlichen Texte. Du verfasst die Nutzungsbedingungen, die Datenschutzerklärung, das Impressum und die Seiten für die beiden gesetzlichen Buttons. Sie beschreiben deine Instanz und benennen dich als Betreiber.

Aktivierung

Setze CONTENT_DIR auf einen Ordner, den die App lesen kann:

sh
CONTENT_DIR=/srv/openplate-content

Binde den Ordner bei einem Container schreibgeschützt ein und verweise mit der Variable auf den Einhängepunkt:

yaml
services:
  openplate:
    environment:
      CONTENT_DIR: /content
    volumes:
      - ./content:/content:ro

Ein Wert, der keinen Ordner benennt, stoppt den Startvorgang. Ein fehlgeschlagener Einhängeversuch fällt sofort auf. Die App kann nicht starten und als Instanz ohne rechtliche Seiten erscheinen.

Wenn CONTENT_DIR nicht gesetzt ist

Das ist die Standardeinstellung, und sie passt zu einer Haushaltsinstanz, die nichts verkauft.

  • Jede Inhaltsroute antwortet mit 404: /terms, /privacy, /privacy/website, /imprint, /withdrawal, /kuendigung, /kuendigung/bestaetigt, /widerrufen und /widerrufen/bestaetigt.
  • Die öffentliche Fußzeile zeigt nur Quellcode, Lizenz und Einstellungen an. Die fünf rechtlichen Links (Datenschutz, Nutzungsbedingungen, Impressum und die beiden gesetzlichen Buttons) werden nicht angezeigt.
  • Einstellungen, Über enthält keine Gruppe Rechtliches. Wenn der Ordner eingehängt ist, listet diese Seite dieselben fünf Links unter einer Überschrift Rechtliches auf, sodass eine angemeldete Person, die keine Fußzeile sieht, das Impressum dennoch erreicht.
  • Der Hinweis, den ein abgemeldeter Besucher auf einer persönlichen Seite sieht, verlinkt auf die Startseite und auf die Anmeldung, ohne Link zum Impressum oder zum Datenschutz.
  • Das Newsletter-Formular lässt, falls du es aktiviert hast, seine Datenschutzzeile weg.

Die Links kehren zurück, sobald der Ordner eine Datei imprint.md enthält, in der Sprache des Lesers oder auf Englisch. Das Impressum dient als Kriterium, weil das deutsche Recht es für jede Instanz vorschreibt, die eine der anderen Seiten veröffentlicht.

Der Ordner

<CONTENT_DIR>/
  en/
    terms.md
    privacy.md
    imprint.md
    ...
  de/
    terms.md
    ...

Ein Ordner pro Sprache: en, de, fr, it, es oder tr. Eine Datei pro Seite, benannt nach ihrem Slug:

SlugPfad in der App
terms/terms
privacy/privacy
privacy-website/privacy/website
imprint/imprint
withdrawal/withdrawal
kuendigung/kuendigung
kuendigung-bestaetigt/kuendigung/bestaetigt
widerrufen/widerrufen
widerrufen-bestaetigt/widerrufen/bestaetigt

Eine Seite, die in der Sprache des Lesers fehlt, wird auf Englisch ausgeliefert. Eine Seite, die auch auf Englisch fehlt, ergibt ein 404. Die App liest nur diese Slugs. Sie baut niemals einen Pfad aus einer URL zusammen.

Die App liest jede Datei auf Anfrage und hält die geparste Seite im Speicher. Sie liest die Datei erneut ein, sobald sich deren Änderungszeitpunkt oder Größe ändert. Eine Bearbeitung einer eingebundenen Datei erscheint bei der nächsten Anfrage ohne Neustart.

Das Dateiformat

UTF-8, LF-Zeilenenden, keine Byte-Reihenfolge-Markierung. Jede Datei beginnt mit genau diesem Frontmatter:

---
title: Terms of service
updated: 2026-09-21
---

title ist die Seitenüberschrift. updated ist ein Kalenderdatum, und die App zeigt es unter der Überschrift als „Zuletzt aktualisiert“ an, in der Sprache des Lesers. Wiederhole keines von beiden im Hauptteil.

Der Hauptteil verwendet diese Teilmenge und nichts anderes:

  • Überschriften ## und ###. # ist der Titel und wird nie geschrieben.
  • Absätze, getrennt durch eine Leerzeile.
  • Listen mit - oder 1. , eine Ebene, keine Einrückung.
  • **strong** und *emphasis*.
  • Links [text](target). Das Ziel ist ein Pfad in der App (/imprint), https://, mailto: oder tel:. Ein Pfad in der App öffnet sich ohne Neuladen.
  • Ein fester Zeilenumbruch: ein Backslash als letztes Zeichen einer Zeile, gefolgt von der nächsten Zeile desselben Absatzes. Nutze ihn für eine Postanschrift.
  • Eine Definitionsliste: eine Begriffszeile gefolgt von einer oder mehreren : definition-Zeilen, ohne Leerzeile zwischen den Einträgen.
  • Ein Escape-Zeichen: ein Backslash vor \, *, [ oder ] macht das Zeichen wörtlich.

Absätze vor der ersten Überschrift bilden den Vorspann der Seite und werden größer dargestellt.

Was abgewiesen wird

Rohes HTML jeglicher Art (ein < gefolgt von einem Buchstaben, /, ! oder ?), HTML-Zeichenreferenzen wie &amp;, Bilder, Tabellen, Code, Blockzitate, #- oder ####-Überschriften, verschachtelte oder eingerückte Listen und jeglicher {{-Platzhalter.

Eine Datei, die das Format verletzt, wird abgewiesen, nicht repariert. Die App protokolliert jedes Problem mit seiner Zeilennummer, einmal pro Version der Datei. Die Seite antwortet mit 503 und der neutralen Fehleranzeige. Eine rechtliche Seite, die eine Tabelle stillschweigend verwirft oder ein Tag als Text ausgibt, würde ein Dokument veröffentlichen, das niemand verfasst hat. Korrigiere die Datei, und die nächste Anfrage liefert sie aus.

Benannte Abschnitte

Zwei Seiten enthalten ein Formular im Code der App: /kuendigung (Vertrag kündigen) und /widerrufen (Vertrag widerrufen). Ihre Bestätigungsseiten enthalten die Empfangsbestätigung im Code. Die Formularbeschriftungen, die Schaltflächen, die Validierungsmeldungen und die Zeilen der Empfangsbestätigung sind Teil der App. Der Fließtext darum herum stammt aus der Datei. Ein benannter Abschnitt enthält jeweils die Teile, die die App um das Formular herum platziert:

:::section unavailable
Text of the section, in the same subset.
:::

Jede dieser Seiten muss genau die folgenden Abschnitte enthalten, jeweils einmal. Ein fehlender oder ein zusätzlicher Abschnitt wird wie jeder andere Fehler abgewiesen.

SlugAbschnittWo die App ihn darstellt
kuendigung(Hauptteil)Der Vorspann, über dem Kündigungsformular.
kuendigungunavailableAnstelle des Formulars, wenn CORE_URL nicht gesetzt ist, und unter der Absendeschaltfläche, wenn eine Übermittlung den Erklärungsservice nicht erreichen kann.
kuendigung-bestaetigt(Hauptteil)Normalerweise leer.
kuendigung-bestaetigtmail-noticeNach den Zeilen der Empfangsbestätigung, vor der Druckschaltfläche.
widerrufen(Hauptteil)Der Vorspann, über dem Widerrufsformular.
widerrufenunavailableWie bei kuendigung.
widerrufen-bestaetigt(Hauptteil)Normalerweise leer.
widerrufen-bestaetigtmail-noticeWie bei kuendigung-bestaetigt.

Jede andere Seite hat keine Abschnitte: Ihr gesamter Hauptteil bildet die Seite.

Der Titel von kuendigung ist die Beschriftung, die das deutsche Gesetz für diese Seite vorschreibt, und dasselbe gilt für widerrufen. Die Fußzeile und die Absendeschaltflächen der App tragen die gesetzlich vorgeschriebenen Schaltflächenbeschriftungen selbst.

Woher die openplate-Instanzen ihre Dateien beziehen

Gehostete Instanzen binden Dateien ein, die in einem privaten Repository liegen, ein Verzeichnisbaum pro Instanz. Dieses Repository prüft jede Datei gegen dieses Format, bevor sie ausgeliefert wird. Eine abgewiesene Seite wird abgefangen, bevor sie einen Server erreicht.

Diese Seite auf GitHub bearbeiten