~/zafer
Tüm yazılara dön
2 dk okuma

Admin Formunda Slug Sadece Oluşturma Anında Otomatik Türetiliyor

Admin panelinde yeni bir yazı oluştururken başlığı yazdıkça slug otomatik türetiliyor:

// apps/admin/src/routes/post-form.tsx
function handleChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) {
  const { name, value, type } = e.target;
  setForm((prev) => {
    const next = { ...prev, [name]: value };
    if (name === "titleTr" && !isEditing) {
      next.slug = value
        .toLowerCase()
        .replace(/[^a-z0-9]+/g, "-")
        .replace(/(^-|-$)/g, "");
    }
    return next;
  });
}

Slug, /post/[slug] URL'inin kendisi — dışarıya paylaşılmış, arama motorlarınca indexlenmiş, başka sitelerden link verilmiş olabilir. Var olan bir yazıyı düzenlerken başlığı değiştirmek slug'ı da otomatik değiştirseydi, o yazıya giden her eski link 404'e düşerdi. !isEditing koşulu, bu otomatik türetmeyi sadece slug'ın henüz hiçbir yerde kullanılmadığı an — ilk oluşturma sırasında — çalıştırıyor. Düzenlerken slug tamamen manuel bir alan, kullanıcı isterse bilinçli olarak değiştirebiliyor ama yanlışlıkla değişmiyor.

Regex'in kendisi de şemadaki kısıtla eşleşiyor

next.slug = value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");

Bu dönüşüm, packages/schemas/src/post.ts'deki slug: z.string().regex(/^[a-z0-9-]+$/) kısıtını tam olarak karşılayan bir çıktı üretiyor — küçük harf, rakam, tire dışında hiçbir karakter kalmıyor, baş/son tiresi temizleniyor. Form UX'i ile API şeması burada aynı kuralı iki farklı yerde (regex dönüştürme, regex doğrulama) ifade ediyor; form kullanıcıyı zaten geçerli bir slug'a yönlendiriyor, API ise son savunma hattı olarak kalıyor.

Neden slug alanı yine de düzenlenebilir bırakılıyor

Otomatik türetim varsayılan davranış ama input salt-okunur değil — kullanıcı "başlıktan türeyen slug beğenmedim, kendim yazacağım" diyebilir. Otomasyon varsayılanı kolaylaştırıyor, zorunlu kılmıyor.