İçeriğe Geç
Tüm Yazılar

Ürün5 Dakika Okuma

ahmetakyapi.com: Bu Siteyi Nasıl Kurdum

Projelerimi, yazdıklarımı ve kim olduğumu tek adreste toplamak için kurduğum site. Neden hazır bir şablon kullanmadım, sitede ne var, hangi teknolojileri seçtim ve hızlı kalması için neler yaptım.

Bu Yazıda10 Bölüm

Bir süre sonra projelerim GitHub’a, yazdıklarım not defterlerine, ekran görüntüleri de telefonun galerisine dağılmıştı. Birine “neler yapıyorsun” diye sorulduğunda gösterecek tek bir adres yoktu. ahmetakyapi.com o adres: projelerim, her birinin nasıl yapıldığını anlatan yazılar ve kim olduğum, hepsi aynı yerde. Şu an okuduğun sayfa da onun bir parçası.

Neden Kendim Yazdım

Hazır bir portfolyo şablonu ya da bir blog platformu işimi görürdü, hem de bir günde. Ama bu site aynı zamanda bir vitrin. Arayüz işi yapan birinin sitesi, nasıl iş çıkardığını da göstermeli; hazır şablonda yazı tipinden geçiş animasyonuna kadar her şey başkasının kararı oluyor.

Bir de deneme alanı lazımdı. Tarayıcıya yeni gelen özellikleri, mesela sayfalar arası geçişleri ya da kaydırmaya bağlı CSS animasyonlarını iş projesinde hemen kullanamıyorsun. Kendi sitende kullanıp nerede iyi, nerede sorunlu olduğunu görebiliyorsun. Bu sitedeki her şey önce burada denendi.

Sitede Neler Var

  1. Ana Sayfa

    Kısa bir tanıtım, sürükleyip döndürebildiğin bir dünya küresi, öne çıkan üç proje, iş deneyimim ve son yazılar.

  2. Projeler

    On üç proje; her birinin masaüstü ve telefon ekran görüntüleri, kullandığı teknolojiler, canlı adresi ve kaynak kodu. Platform, oyun ve araç diye süzülebiliyor. Listeden bir projeye tıklayınca görseli büyüyüp detay sayfasının kapağı oluyor.

  3. Yazılar

    Projelerin arkasındaki kararları anlatan yazılar. İçindekiler, kod blokları, tablolar, karşılaştırma kutuları ve GitHub üzerinden yorumlar var. Etikete göre süzme tamamen CSS ile çalışıyor.

  4. Komut Paleti

    ⌘K ya da Ctrl+K ile açılıyor; sayfalara, projelere, yazılara ve tema değişimine klavyeden ulaşıyorsun.

  5. Paylaşım Kartları

    Her proje ve yazı için bağlantı önizlemesi otomatik çiziliyor. Başlığı değiştirdiğimde kart da kendiliğinden güncelleniyor.

Kullandığım Teknolojiler

ParçaNe KullandımNeden
ÇatıNext.js 16, React 19, TypeScriptSayfalar derleme anında hazırlanıyor, sunucu bileşenleri tarayıcıya gereksiz JavaScript göndermiyor.
StilTailwind CSS v4Renkler ve boşluklar tek bir token dosyasında; açık ve koyu tema aynı değişkenlerden besleniyor.
GeçişlerView TransitionsSayfa değişirken içerik kayarak geliyor, proje kartı detay sayfasının kapağına dönüşüyor.
AnimasyonCSS kaydırma zaman çizelgesiKaydırınca beliren her şeyi tarayıcı yürütüyor; JavaScript yok.
İçerikTypeScript dosyalarıYazılar ve projeler kodun yanında, tipli; yanlış bir alan derlemeyi durduruyor.
Paylaşım GörseliSatoriHer proje ve yazı için kendi bağlantı önizlemesi derlemede üretiliyor.
YorumlarGiscusYorumlar GitHub Discussions’ta duruyor; veritabanı tutmam gerekmiyor.
YayınVercelAna dala gönderdiğim an birkaç dakikada canlıda.

Sayfalar Neden Statik

Bir portfolyonun içeriği her ziyarette değişmiyor. O yüzden bütün sayfalar derleme sırasında bir kez üretiliyor ve ziyaretçiye hazır HTML olarak gidiyor. Sunucuda her istekte çalışan bir kod yok; sayfa CDN’den anında geliyor.

Tema seçimi bunu zorlaştıran tek şeydi. Tema bir çerezde duruyor ve sunucu çerezi okursa her sayfa dinamik oluyor, yani her ziyaret bir fonksiyon çağrısına dönüyor. Bunun yerine sayfanın başına birkaç yüz baytlık küçük bir betik koydum: ilk boyamadan önce çerezi okuyup doğru temayı yazıyor. Sayfa statik kalıyor, yanlış tema bir an bile görünmüyor.

lib/theme.ts
// <head> içinde, her şeyden önce çalışır (sadeleştirilmiş hâli).
const m = document.cookie.match(/(?:^|; )theme=(dark|light)/)
document.documentElement.dataset.theme = m ? m[1] : 'light'

Geçişler: Sayfa Değişirken Kopukluk Olmasın

