
Unternehmenswebsite

Eine ultra-premium Unternehmens-Web- und Beratungsplattform für Emine Kaya, eine Maschinenbauingenieurin mit 35 Jahren Erfahrung in HLK und Sanitärinstallation. Mit einem 'Industrial Luxury'-Designkonzept mit dunkler, editorialer Ästhetik und hoher Leistung.
35 Jahre Ingenieursgeschichte ins Web zu bringen ist nicht wegen des Schreibens schwierig, sondern weil diese Geschichte überfliegbar werden muss: In den ersten dreißig Sekunden sucht ein Besucher die Antwort auf eine Frage — hat diese Person meine Art von Arbeit schon gemacht? Der zweite Punkt war die Kontaktaufnahme selbst. In der Beratung für mechanische Gebäudetechnik wird aus einer Anfrage nur dann ein Auftrag, wenn Leistungsart, Umfang und Budgetrahmen von Anfang an feststehen; ein Formular mit einem einzigen "Ihre Nachricht"-Feld liefert diese Informationen nicht und lässt den Besucher zudem vor einem leeren Feld stehen. Der dritte Punkt war die Sprache: Die Inhalte sollten auf Türkisch und Englisch erscheinen, und englischsprachige Besucher dürfen nicht auf einer türkischen URL landen.
Zwei Seiten. Der Besucher: meist ein Unternehmer oder Projektleiter, der vor einer Investition oder Sanierung eine Beratung sucht; er schaut auf Referenzprojekte, Fachgebiete und Chronologie, überwiegend mobil. Die Inhaberin: möchte die eingehende Anfrage in ihrem Postfach sehen, in einer Form, auf die sie direkt antworten kann — sie will kein Panel öffnen und sich in kein System einloggen.
Alleiniger Entwickler. Informationsarchitektur, zweisprachiges Routendesign, Designsystem, Animationsschicht, Kontaktstrecke und transaktionale E-Mail-Vorlagen, SEO-Struktur und Vercel-Deployment.
Next.js 16 App Router, keine Datenbank. Seiten entstehen als Server Components, interaktive Abschnitte sind in eigene Client-Komponenten ausgelagert (AboutClient, ProjectsClient, ContactClient) — die Animationsbibliothek betritt nur diese Inseln. Die zwei Sprachen laufen über lokalisierte Pfade in der pathnames-Tabelle von next-intl: dieselbe Dateisystemroute erscheint auf Türkisch als /hizmetler und auf Englisch als /services. Der einzige Schreibpfad ist das Kontaktformular: Der Client sendet ein POST an /api/contact, der Route Handler rendert React-Email- Vorlagen serverseitig zu HTML und verschickt über Resend zwei E-Mails — eine Benachrichtigung an das Unternehmen, eine Bestätigung an den Absender. Nicht definierte lokalisierte Pfade fallen über eine Catch-all-Route auf 404.
Türkische Besucher sollen /hizmetler sehen, englische /services — für Teilbarkeit wie für Sichtbarkeit in der Suche. Diese Zuordnung ist an einer Stelle definiert, in der pathnames-Tabelle von next-intl; im Dateisystem existiert eine einzige Route, die veröffentlichte URL ändert sich mit der Sprache. Die Alternative, ein eigener Ordner je Sprache, hätte bedeutet, dieselbe Seite zweimal zu schreiben.
KompromissEine neue Seite muss nun an zwei Stellen deklariert werden: in der Dateisystemroute und in der pathnames-Tabelle. Schwerer wiegt die Navigation — Links müssen aus dem Navigations-Wrapper von next-intl kommen; greift jemand aus Gewohnheit zum blanken next/link, führt der Link still in die falsche Sprache, und dieser Fehler wird zur Build-Zeit nicht erkannt. Einen veröffentlichten Pfad umzubenennen bricht außerdem die alte URL; die Weiterleitung muss von Hand geschrieben werden.
Damit aus einer Beratungsanfrage ein Auftrag wird, müssen Leistungsart, Umfang und Budgetrahmen mitkommen. Das Formular wurde in drei Schritte geteilt — Identität, Projektkontext, Nachricht — mit einem vierten Bildschirm als Absendebestätigung. Schrittweises Vorgehen senkt die Abbruchquote gegenüber derselben Feldmenge als einer langen vertikalen Liste, und jeder Schritt zeigt nur seine eigene Frage.
KompromissDer Nutzer sieht das Formular nicht auf einen Blick; wie viele Fragen noch kommen, erschließt er aus der Fortschrittsanzeige. Einen Schritt zurückzugehen, um etwas zu korrigieren, kostet zwei zusätzliche Klicks. Da der Zustand vollständig im Client liegt, geht bei einem Neuladen alles Eingegebene verloren — es gibt keine Entwurfsspeicherung.
Die Sprache der Benachrichtigungs- und Bestätigungsmail muss der Sprache entsprechen, in der das Formular ausgefüllt wurde. Der Route Handler importiert messages/tr.json und messages/en.json direkt und reicht den Wörterbuchtext an die Vorlagen weiter; einen Satz zu korrigieren heißt so nicht, an zwei Stellen zu suchen, und die Übersetzung bleibt in einer Quelle.
KompromissDas gesamte Wörterbuch — Oberflächentexte inklusive, 249 Zeilen je Sprache — landet allein zum E-Mail-Versand im Server-Bundle, während die E-Mail nur einen kleinen Teil davon braucht. Die Sprachauswahl ist außerdem eine handgeschriebene Bedingung im Route Handler: Eine dritte Sprache erfordert einen weiteren Import und einen weiteren Zweig, ein zusätzliches Wörterbuch genügt nicht.
Das Rückgrat des Designs sind Parallax-Ebenen und eine Zeitleiste, die sich mit dem Scrollen bewegt. Mit den diskreten Radschritten des Browsers liefen diese Ebenen auseinander; Lenis übernimmt das Scrollen und macht es mit einem niedrigen lerp-Wert (0,05) kontinuierlich, so dass die Ebenen auf derselben Kurve bleiben.
KompromissDas Scrollen liegt nicht mehr in der Hand des Browsers: das Springen zu einem Suchtreffer auf der Seite, das Ansteuern des Seitenendes über die Tastatur und CSS scroll-behavior sind der Bibliothek ausgeliefert. Die Bibliothek gelangt über das Root-Layout auf jede Seite, also tragen auch inhaltsorientierte Seiten diese Kosten. Bis JavaScript geladen ist, scrollt die Seite nativ und wird dann übernommen — ein in der ersten Sekunde spürbarer Verhaltenswechsel.
Es gab keine einzige Anforderung, die eine Datenbank verlangt hätte: Der Inhalt ist fest, der einzige Schreibpfad ist ein E-Mail-Versand. Deshalb wurde nie eine Persistenzschicht gebaut, und für transaktionale E-Mails fiel die Wahl auf Resend — die Anfrage landet im ohnehin geöffneten Postfach der Inhaberin, ohne dass sie ein separates Panel lernen muss. React Email erlaubt, die E-Mail-Vorlagen in derselben JSX-Sprache und gegen dasselbe Übersetzungswörterbuch zu schreiben; das bleibt lesbar, wo handgeschriebenes HTML-Tabellenlayout es nicht wäre. next-intl wurde gewählt, weil es zweisprachige Routennamen in die Routing-Schicht statt in den Anwendungscode legt. Der React Compiler ist aktiv; statt Memoization in animationslastigen Client-Komponenten von Hand zu schreiben, wurde sie dem Compiler überlassen.
Die Schreiboberfläche besteht aus einem einzigen Endpunkt: /api/contact. Dort findet eine serverseitige Pflichtfeldprüfung statt (Name, E-Mail, Nachricht), der Resend-Schlüssel und die Empfängeradresse liegen in ausschließlich serverseitig lesbaren Umgebungsvariablen, und Fehlermeldungen sind so verallgemeinert, dass nichts zum Client durchsickert. Nicht definierte lokalisierte Pfade liefern über die Catch-all-Route 404. Die bekannte Lücke gehört klar benannt: An diesem Endpunkt gibt es keine Ratenbegrenzung, keine Bot-Verifikation und keine schemabasierte Eingabevalidierung; die Felder durchlaufen weder Längengrenzen noch eine Prüfung auf Header-Injection. Der TemCraftTech-Kontaktendpunkt, den ich im selben Zeitraum geschrieben habe, besitzt all diese Schichten — der Unterschied hier ist keine bewusste Designentscheidung, sondern eine offene Lücke.
Die Seiten entstehen als Server Components; Framer Motion und Lenis gelangen nur in die Client-Inseln. Der React Compiler ist aktiv, Bilder werden über next/image als AVIF/WebP ausgeliefert, und die externe Bildquelle ist auf eine einzige Domain beschränkt. Für dieses Projekt existiert keine gespeicherte, datierte Lighthouse-Ausgabe, deshalb steht hier kein Seitengeschwindigkeitswert — angesichts des Vollbild-Videos im Hero und einer Scroll-Bibliothek im Root-Layout wäre die Behauptung eines ungemessenen Werts irreführend.
Heute würde ich den Kontaktendpunkt von Anfang an härten: Zod-Schema- Validierung, Ratenbegrenzung pro IP und eine Bot-Prüfung hätten in die erste Version gehört. Bei TemCraftTech habe ich denselben Endpunkt mit einer Upstash-gestützten Sliding-Window-Begrenzung, Turnstile, einem Honeypot und der Abweisung von CRLF-Injection gebaut; diese Anordnung hätte sich unverändert hierher übertragen lassen, und sie gehört nicht zu dem, was sich später am günstigsten nachrüsten lässt. Zweitens würde ich die beiden E-Mails nicht in einem einzigen Promise.all versenden: Wenn die Bestätigungsmail scheitert, gibt die Anfrage derzeit einen Fehler zurück, obwohl die Benachrichtigung an das Unternehmen bereits draußen sein kann — und beim erneuten Absenden trifft dieselbe Anfrage zweimal ein. Die Benachrichtigung als verpflichtend und die Bestätigung als Best-Effort zu trennen, ist die richtige Aufteilung.
Sagen Sie mir, was Sie bauen wollen; ich sage Ihnen vorab, wie lange es dauert und wo man anfängt.