Eine Site braucht ein Kontaktformular, die nächste Kommentare unter Beiträgen, die dritte will alte URLs weiterleiten. Das sind keine Content-Modelle — aber jedes Mal denselben Unterbau nebendran zu bauen, Speicher, Spam-Schutz, Admin-Ansicht, ist verlorene Zeit. RustyCMS bringt diese Bausteine als Plugins mit: optional, pro Feature einkompiliert, jedes mit eigener Seite in der Admin-UI.
Einkompiliert, nicht nachgeladen
CARGO_FEATURES=comments,forms — und das Binary enthält genau diese beiden, samt Admin-Oberfläche. Was nicht gebaut wurde, ist nicht da: kein Code im Bundle, kein Eintrag in der Sidebar, keine Route. GET /api/plugins sagt dem Frontend, was aktiv ist. Kein dlopen, kein WASM, kein Marktplatz — RustyCMS bleibt ein Binary.
Dasselbe Prinzip trägt die Backends darunter: Asset-Ablage und Versionshistorie hängen an schmalen Schnittstellen. Das Dateisystem ist die Variante, die ohne Konfiguration läuft; die Versionshistorie hat bereits eine zweite für den Datenbankmodus. Welche läuft, entscheidet eine Env-Variable, nicht ein Umbau.
Kommentare mit Spam-Schichten
Besucher kommentieren ohne Konto — ein anonymer Session-Cookie erlaubt, den eigenen Kommentar später zu bearbeiten oder zu löschen. Davor sitzen mehrere Filter: Rate-Limit pro IP, Cooldown pro Session, Duplikat-Fenster, Honeypot, Mindestalter der Seite (Bots posten in null Millisekunden), IP-Sperrliste. Mit RUSTYCMS_COMMENTS_REQUIRE_APPROVAL=true landet jeder neue Kommentar in der Warteschlange; die Admin-Seite gibt frei, lehnt ab, löscht.
POST /api/comments/mein-artikel
{ "author": "Max", "body": "Toller Artikel!", "honeypot": "", "client_age_ms": 5000 }
GET /api/comments/counts?ids=artikel-1,artikel-2 # Zähler für die Übersicht
Formulare, deren Eingänge im CMS liegen
POST /api/forms/kontakt/submit nimmt ein beliebiges JSON-Objekt an und speichert es. Kein Schema nötig — das Formular existiert mit der ersten Einsendung. Schutz: Rate-Limit pro IP, Body-Limit, Honeypot-Feld, Origin-Allowlist und eine Allowlist erlaubter Formular-IDs (RUSTYCMS_FORMS_ALLOWED_IDS=kontakt,feedback), damit niemand fremde Formulare erfindet. Die Admin-Seite listet Eingänge pro Formular mit Status neu/gelesen.
Redirects, die das Frontend abholt
Alte Pfade auf neue umleiten, 301 oder 302, pro Eintrag ein- und ausschaltbar. Die Redaktion pflegt die Liste in der Admin-UI; GET /api/redirects ist öffentlich und liefert nur aktive Einträge — das Frontend lädt sie beim Start und prüft jeden Request dagegen.
Wiki als Collection
Hierarchische Markdown-Seiten mit Baum, Drag-Reorder, Wiki-Links ([[slug]]) und Embeds ({{embed:slug}}). Das Plugin bringt keine eigenen Routen mit — es ist eine Ansicht auf die Collection wiki_page. Versionierung, Suche, Validierung, Export: Was für Content gilt, gilt auch hier.
Bewusst nicht drin
Kein Plugin-Marktplatz, kein Laden fremden Codes zur Laufzeit. Ein Plugin ist Rust-Code, der mitgebaut wird. Das ist der Preis dafür, dass ein Deployment genau das enthält, was du gebaut hast — und nichts sonst.