Bir projeye tıkladığında listedeki kapak görseli büyüyüp detay sayfasının kapağı oluyor. Bunu tarayıcının View Transitions özelliği yapıyor; React 19’daki ViewTransition bileşeni de onu Next.js’in gezinmesine bağlıyor. Benim yaptığım tek şey iki uçtaki görsele aynı adı vermek.

ProjectCover.tsx
<ViewTransition name={`project-${slug}`} share="morph" default="none">
  <div className="aspect-[16/10] overflow-hidden rounded-card">
    <ThemedImage {...shot} alt={title} />
  </div>
</ViewTransition>

Tarayıcı iki görselin konumunu ve boyutunu kendisi ölçüp aradaki hareketi çiziyor. Desteklemeyen tarayıcıda sayfa normal şekilde açılıyor; kaybedilen tek şey animasyon.

Animasyonlar Neden CSS

Sitenin ilk hâlinde animasyonlar için framer-motion kullanıyordum. Ana sayfanın indirdiği JavaScript’in yarısına yakını o kütüphaneydi. Yaptığı işlere tek tek bakınca hepsinin CSS ile yapılabildiğini gördüm ve kaldırdım.

Kaydırınca beliren kartlar artık animation-timeline: view() ile çalışıyor. Eleman ekrana girdikçe animasyon ilerliyor; zamanlayıcı da gözlemci de yok. Hepsi bir @supports bloğunun içinde, yani desteklemeyen tarayıcıda içerik zaten görünür hâlde duruyor.

İlk Yüklemede İnen JavaScript (KB)
Ana Sayfa
181 → 104
Projeler
179 → 99
Yazı Sayfası
146 → 104

Hareketi azaltmayı seçmiş biri için animasyonların hepsi kapalı. Sayfa aynı, sadece kıpırdamıyor.

Küçük Ama Benim İçin Önemli Parçalar

Dünya Küresi

Ana sayfadaki küre bir harita kütüphanesi değil, düz bir <canvas>. Şehirleri enlem ve boylamdan ekrana çeviren birkaç satır trigonometri, aralarındaki yaylar ve üzerlerinde akan küçük noktalar. İstanbul’a dönük açılıyor; parmağınla ya da fareyle çevirebiliyorsun. Ekrandan çıkınca ya da sekme arkadayken çizim duruyor, pil yemiyor.

İmza

Başlıktaki el yazısı “Ahmet Akyapı” bir yazı tipi değil, SVG yolu. Yazı tipi indirilmediği için sayfa yüklenirken harfler kaymıyor; sayfa açılırken de kalem kâğıtta ilerliyormuş gibi soldan sağa yazılıyor.

Kod Boyayıcı

Yazılardaki kod blokları için hazır bir kütüphane kullanmadım. Yazılarda geçen dil sayısı beş; bunun için yazdığım küçük boyayıcı birkaç kilobayt tutuyor ve renkleri temadan alıyor.

Ekran Görüntüleri

Her projenin görseli açık ve koyu temada ayrı çekildi. İkisi de sayfada duruyor, hangisinin görüneceğine CSS karar veriyor; JavaScript beklenmiyor. Görseller zaten gösterileceği boyutta WebP, o yüzden bir optimizasyon servisine de ihtiyaç kalmadı.

İçerik Nasıl Yazılıyor

Yazılar bir veritabanında ya da Markdown dosyalarında değil, TypeScript dosyalarında duruyor. Her yazı bir blok listesi: paragraf, başlık, kod, tablo, karşılaştırma, adım adım akış. Bu sayede yazının içine tasarımı bozacak bir şey giremiyor; tanımadığı bir blok türü yazarsam derleme hemen hata veriyor. Bunun neden böyle olduğunu ayrı bir yazıda anlattım.

Başlık ve özet aynı dosyadan sitede, RSS’te ve paylaşım görselinde kullanılıyor. Okuma süresi de elle yazılmıyor, içerikten hesaplanıyor.

Telefonda da Rahat Olsun

Ziyaretlerin çoğu telefondan geliyor, o yüzden her sayfayı önce dar ekranda kontrol ediyorum. Tablolar telefonda yana kaymıyor, her satır kendi kartına dönüşüyor. Küre dikey kaydırmayı engellemiyor: hızlı kaydırırsan sayfa iner, basılı tutarsan küre döner. Başlık çentiğin altında kalmıyor, alt menü güvenli alana göre yerleşiyor.

Sırada Ne Var

Bu sitenin kendi ekran görüntüleri henüz yok; projeler sayfasında adından çizilen bir kapakla duruyor. Bir de yazıların İngilizce çevirilerini eklemek istiyorum. Site bitmiş bir şey değil; yeni bir şey öğrendikçe önce burada deniyorum.

İlgili Proje

Portfolyo

ahmetakyapi.com

Şu an gezdiğin site. Projelerim, her birinin nasıl yapıldığını anlatan yazılar ve kim olduğum tek bir adreste.

Projeyi İncele

Diğer Yazılar

Tüm Yazılar
  1. Açılış Zili: ABD Borsasını Doğru Takip Etmek3 Ekim 2026 · 7 Dakika
  2. One Piece Hub: Spoiler Vermeyen Türkçe Wiki1 Eylül 2026 · 6 Dakika
  3. Açılış Zili: ABD Borsasını Türkçe Takip Eden Site12 Ağustos 2026 · 8 Dakika