"Swarm" nasıl yapıldı?
4.200 parçacık FINDIE logotipini yazıyor, basılı tutunca sürüye dönüşüyor, scroll'da DESCRIBE → BUILD → QUEUE → LAND kelimelerine şekilleniyor. Bu rehber, o motorun ve sayfanın nasıl kurulduğunu anlatır. Framework yok, build yok: tek HTML dosyası.
Konsept: sürü = ajan filosu
Findie bir AADE (Autonomous Agentic Development Environment): Kanban'a kart bırakırsın, yapay zekâ ajanları izole git worktree'lerinde inşa eder, seri merge kuyruğu işi indirir, main yalnızca fast-forward ilerler. Yani ürünün özü: tek tek zayıf ama birlikte iş bitiren çok sayıda otonom birim. Sığırcık sürüsü (murmuration) bunun doğadaki karşılığı. Sayfanın imza tekniği de bu yüzden parçacık sürüsü: ürünün metaforu, süsü değil.
Ders: önce "bu ürünün doğadaki/dünyadaki karşılığı ne?" sorusunu cevapla, sonra o tek fikri sayfanın her köşesine uygula. Tek güçlü fikir, on ortalama bölümden iyidir.
Parçacık motoru (vanilla canvas)
Motor ~150 satır; kütüphane yok. İki mod var:
- MORPH: her parçacık kendi hedef pikseline yay (spring) ile çekilir:
v = v*0.82 + (hedef-konum)*0.06. Üstüne küçük bir sinüs titreşimi eklenir ki harfler "nefes alsın". - FLOCK (boids): ayrılma + hizalanma + kümelenme. Komşu araması için ekran 46px hücrelere bölünür (spatial hash); 4.200 parçacıkta bile O(n) kalır, 60fps korunur.
Kelime nasıl parçacığa dönüşür? Görünmez bir canvas'a Bricolage Grotesque (800) ile kelime yazılır, getImageData ile alfa kanalı taranır, dolu pikseller belirli adımlarla örneklenir:
ox.font = "800 " + fontSize + "px 'Bricolage Grotesque'";
ox.fillText(word, W/2, H*0.45);
const img = ox.getImageData(0,0,W,H).data;
for (let y=0; y<H; y+=step)
for (let x=0; x<W; x+=step)
if (img[(y*W+x)*4+3] > 128) targets.push(x,y);
// step, nokta sayısı ~N'e yaklaşana dek büyütülür (adaptif yoğunluk)
- Hedef sayısı parçacık sayısından azsa artan parçacıklar "toz" olur: %10 opaklıkla süzülürler.
- İz efekti: her karede ekranı silmek yerine
rgba(5,7,11,.38)ile boyanır; hareket kuyruk bırakır. - Renk: MORPH'ta krem, FLOCK'ta ve finalde Findie mavisi (
#037BFCailesi, markanın kendi rengi). Tek accent, markadan geliyor. - Fare MORPH'ta bir agent: yarıçapına giren kelime noktaları (task'lar) imlece atanır, altın açılı (filotaksi) yörünge yuvalarında imlecin etrafında döner ve ince mavi dispatch çizgileriyle merkeze bağlanır. İşi biten task maviden beyaza parlayarak harfteki yerine geri iner; imlecin altında mono bir "NN TASKS" sayacı akar (aynı anda en çok 56 task).
- FLOCK'ta fare klasik itme (repulsion) uygular; "basılı tut" sürüyü serbest bırakır, bırakınca kelimeye geri toplanır.
Scroll sinematografisi (GSAP ScrollTrigger)
Kelime morph sahnesi pin + scrub ile kurulu: bölüm ekrana yapışır, 3.2 ekran boyu scroll boyunca ilerleme 0→1 akar, her çeyrekte kelime değişir:
ScrollTrigger.create({
trigger: '#morph', start: 'top top',
end: '+=320%', pin: true, scrub: true,
onUpdate(self){
const s = Math.min(3, Math.floor(self.progress * 4));
if (s !== seg) { seg = s; form(WORDS[s]); /* caption swap */ }
}
});
Sahneden çıkınca (onLeave) sürü serbest moda düşer ve %16 opaklığa iner: sayfanın geri kalanında arka planda yaşamaya devam eder. Final bölümüne girince geri toplanıp mavi SHIP kelimesini yazar. Canvas position:fixed tek katmandır; tüm sayfa aynı simülasyonun içinde geçer.
Tipografi ve dil
- Bricolage Grotesque 800 (dev display: yumuşak hatlı, karakterli) + Geist (gövde; ürünün kendi UI fontu) + Geist Mono (telemetri). Hepsi woff2 self-host; ilk boyamada üçüncü parti istek yok. İlk sürüm Archivo Black ile fazla sert duruyordu; kullanıcı geri bildirimiyle hatlar yumuşatıldı: display değişti, butonlar 16px+ radius aldı, başlıklar sentence-case oldu.
- Ölçek korkusuzca büyük: doctrine satırları
clamp(26px, 4.6vw, 64px). Hover'da satır marka mavisine invert olur; ekran görüntüsü "polaroid" gibi yana düşer. - Telemetri dili dünyayı kurar: "LIVE SIMULATION · 4200 AGENTS IN FORMATION", "HOLD ANYWHERE · RELEASE THE SWARM". Küçük mono satırlar sayfaya "çalışan sistem" hissi verir.
Detay katmanı
- Preloader: 1 saniyelik "SPAWNING SWARM" + yüzde sayacı; perde yukarı kalkarken parçacıklar logoya toplanıyor. Yükleme değil, sahne girişi.
- Custom cursor: mavi halka,
mix-blend-mode:screen; link üstünde büyür, basılı tutunca 2.2x. Dokunmatik cihazda tamamen kapalı. - Grain + vignette: sabit, tıklama geçirmez iki katman; %7 film greni her şeyi birbirine yapıştırır.
- Erişilebilirlik: canvas dekoratif (
aria-hidden); anlatının tamamı gerçek DOM metni.prefers-reduced-motion'da simülasyon tek kare çizer, pin sahneleri normal akışa döner.
Üç turlu eleştiri döngüsü
- Tur 1 (yıkım): İlk sürüm "temiz bir SaaS sayfası"ydı: yıldız alanı, bento grid, ölçülü animasyonlar. Teknik olarak kusursuz, duygusal olarak unutulabilir. Referans işlerle yan yana koyunca karar netti: çöpe at, imza tekniği etrafında yeniden kur.
- Tur 2 (yeniden inşa): Parçacık motoru + pin sahnesi + brutalist tipografi. Ekran görüntüleriyle denetim: cursor açılışta köşede takılı kalıyordu (ilk harekete kadar gizlendi), SHIP finali soluktu (parlak marka moduna bağlandı), harf dolgusu inceydi (parçacık boyutu büyütüldü).
- Tur 3 (cila): Fold / morph ortası / final / tam sayfa / mobil çekimleri, konsol hata taraması, canlı deploy doğrulaması.
Sen de kur
# 1. Ürünün metaforunu bul; imza tekniğini ona göre seç
# 2. Text-to-particle: offscreen canvas + getImageData + adaptif örnekleme
# 3. İki modlu motor: spring-morph + boids (spatial hash ile)
# 4. GSAP ScrollTrigger: pin + scrub, çeyreklerde kelime değiştir
# 5. Fixed canvas = tüm sayfa tek simülasyonun içinde
# 6. Üç tur acımasız eleştiri; her turda screenshot + kusur listesi
npx wrangler pages deploy ./site --project-name=my-world