Zum Hauptinhalt
Zurück zu Projekten
Emine Kaya Engineering logo

Emine Kaya Engineering

Unternehmenswebsite

Emine Kaya Engineering

Eine Unternehmens- und Beratungswebsite, die ich für Emine Kaya entwickelt habe, eine Maschinenbauingenieurin mit 35 Jahren Erfahrung in HLK und Sanitärinstallation. Sie stellt diese Erfahrung auf Türkisch und Englisch übersichtlich dar, und ein vierstufiges Kontaktformular klärt Art und Umfang jeder Anfrage von Anfang an.

Verwendete Technologien

  • Next.js 16
  • TypeScript
  • Tailwind CSS
  • Framer Motion
  • next-intl
  • Lenis

Hauptmerkmale

  • Kinematischer Hero-Bereich — Vollbild-Video mit Wort-für-Wort-Enthüllungstypografie
  • Parallax-SVG-Raster und Spotlight-Hover-Effekt-Kompetenzkarten
  • 4-stufiges interaktives Kontaktformular mit Glasmorphismus-Design
  • Scroll-Timeline und Split-Screen-Über-uns-Bereich
  • Lenis Smooth Scroll und Seitenübergangsanimationen

Entwicklungszeit

1 Monat

Problem

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.

Nutzer

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.

Meine Rolle

Alleiniger Entwickler. Informationsarchitektur, zweisprachiges Routendesign, Designsystem, Animationsschicht, Kontaktstrecke und transaktionale E-Mail-Vorlagen, SEO-Struktur und Vercel-Deployment.

Architektur

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.

Zentrale Entscheidungen

  1. Routennamen stehen in der Routing-Tabelle, nicht im Übersetzungswörterbuch

    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.

  2. Das Kontaktformular ist eine dreistufige Strecke, kein einzelnes Feld

    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.

  3. E-Mail-Texte werden aus demselben Übersetzungswörterbuch gespeist wie die Oberfläche

    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.

  4. Das Scrollverhalten wurde dem Browser entzogen und an Lenis übergeben

    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.

Technologiewahl

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.

Sicherheit

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.

Performance

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.

Ergebnisse

Aktive Entwicklung
2026-02 · 17 Commits
TypeScript-Quelldateien
38
Lokalisierte Routen
2 Sprachen × 6 Pfade
Architektonische Garantie
Ein nicht definierter lokalisierter Pfad liefert 404 und rutscht nicht in eine andere Sprache
Entwicklungszeit
1 Monat

Was ich heute anders machen würde

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.

Finden wir gemeinsam den richtigen Einstieg

Sagen Sie mir, was Sie bauen möchten; ich sage Ihnen vorab, wie lange es dauert und was der sinnvolle erste Schritt ist.