Pump Up The Jam!

Eigentlich verrückt: Vor knapp einem Jahr hatte ich mich hier im Blog noch über den grassierenden Hype der „Meta-Frameworks“ wie Next.js, Astro und Nuxt ausgelassen, und dass es viele Gründe gibt, davon die Finger zu lassen.

Nur wenige Wochen später habe ich dann mein erstes Nuxt-Projekt gestartet und mich zusammen mit dem fantastischen Ralf Göke auf eine lange Reise begeben. Es geht um den Relaunch von scouter.de – das Carsharing-Angebot eines meiner langjährigsten Kunden.

Die Aufgabe

Bei scouter.de gibt es bereits seit dem Start der Marke im Jahr 2014 vier Hauptbereiche umzusetzen:

  1. Marketing-Website mit 10-15 Einzelseiten (zeitweise auch mit News)
  2. Online-Registrierung
  3. Mein-Konto-Bereich
  4. Buchungsbereich

Beim ersten Punkt waren wir technologisch stets unabhängig, aber bei den Punkten 2 - 4 musste natürlich eine API zum Systemdienstleister (DB Flinkster Netzwerk) eingebunden werden, welche die eigentlichen Daten liefert und verwaltet.

Es gab in den vergangenen zehn Jahren dann eine stetige Evolution am laufenden Projekt (a.k.a. Feature Creep) mit immer komplizierterem PHP/jQuery-Code. Wir bauten eine eigene Middleware zum Glätten der „Ein-bisschen-RESTful“-API. Im Jahr 2021 kam dann für den Buchungsbereich eine SPA (Single Page Application) hinzu, die auch als Multiplattform-App in die nativen Stores wanderte, sowie auf, äh, abenteuerliche Weise1 in den CMS-basierten Marketingteil der Website eingebettet wurde.

Anfang 2023 war scouter.de ein Sammelsurium an Technologien, die man beim besten Willen niemandem mehr hätte erklären können. Aber nun ja: Es hat funktioniert. Wenn es Ausfälle gab, war das (meistens) nicht meine Schuld.

Der technische Anlass für die ganz große Reform war dann der Wechsel des Carsharing-Systemanbieters hin zu Cantamen. Für mich ein echter Befreiungsschlag! Und weil abzusehen war, dass es mit einem simplen Austausch der API-Syntax nicht getan war, grübelte ich einige Wochen lang über die geeignete Basis-Technologie für den Relaunch nach.

Warum Nuxt?

Kernstück von scouter.de ist für die fünfstellige Anzahl an Bestandkunden ganz klar die native App bzw. der Buchungsbereich der Website, die auch als PWA funktioniert hat2. Diese war technologisch einigermaßen frisch, nämlich mit Vue.js umgesetzt, und mit Ralfs Hilfe waren wir tatsächlich gerade dabei, alles auf die Composition-API umzustellen und TypeScript einzuführen.

Wir haben also kurzerhand beschlossen, alle anderen scouter.de-Bestandteile in die Architektur der Web-App zu überführen: von PHP/jQuery zu Vue.js! Und weil man mit einer ultrafetten SPA keinen SEO-Blumentopf gewinnt, sollte das Ganze dann in eine statische Multi-Page-Applikation (oder auch Hybrid-App) überführt werden, die von jedem beliebigen Webhosting ausgeliefert werden kann.

Und hier kommt dann endgültig Nuxt ins Spiel, da hier das Zusammenspiel mit den vorhandenen Vue.js-Fragmenten mutmaßlich am besten funktionieren würde. Denn Nuxt ist zwar nicht offiziell Bestandteil des Vue.js-Projektes, aber es fühlt sich in der Praxis durchaus so an.

Warum nur statisches Hosting und kein serverseitiges JavaScript – das ist ja einer der großen Versprechen von Nuxt und Co.? Ganz ehrlich, weil ich den ganzen Node.js-Hostern wie Vercel oder netlify nicht über den Weg traue. Wenn wir schon die Website statisch rausrendern und dann „hydrieren“, dann muss der Server maximal dumm sein. Und das klappt mit Nuxt eigentlich auch ganz gut. Der vorgerenderte HTML-Code ist maximal schnell, zumindest beim Anzeigen der Einstiegsseite (egal, welche das sein mag). Sobald diese Einstiegsseite sich per JavaScript hydriert hat, verwandelt sich die MPA wieder zu einer SPA. Da sind wir dann übrigens gerade noch beim Finetuning unserer Matomo-Events.

Herausforderungen der Dynamik

Ein bisschen fummelig wird es leider in der Inhaltspflege. Hier setzen wir auf ProcessWire als Headless CMS und ein paar nicht so elegante Verrenkungen im Nuxt-Code, so dass wir zur richtigen Zeit (buildtime oder runtime?) die richtigen Daten (mit oder ohne Caching?) zur Verfügung haben.

