
Kurumsal Web Sitesi

35 yıllık makina mühendisliği ve mekanik tesisat tecrübesine sahip Emine Kaya için tasarlanmış ultra-premium kurumsal web ve danışmanlık platformu. 'Industrial Luxury' konseptinde karanlık, editoryal ve yüksek performanslı bir tasarım.
35 yıllık bir mühendislik geçmişini web'e taşırken asıl zorluk metin yazmak değil, o geçmişi taranabilir hâle getirmek: ziyaretçi ilk otuz saniyede "bu kişi benim işimi yapmış mı" sorusunun cevabını arıyor. İkinci mesele iletişimin kendisiydi. Mekanik tesisat danışmanlığında gelen talebin işe dönüşmesi için hizmet türü, ölçek ve bütçe aralığının baştan belli olması gerekiyor; tek kutulu bir "mesajınız" formu bu bilgiyi getirmiyor, getirse bile ziyaretçiyi boş bir alanla baş başa bırakıyor. Üçüncüsü dil: içerik hem Türkçe hem İngilizce yayınlanacaktı ve İngilizce ziyaretçinin Türkçe URL'e düşmemesi gerekiyordu.
İki taraf. Ziyaretçi: çoğunlukla bir yatırım veya tadilat öncesi danışman arayan işletme sahibi ya da proje yöneticisi; referans projelere, uzmanlık alanlarına ve kronolojiye bakıyor, mobilde geziyor. İşletme sahibi: gelen talebi e-posta kutusunda, doğrudan yanıtlanabilir biçimde görmek istiyor — panel açmak, sisteme girmek istemiyor.
Tek geliştirici. Bilgi mimarisi, iki dilli rota tasarımı, tasarım sistemi, animasyon katmanı, iletişim akışı ve işlemsel e-posta şablonları, SEO yapısı ve Vercel dağıtımı.
Next.js 16 App Router, veritabanı yok. Sayfalar Server Component olarak üretiliyor, etkileşimli bölümler ayrı istemci bileşenlerine (AboutClient, ProjectsClient, ContactClient) ayrılmış — animasyon kütüphanesi yalnız bu adacıklara giriyor. İki dil, next-intl'in pathnames tablosuyla yerelleştirilmiş yollar üzerinden yürüyor: aynı dosya sistemi rotası Türkçe'de /hizmetler, İngilizce'de /services olarak yayınlanıyor. Tek yazma yolu iletişim formu: istemci /api/contact'a POST atıyor, route handler React Email şablonlarını sunucuda HTML'e render edip Resend üzerinden iki e-posta gönderiyor — biri işletmeye bildirim, biri kullanıcıya onay. Tanımlı olmayan yerelleştirilmiş yollar catch-all rotadan 404'e düşüyor.
Türkçe ziyaretçinin /hizmetler, İngilizce ziyaretçinin /services görmesi gerekiyordu — hem paylaşılabilirlik hem arama görünürlüğü için. Bu eşleme next-intl'in pathnames tablosunda tek yerde tanımlı; dosya sisteminde tek bir rota var, yayınlanan URL dile göre değişiyor. Alternatif olan her dil için ayrı klasör açmak, aynı sayfayı iki kez yazmak demekti.
ÖdünleşimYeni bir sayfa artık iki yerde tanımlanmak zorunda: dosya sistemi rotası ve pathnames tablosu. Daha ağır bedel gezinme tarafında — bağlantılar next-intl'in kendi navigation sarmalayıcısından gelmek zorunda; biri alışkanlıkla çıplak next/link kullanırsa bağlantı sessizce yanlış dile gider ve bu, derleme zamanında yakalanmaz. Yayınlanmış bir yolun adını değiştirmek de eski URL'i kırıyor; yönlendirmeyi elle yazmak gerekiyor.
Danışmanlık talebinin işe dönüşmesi için hizmet türü, ölçek ve bütçe aralığının baştan gelmesi gerekiyor. Form üç adıma bölündü — kimlik, proje bağlamı, mesaj — ve dördüncü ekran gönderim onayı. Adım adım ilerlemek, aynı alanları tek sayfada dikey bir liste hâlinde göstermeye göre terk oranını düşürüyor ve her adımda yalnızca o adımın sorusu görünüyor.
ÖdünleşimKullanıcı formun tamamını bir bakışta göremiyor; kaç soru kaldığını ilerleme göstergesinden tahmin ediyor. Bir önceki adıma dönüp bir şeyi düzeltmek fazladan iki tıklama. Durum tamamen istemcide tutulduğu için sayfa yenilenirse girilen her şey kayboluyor — taslak saklama yok.
Bildirim ve onay e-postalarının dili, formun doldurulduğu dille aynı olmalı. Route handler messages/tr.json ve messages/en.json'u doğrudan import ediyor ve şablonlara sözlükten gelen metni geçiriyor; böylece bir cümleyi düzeltmek için iki ayrı yere bakmak gerekmiyor, çeviri tek kaynakta kalıyor.
ÖdünleşimSözlüğün tamamı — arayüz metinleri dahil, dil başına 249 satır — e-posta göndermek için sunucu paketine giriyor; e-postanın ihtiyaç duyduğu kısım bunun küçük bir bölümü. Ayrıca dil seçimi route handler içinde elle yazılmış bir koşul: üçüncü bir dil eklemek bir import ve bir dal daha yazmayı gerektiriyor, sözlüğü eklemek yetmiyor.
Tasarımın omurgası parallax katmanları ve kaydırmayla ilerleyen bir zaman çizelgesi. Tarayıcının kesikli tekerlek adımlarıyla bu katmanlar birbirinden kopuk hareket ediyordu; Lenis kaydırmayı devralıp düşük bir lerp değeriyle (0.05) sürekli hâle getiriyor ve katmanlar aynı eğri üzerinde kalıyor.
ÖdünleşimKaydırmanın kontrolü artık tarayıcıda değil: tarayıcı içi arama ile bir sonuca atlama, klavyeyle sayfa sonuna gitme ve CSS scroll-behavior davranışları kütüphanenin insafına kalıyor. Kütüphane kök düzende her sayfaya giriyor, yani içerik odaklı sayfalar da bu maliyeti taşıyor. JavaScript yüklenene kadar kaydırma normal davranıyor, sonra ele geçiriliyor — ilk saniyede hissedilen bir davranış değişimi.
Veritabanı gerektiren tek bir ihtiyaç yoktu: içerik sabit, tek yazma yolu bir e-posta gönderimi. Bu yüzden kalıcı katman hiç kurulmadı ve işlemsel e-posta için Resend seçildi — talep, işletme sahibinin zaten açık olan e-posta kutusuna düşüyor, ayrı bir panel öğrenmesi gerekmiyor. React Email, e-posta şablonlarının aynı JSX diliyle ve aynı çeviri sözlüğüyle yazılmasını sağlıyor; HTML tablo düzenini elle yazmaya göre okunabilir kalıyor. next-intl, iki dilli rota adlarını uygulama koduna değil yönlendirme katmanına yerleştirdiği için tercih edildi. React Compiler açık; animasyon yoğun istemci bileşenlerinde memoization'ı elle yazmak yerine derleyiciye bırakıldı.
Yazma yüzeyi tek bir uçtan ibaret: /api/contact. Bu uçta sunucu tarafında zorunlu alan kontrolü (ad, e-posta, mesaj) yapılıyor, Resend anahtarı ve alıcı adresi yalnız sunucuda okunabilen ortam değişkenlerinde tutuluyor ve hata mesajları istemciye içerik sızdırmayacak biçimde genelleştiriliyor. Tanımlı olmayan yerelleştirilmiş yollar catch-all rotadan 404 dönüyor. Bilinen eksik açıkça söylenmeli: bu uçta oran sınırlama, bot doğrulaması ve şema tabanlı girdi doğrulaması yok; alanlar uzunluk sınırından ve başlık enjeksiyonu kontrolünden geçmiyor. Aynı dönemde yazdığım TemCraftTech iletişim ucunda bu katmanların tamamı mevcut — buradaki fark bilinçli bir tasarım tercihi değil, kapatılmamış bir açık.
Sayfalar Server Component olarak üretiliyor; Framer Motion ve Lenis yalnızca istemci adacıklarına giriyor. React Compiler açık, görseller next/image üzerinden AVIF/WebP olarak sunuluyor ve uzak görsel kaynağı tek bir alan adıyla sınırlandırılmış. Bu proje için saklanmış, tarih damgalı bir Lighthouse çıktısı bulunmadığından buraya sayfa hızı skoru yazılmadı — hero'daki tam ekran video ve kök düzene giren kaydırma kütüphanesi göz önüne alındığında ölçülmemiş bir skor iddia etmek yanıltıcı olurdu.
İletişim ucunu bugün baştan sertleştirirdim: Zod ile şema doğrulama, IP başına oran sınırlama ve bir bot kontrolü, ilk sürümde yazılmalıydı. TemCraftTech'te aynı ucu Upstash tabanlı kayan pencere limiti, Turnstile, honeypot ve CRLF enjeksiyonu reddiyle kurdum; oradaki dizilim buraya olduğu gibi taşınabilirdi ve bu, sonradan eklenmesi en pahalı olan şey değil. İkinci olarak iki e-postayı tek bir Promise.all içinde göndermezdim: şu hâliyle onay maili başarısız olursa istek hata dönüyor, oysa işletmeye bildirim çoktan gitmiş olabiliyor — kullanıcı formu tekrar gönderdiğinde aynı talep iki kez düşüyor. Bildirimi zorunlu, onayı en iyi çaba olarak ayırmak doğru ayrım.
Ne yapmak istediğinizi anlatın; ne kadar süreceğini ve nereden başlanacağını baştan söylerim.