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;
});
}
!isEditing koşulu, kazara link kırmayı engelliyor
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.