|

vefacaglar com

bu sitenin amacı?

yıllardır basit bir hobi sitesi yapmak istiyordum fakat kafamdaki şeyi yapma konusunda yeterli zamanım ve enerjim hiç bir zaman olmadı. fakat yaklaşık 6 aydır güzel boş zamanım oldu, geliştirme süreleri çok kısaldı ve teknoloji çok gelişti. eskisi gibi hosting kirala filezilla ile yolla gibi bir yaklaşım da yok artık.

2017 yılında art dada'da çalışmaya başladığımda websiteleri yapmaya başlamıştım, psd tasarımını html css e dönüştürüyordum fakat sayfalar arasında gezerken hep sayfanın refresh olması rahatsız ediyordu beni. angular ve react gibi teknolojileri denemiştim ama onlar da sayfa açıldıktan sonra render olduğundan seo tarafı yoktu. ssr diye bir teknoloji olduğunu öğrenmiştim, ara ara öğrenmeye meyillenmiştim fakat kariyerim beni backend tarafa daha çok ittiği için ön yüzden uzaklaşmıştım. hatta son 6 yıldır neredeyse sadece backend ve mikroservislerle çalışıyorum.

ssr konularını halletmiş olsam bile başka bir problemim vardı, nodejs veya .net core çalıştıran hosting sayısı bile oldukça azdı o yıllarda. digitalocean gibi sitelerden droplet kiralayıp türlü taklalarla linux ile uzaktaki sunucuya bağlanıp nginx kurup çok basit nodejs uygulamalarını atıp çalıştırabilmiştim fakat bunlar saatlerimi alıyordu. zaten kariyerimde mimari tarafa doğru yöneldiğim için daha çok microservis kısımlarına ve mimari tarafa odaklandım.

günümüzde yapay zeka araçlarıyla syntax kısmına çok hakim olmadan mimari ve teknoloji tarafındaki bilgilerle aklımdaki şeyleri koda dökmek oldukça kısaldı. hem bolca zamanımda var artık. yer aldığım projelerdeki yaşadığım tecrübeleri, izlediğim filmler hakkında yorumlar yapmayı, oynadığım oyunları paylaşmayı ve gittiğim konserleri paylaşmayı istediğim tamamen hobi amaçlı bir şeyleri denediğim bu web sitesini geliştirdim.

sitenin yapısı

markdown odaklı bir yapı kurdum olabildiğince esnek olması için. çok aşırı mühendislik kasmadan mdx odaklı içeriklerle istediğim kadar esnetebiliyorum içerikleri ve sayfaları.

yer aldığım projeleri paylaşmak için ayrı bir tablo yapısı kurguladım, projeye ile postları henüz bağlamadım ama ilişki kurabilirim. proje sayfası gibi düşünerek.

sayfa ayrı bir tabloda, blog yazıları gibi değil onlar. home ve about sayfaları için fixed home ve about slug'ına ait pages datasından çekiyorum.

mimari genel bakış

monorepo yapısı: turborepo + pnpm workspace. iki uygulama, iki paket.

genel yapı

proje bir Turborepo + pnpm workspace olarak organize edildi. Tek bir repoda iki uygulama ve iki paylaşılan paket var:

  • `apps/web` — Next.js 14, public site ve dashboard
  • `apps/api` — Fastify ile yazılmış REST API
  • `packages/db` — Drizzle ORM şemaları ve migration'lar
  • `packages/shared` — iki tarafın da kullandığı küçük TypeScript yardımcıları

monorepo seçmemin sebebi basit: frontend, backend ve veritabanı şemaları birbirine bağlı olarak evriliyor. Şemayı değiştirdiğimde API ve UI'ı aynı commit içinde güncelleyebilmek hayatı kolaylaştırıyor.

frontend — `apps/web`

frontend tarafında Next.js 14'ün App Router'ını kullanıyorum. Public sayfalar (`/`, `/about`, `/blog`, `/projects`) `src/app/` altında klasik App Router yapısında duruyor. İçerik yönetimi için ayrı bir route grubu var: `src/app/dashboard/`. Burada yazıları ve sayfaları yönetiyorum.

public sayfalar, API'den veri çekerken normal `fetch` kullanıyor. dashboard ise API'ye Next.js server actions üzerinden gidiyor; yani form post'ları doğrudan server'da çalışıyor, ayrıca bir endpoint açmama gerek kalmıyor. Bu ayrım sayesinde "okunan" ile "yazılan" yollar net biçimde ayrılıyor.

stil tarafında bilinçli olarak sade kaldım: düz CSS ve CSS Modules. Tailwind ya da ağır bir UI kütüphanesi eklemedim. Kişisel bir site için bunlar fazladan yük; CSS Modules yeterince izole, yeterince okunaklı.

blog yazılarının gövdesi markdown olarak veritabanında duruyor ve sayfada `next-mdx-remote` ile render ediliyor.

backend — `apps/api`

API tarafında Fastify kullanıyorum. Express'ten daha hızlı, ve daha önemlisi şema tabanlı çalışmaya doğal biçimde uyum sağlıyor.

şema tanımları için TypeBox seçtim. Bunun güzel tarafı tek bir şemadan hem runtime validation hem de TypeScript tipleri elde edebiliyor olmam (`Static<typeof Schema>`). Üstüne bonus olarak swagger dokümantasyonu otomatik üretiliyor — `/swagger` adresinden gezilebilir.

API'nin iç organizasyonunu Feature Folder / Handler pattern ile yapıyorum. son 2 yıldır .net tarafında cqrs yaklaşımıyla geliştirme yaptığım için o yapıyı bozmak istemedim.

repoya buradan ulaşabilirsiniz.

canlıya alma

tahmin ettiğimden çok daha kolay ve maliyetsiz oldu. hatta sıfır maliyet diyebilirim. eskiden free websitesi yayınlamak için heroku veya azurewebsites kullanabiliyorduk fakat dns yönlendirmesi yapmak için para vermemizi istiyolardı.

günümüzde veritabanından uygulamalara kadar her şeyi free yayınlayabiliyoruz hatta full devops araçlarını ücretsiz ve çok kolay kullanabiliyoruz.

ilk önce free db aradım, mongo veya postgresql kullanmayı düşünüyordum fakat typesafe gitmek isteyip postresql devam ettim. neon veya vercelin free paketleri vardı kredi kartı istemeyen. onlardan birini kullandım.

ön yüzü vercelde, api tarafınıda render a deploy etmeyi planlıyordum fakat ön yüzü publish ederken vercel'in fastify desteğini de görünce ikisini de aynı yere deploy ettim. olurda kaynaklar yetmez ise vercel + render yapısına geçirebilirim veya hiç uğraşmayıp parası neyse verebilirim.

her neyse bir kaç tık ile ikisini de deploy ettim. ön yüz kısmı hiç uğraştırmadı fakat backend tarafında bir kaç problemle karşılaştım fakat logları inceleyerek bir kaç denemede hallettim. hayal ettiğimden çook daha basitmiş artık deployment işleri.