diabolikss.com'u Nasıl Yaptım: Sıfırdan Canlıya, Tüm Süreç
20 Mayıs 2026

Bir pre-sales mühendisi olarak yıllardır "kişisel siteyi bir gün yapacağım" diyordum. Sonunda yaptım. Ama sadece bir "hakkımda" sayfası değil; blog, podcast arşivi, sunum sistemi, 18 farklı hesaplayıcı araç ve daha fazlasıyla tam anlamıyla bir platform. Bu yazıda baştan sona tüm süreci, aldığım kararları, yaptığım hataları ve öğrendiklerimi anlatıyorum.
Neden Yaptım?
Pre-sales mühendisliği Türkiye'de hâlâ yeterince anlaşılmayan bir rol. Müşteriye teknik derinlik ile iş değerini aynı anda sunmak zorunda olan, demo yapan, teklif yazan, soru soran ve çoğu zaman sahne arkasında kalan insanlar bunlar.
Yıllardır bu konuda not alıyordum, sunum hazırlıyordum, içerik üretiyordum. Ama hepsi dağınıktı: Medium'da bazı yazılar, Notion'da şablonlar, Obsidian'da wiki, Spotify'da podcast bölümleri. Hepsini bir çatı altında toplamak istedim. Sadece kendim için değil, bu yolda olan herkese Türkçe bir kaynak olmak için.
Teknik Stack Seçimi
Baştan şunu söyleyeyim: bu projeyi Claude ile birlikte geliştirdim. Her adımda yanımda bir teknik ortak gibi çalıştı, kod yazdı, hata ayıkladı, mimari önerdi. Ama kararlar hep bendeydi.
Neden Next.js 14? App Router ile server component ve client component ayrımı, API route'lar, statik sayfa üretimi hepsi tek çatı altında. TypeScript strict mode ile tip güvenliği, Tailwind CSS ile hızlı stil.
Neden AWS Lightsail? Basit ve öngörülü fiyatlandırma. Ubuntu 22.04 üzerinde PM2 ile Node.js sunucusu. Domain yönetimi ve S3 entegrasyonu için AWS ekosistemi içinde kalmak mantıklıydı.
PM2 neden?
Production'da next start çalıştırmak için process manager şart. Cluster mode ile performans, otomatik restart ile uptime. Build aldıktan sonra .next/BUILD_ID dosyasının varlığını kontrol etmeden deploy etme. Bu hatayı bir kez yaptım, 502 Bad Gateway ile karşılaştım, bir daha yapmadım.
Mimari: Nasıl Çalışıyor?
Yerel Geliştirme → npm run build → rsync ile sunucuya → pm2 restart
Deploy süreci bu kadar basit. Karmaşık bir CI/CD pipeline kurmak yerine rsync'i tercih ettim; küçük bir site için yeterli, hızlı ve anlaşılır.
Sayfa yapısı:
/ → Ana sayfa
/blog → Blog (302 yerel yazı + Medium)
/podcast → Podcast arşivi
/sunumlar → PDF sunum arşivi
/hesaplayici → 18 teknik hesaplayıcı
/araclar → AI araçlar
/sozluk → Terimler sözlüğü
/uses → Ekipmanlar
/hakkimda → Hakkımda
/danismanlik → Danışmanlık
/urunler → Gumroad + Amazon
Blog Sistemi
302 blog yazısı var sitede. Bunların büyük bölümü MDX formatında content/blog/ klasöründe yaşıyor. MDX'i seçmemin sebebi şu: Markdown'a React component gömebilmek. Kod blokları, özel bileşenler, her şey mümkün.
Ama bir sorun vardı: Medium'daki yazılarım burada görünmüyordu.
Medium Entegrasyonu
Medium'un RSS feed'i maksimum 10 yazı döndürür, bu bilinen bir kısıtlama. Çözümüm basit ama etkili oldu: biriktirme sistemi.
Her RSS çekişinde gelen yazıları sunucudaki bir JSON dosyasına yazıyorum. Eski yazılar silinmiyor, yeniler ekleniyor, URL bazlı deduplicate ediliyor. RSS çekimi başarısız olursa diskten olanlar dönüyor.
Medium RSS (son 10) + data/medium-posts.json (tüm arşiv) → Blog sayfası
Kapak görsellerini de otomatik çekiyorum. Medium bu işlemi curl ile engellediği için Chrome extension üzerinden fetch ile og:image meta etiketlerini aldım.
Tag Filtresi ve URL Sorunu
Blog'da tag filtrelemesi vardı ama URL değişmiyordu. /blog?tag=pre-sales diye bir şey yoktu. Sayfayı yenilersen filtre gidiyor, linki paylaşamazsın.
useSearchParams hook'u ile çözdüm. Tag'e tıklayınca router.push('/blog?tag=...') çağrılıyor, URL güncelleniyor. Sayfa yenilenince de aynı filtreli haliyle açılıyor. Küçük bir değişiklik, büyük kullanıcı deneyimi farkı.
Sunum Arşivi: AWS S3 ve PDF Viewer
Bu kısmı en çok zaman alan ve en çok keyif aldığım özellikti.
Pre-sales mühendisleri sunum hazırlar. Çok sunum. Bunları "indirin" deyip Google Drive linki paylaşmak yerine, tarayıcı içinde görüntülenebilir bir arşiv istedim.
Mimari Kararı: Private S3 ve Presigned URL
PDF'leri public yapmak yerine private bucket'ta tuttum. Kullanıcı bir sunuma erişmek istediğinde Next.js API route devreye giriyor, AWS SDK üzerinden 60 dakika geçerli bir imzalı URL üretiyor. Bu URL react-pdf tarafından kullanılıyor, PDF canvas üzerinde render ediliyor.
Avantajı şu: dosyalar direkt indirilemez, URL DOM'da görünmez ve süresi dolar.
PDF Viewer Özellikleri
- Klavye ok tuşlarıyla sayfa geçişi
- Sayfa sayacı
- Presigned URL gelene kadar loading spinner
- "Blog yazısını oku" linki: her sunumu ilgili blog yazısıyla bağladım
Blog URL Alanı
İlk versiyonda blogPostSlug adında bir alan vardı, yerel blog slug'ına yönlendiriyordu. Ama yazılarım Medium'daydı. Düzelttim: blogUrl alanı tam URL kabul ediyor. Admin panelinde Medium linkini yapıştırıyorum, otomatik çalışıyor.
Admin Paneli
Sunum eklemek için ayrı bir admin paneli yaptım. PDF ve thumbnail yükleme, metadata düzenleme, silme. Form submit edilince PDF S3'e yükleniyor, data/presentations.json güncelleniyor.
18 Hesaplayıcı Araç
Bu kısım projenin en büyük bölümü. Pre-sales mühendisleri çok hesap yapar: depolama kapasitesi, yedekleme penceresi, network bant genişliği, TCO karşılaştırması... Bunları her seferinde Excel'de yapmak yerine interaktif web araçları olsun istedim.
5 kategori, 18 araç:
Depolama ve RAID RAID 0/1/5/6/10 kapasite hesabı. Deduplikasyon ve sıkıştırma oranı tasarrufu. Storage büyüme projeksiyonu.
Yedekleme Veeam repository boyutlandırması. Restore süre tahmini. LTO-10 bant arşivi hesabı.
Sanallaştırma Burada 5 platform desteği var: VMware, Nutanix, Sangfor, Verge.io ve HPE VM Essentials. Her platform için farklı overhead oranları, yönetim RAM'i ve lisans maliyeti hesaplanıyor. Ama lisans için rakam vermedim, kalitatif etiketler kullandım: "Çok Yüksek", "Yüksek", "Orta". Çünkü fiyatlar değişken.
Network Bant genişliği ihtiyacı, WAN/SD-WAN TCO karşılaştırması, switch katman mimarisi, firewall throughput hesabı. Bu araçlarda özellikle dikkat ettiğim bir şey var: tüm TL bazlı tahminlerin yanında belirgin uyarı kutuları koydum.
Pre-Sales ve TCO On-Prem vs Cloud karşılaştırması (AWS/Azure, kur senaryoları), veri merkezi OpEx normalizasyonu (₺/VM, ₺/TB, ₺/rack), ROI hesaplayıcı (NPV, payback süresi), lisans modeli karşılaştırması (Perpetual vs Subscription, break-even yılı).
Teknik Detay: useCountUp
Her araçta sonuçlar animasyonlu sayıyor. Sıfırdan hedef değere cubic ease ile, requestAnimationFrame tabanlı bir hook. Görsel olarak etkili, performans açısından da temiz.
Yaşanan Bir Hata
BantGenligi.tsx dosyasında TypeScript'te Set<string> yerine Set<AppId> yazmalıydım. ESLint ise ternary'i statement olarak kullanmama izin vermedi. Bu hatalar build'i kırdı, sunucuya eksik .next/ klasörü gönderildi, 502 Bad Gateway aldım.
Öğrendiğim ders: her build sonrası .next/BUILD_ID dosyasının varlığını kontrol et, sonra deploy et.
Ekipmanlar Sayfası
"Uses" sayfası teknoloji dünyasında çok yaygın bir format ama Türkçe'de pek yok. Günlük kullandığım donanım, yazılım, AI araçları ve servisleri listeledim. Reklam veya sponsorluk yok, sadece gerçekten kullandıklarım.
MacBook Air M2, yıllardır sadık kalan HP Pavilion 24xw monitör, Logitech G305, AirPods. Yazılım tarafında Evernote, Notion, Obsidian, Canva. AI araçlarında Claude her şeyin başı, Gemini görsel üretim için, NotebookLM podcast üretim hattımın kalbi.
Podcast Üretim Hattım
Bu konuyu ayrı bir yazıda detaylı anlatacağım ama kısaca: Obsidian'daki notlar ve Claude ile kaynak bulma, ardından NotebookLM'de içerik hazırlama ve son olarak Spotify Podcast'e yükleme. Neredeyse tamamen otomatize bir süreç.
Küçük Ama Önemli Detaylar
ytkisa: YouTube link kısaltıcı aracım ayrı bir sunucuda HTTP üzerinden çalışıyor. Ana site HTTPS olduğu için iframe içinde gösteremiyorum; mixed content güvenlik kuralı bunu engelliyor. Domain alınca düzelecek. Şimdilik "Yeni sekmede aç" butonu var.
Sunumlar filtresi: Başta sadece tag filtresi vardı. Arama ve tarih sıralaması ekledim. Küçük dokunuş, büyük fark.
Medium RSS biriktirme: İlk kurulumda 10 yazı geldi. Her iki saatte bir RSS çekildiğinde yeni yazılar ekleniyor, arşiv büyüyor. Şu an 17 yazı var.
Karşılaştığım Zorluklar
1. TypeScript strict mode ile ESLint: Her kullanılmayan değişken, her ternary statement, her eksik dependency array build'i kırıyor. Başlarda sinir bozucu geldi, sonra fark ettim ki bu kurallar gerçek hataları önlüyor.
2. Medium görselleri:
curl ile çekemiyorum, WebFetch JavaScript render etmiyor. Çözüm: Chrome extension üzerinden fetch çağrısı. Biraz dolaylı ama çalışıyor.
3. Deploy sonrası 502 hataları:
Her zaman aynı sebep: build hatası var, BUILD_ID oluşmamış, eksik .next/ sunucuya gönderilmiş. Önce ls .next/BUILD_ID, sonra deploy.
4. Kategori navigasyonu:
İki seviyeli navigasyon (kategori ve araç sekmeleri) ilk başta karmaşıktı. CATEGORY_DEFAULT mapping'i ile çözdüm; her kategori değişiminde varsayılan araç otomatik seçiliyor.
Sonuç
Projeyi bitirdiğimde elimde şunlar var: 302 blog yazısı, Medium entegrasyonu, podcast arşivi, 4 sunum ve PDF viewer, 18 hesaplayıcı araç, ekipmanlar sayfası, admin paneli, arama sistemi.
Hepsi tek domain altında, tutarlı bir tasarımla, gerçekten çalışan özelliklerle.
Bu projeyi yaparken en çok şunu öğrendim: küçük ama tamamlanmış, büyük ama yarım kalandan çok daha değerli. Her özelliği deploy edip canlıda görünce bir sonrakine geçmek için motivasyon geliyor.
Eğer siz de benzer bir şey yapıyorsanız ya da yapmayı düşünüyorsanız, sormak istedikleriniz için buradayım.
Mehmet Aydın · Mayıs 2026 diabolikss.com
Bu Yazıdaki Terimler
Tüm Sözlük →Danışmanlık
Bu konular hakkında konuşmak ister misiniz?