Auch die Authentifizierung von CMS-Nutzern lösen wir manuell und nicht wahnsinnig elegant – hier wäre ein kleines bisschen Serverlogik nicht übel gewesen, aber es betrifft nur einen Spezialanwendungsfall, nicht etwa alle Carsharing-Kunden.

Was den Kunden dann noch so einfällt ;-)

Wenn man schon mal dabei ist, einen großen Relaunch zu machen, gibt es natürlich immer noch Ideen. Denn statt einfach den Systemdienstleister auszutauschen und die Website in Nuxt statt in PHP zu bauen, kann man auch gleich alles neu machen, oder?

  • Neues Screendesign
  • Neue Tarife
  • Umstellung auf einen einzelnen One-Pager für 80% der Marketing-Inhalte
  • Unorthodoxe Landingpage-UX
  • Wechsel von Google Maps auf einen eigenen Versatiles-Server (Danke an yetzt)
  • Wechsel von YouTube zu Video.Taxi

Was den Entwicklern dann noch so einfällt ;-)

Neben der „großen“ Umstellung aller Komponenten zu Nuxt, könnte man noch einen ganzen Blumenstrauß an Technologien erwähnen, die wir entweder endlich mal zum Einsatz bringen wollten, oder die wir on-the-fly während des Projektes erlernen mussten. Als da wären:

  • TypeScript, ESLint und Prettier auf dem gesamten Projekt, sogar ziemlich streng konfiguriert
  • VS Code als Code-Editor
  • Tailwind CSS für alle neu gestalteten Komponente. Das BEM-basiertes SCSS von 2016 wird schrittweise ersetzt, lebt aber aktuell noch friedlich Seit’ an Seit’ mit Tailwind
  • Ein eigener Docker-basierter Gitlab-Runner zum Deployment auf einer kleinen Linux-Büchse in meinem Waschkeller
  • MapLibre GL JS zur Anzeige von vektorbasierten Maps-Daten. Mit der Doku aus der Hölle.
  • Luxon statt moment.js
  • Pinia statt Vuex
  • FormKit für flexible Formulare in Vue.js

Die „native“ App

Bereits seit 2021 nutze ich für die Buchungsfunktion eine SPA, die über das Capacitor-Framework in eine native iOS- und Android-App gegossen wird und somit ihren Weg in die App-Stores findet. Das Schöne für uns und die Kunden: Die Buchungsfunktion auf der Website scouter.de/buchen ist absolut identisch und kommt aus der gleichen Codebasis. Lediglich ein paar Conditionals beim Build sorgen dafür, dass unten eine Tabnavigation statt einer Burger-Navigation erscheint, und im Headerbereich die Farbflächen auch die diversen Notches und Safe Areas ausfüllt.

Das funktioniert wirklich gut, und ich bin großer Fan davon. Selbstverständlich kann es eine solche App nicht mit einer ausgereiften echten Nativ-Entwicklung aufnehmen. Aber dafür wäre absolut keine Zeit gewesen. Wir haben noch in den Tagen um den Launch herum relativ fundamentale Dinge geändert, die Dynamik war atemberaubend. Wenn man das jeweils alles dreifach (Web, iOS, Android) hätte implementieren müssen – keine Chance! War haben uns schnell bewegt und Dinge zerbrochen. Dafür ist Webtechnologie dann halt doch ganz geil.

Würde ich es wieder machen?

Für genau dieses Projekt ist die gewählte Jamstack-Architektur genau das Richtige: Der pfeilschnelle statische Einstieg erfreut das Besucher- und SEO-Herz, aber gleichzeiig ist die komplexe JavaScript-Clientlogik überall auf der Website verfügbar und nicht in eine einzelne Vue-Insel eingesperrt. Das hat schon was.

Ideal zur Inhaltspflege ist es aber definitiv nicht – man kann keine frei gestaltbaren blockbasierten Seiten aufbauen oder pflegen, neue Pressemitteilungen erfordern einen Rebuild/Deployment des ganzen Projektes (dauert derzeit 7–8 Minuten). Aber es handelt sich eben nicht um eine redaktionelle Website, sondern um Marketing-Inhalte, die sich eher im Monats- oder Quartalsrhytmus ein wenig ändern, und dann auch meist sowieso noch einmal durch die Hand des Webentwicklers gehen müssen.

Das ist aber alles – zugegeben – ein bisschen Zufall, dass es hier insgesamt so gut passt. Auch in Zukunft wird ein Großteil der kleinen und mittelgroßen Websites mit einem serverseitig-dynamischen System wie Kirby oder ProcessWire am besten bedient sein.


  1. Das wollt ihr wirklich nicht wissen, was ich da gemacht habe! 

  2. Fun Fact zur aktuellen Diskussion: Die echte PWA hat laut unseren Statistiken kaum jemand benutzt)