<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://program.sonsuz.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://program.sonsuz.us/" rel="alternate" type="text/html" /><updated>2026-10-09T12:05:47+00:00</updated><id>https://program.sonsuz.us/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">Bağış Toplama Sistemleri Karşılaştırması: CiviCRM, GiveWP ve Open Collective</title><link href="https://program.sonsuz.us/posts/bagis-toplama-sistemleri-karsilastirmasi-civicrm-givewp-ve-open-collective/" rel="alternate" type="text/html" title="Bağış Toplama Sistemleri Karşılaştırması: CiviCRM, GiveWP ve Open Collective" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/bagis-toplama-sistemleri-karsilastirmasi-civicrm-givewp-ve-open-collective</id><content type="html" xml:base="https://program.sonsuz.us/posts/bagis-toplama-sistemleri-karsilastirmasi-civicrm-givewp-ve-open-collective/"><![CDATA[<p>Bir bağış sistemi seçmek, web sitesine yalnızca renkli bir “Destek Ol” düğmesi eklemekten çok daha fazlasıdır. Bağışçı ilişkileri, ödeme altyapısı, kampanya takibi, şeffaflık ve raporlama gibi parçalar doğru biçimde birleşmelidir. CiviCRM, GiveWP ve Open Collective aynı amaca hizmet ediyor gibi görünse de farklı organizasyon modellerine hitap eder: biri kapsamlı bir ilişki yönetim sistemi, biri WordPress odaklı bağış eklentisi, diğeri ise şeffaf topluluk finansmanı platformudur.</p>

<p>``</p>

<h2 id="önce-temel-mantık-bağış-sistemi-nasıl-çalışır">Önce temel mantık: Bağış sistemi nasıl çalışır?</h2>

<p>Tipik bir bağış akışı; bağışçı, form, ödeme sağlayıcısı, işlem kaydı ve raporlama katmanlarından oluşur. Kullanıcı formu doldurduğunda sistem ödeme sağlayıcısına bir istek gönderir. Başarılı işlem sonrasında bağış kaydedilir, makbuz oluşturulur ve gerekiyorsa bağışçıya otomatik e-posta gönderilir.</p>

<p>Bir kampanyanın net geliri basitçe şöyle modellenebilir:</p>

\[G_{net} = G_{brüt} - (G_{brüt} \times o_{komisyon}) - M_{sabit} - G_{iade}\]

<p>Burada $o_{komisyon}$ ödeme sağlayıcısının oransal kesintisini, $M_{sabit}$ işlem başına sabit maliyetleri temsil eder. Dolayısıyla yalnızca yazılımın fiyatını değil, ödeme komisyonlarını ve operasyon yükünü de karşılaştırmak gerekir.</p>

<h2 id="üç-sistemin-karakteri">Üç sistemin karakteri</h2>

<table>
  <thead>
    <tr>
      <th>Sistem</th>
      <th>Temel yaklaşım</th>
      <th>Güçlü olduğu alan</th>
      <th>Teknik ihtiyaç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>CiviCRM</td>
      <td>CRM ve bağış yönetimi</td>
      <td>STK, dernek, üyelik ve etkinlik takibi</td>
      <td>Orta-yüksek</td>
    </tr>
    <tr>
      <td>GiveWP</td>
      <td>WordPress bağış eklentisi</td>
      <td>Hızlı kampanya sayfaları ve formlar</td>
      <td>Orta</td>
    </tr>
    <tr>
      <td>Open Collective</td>
      <td>Şeffaf mali yönetim platformu</td>
      <td>Açık kaynak ve topluluk projeleri</td>
      <td>Düşük-orta</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/bagis-toplama-sistemleri-54.svg" alt="bagis-toplama-sistemleri-54" /></p>

<h3 id="civicrm-kurumsal-hafıza-isteyenlere">CiviCRM: Kurumsal hafıza isteyenlere</h3>

<p>CiviCRM yalnızca ödeme almakla kalmaz; bağışçıları, üyelikleri, etkinlikleri, e-postaları ve geçmiş etkileşimleri tek profilde toplar. Drupal, Joomla veya WordPress ile çalışabilir. Özellikle aynı destekçiyle yıllar boyunca ilişki kuran kuruluşlar için güçlüdür.</p>

<p>Bunun karşılığında kurulum ve bakım daha zahmetlidir. Veri modeli, roller, izinler ve zamanlanmış görevler doğru yapılandırılmalıdır. Küçük bir kampanya için ağır gelebilir; fakat binlerce kişiyle çalışan bir STK için adeta dijital genel merkezdir.</p>

<h3 id="givewp-wordpress-içinde-pratik-çözüm">GiveWP: WordPress içinde pratik çözüm</h3>

<p>GiveWP, mevcut WordPress sitesini bağış platformuna dönüştürür. Kampanya formları, hedef göstergeleri, bağışçı panelleri ve tekrarlayan ödeme özellikleri sunar. İçerik ekibinin WordPress’e aşina olması önemli bir avantajdır.</p>

<p>Basit bir entegrasyon mantığı şu şekilde düşünülebilir:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">add_action</span><span class="p">(</span><span class="s1">'give_insert_payment'</span><span class="p">,</span> <span class="k">function</span> <span class="p">(</span><span class="nv">$payment_id</span><span class="p">)</span> <span class="p">{</span>
    <span class="nv">$amount</span> <span class="o">=</span> <span class="nf">give_get_payment_total</span><span class="p">(</span><span class="nv">$payment_id</span><span class="p">);</span>
    <span class="nb">error_log</span><span class="p">(</span><span class="s1">'Yeni bağış tutarı: '</span> <span class="mf">.</span> <span class="nv">$amount</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>

<p>Bu örnek, yeni ödeme kaydedildiğinde bağış tutarını günlük dosyasına yazar. Gerçek projede aynı kanca CRM bildirimi göndermek veya özel bir teşekkür süreci başlatmak için kullanılabilir. Ancak ücretli eklentiler, ödeme ağ geçitleri ve WordPress güvenliği toplam maliyete eklenmelidir.</p>

<h3 id="open-collective-şeffaflık-varsayılan-ayar">Open Collective: Şeffaflık varsayılan ayar</h3>

<p>Open Collective özellikle açık kaynak projeleri, yerel topluluklar ve gayriresmî gruplar için dikkat çekicidir. Gelirler ve giderler herkese açık gösterilebilir. Bir mali sponsor kullanıldığında topluluk, ayrı bir tüzel kişilik kurmadan para kabul etme ve harcama olanağı bulabilir.</p>

<p>Platformun en güçlü tarafı şeffaflıktır; ancak klasik CRM özellikleri veya tamamen özelleştirilebilir bağış deneyimi bekleyen kuruluşlar için sınırlı kalabilir.</p>

<h2 id="hangisini-seçmeli">Hangisini seçmeli?</h2>

<table>
  <thead>
    <tr>
      <th>İhtiyaç</th>
      <th>Önerilen seçenek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ayrıntılı bağışçı geçmişi ve üyelik yönetimi</td>
      <td>CiviCRM</td>
    </tr>
    <tr>
      <td>WordPress üzerinde hızlı bağış kampanyası</td>
      <td>GiveWP</td>
    </tr>
    <tr>
      <td>Herkese açık gelir-gider takibi</td>
      <td>Open Collective</td>
    </tr>
    <tr>
      <td>İleri düzey özelleştirme ve veri sahipliği</td>
      <td>CiviCRM veya GiveWP</td>
    </tr>
    <tr>
      <td>Minimum altyapı yönetimi</td>
      <td>Open Collective</td>
    </tr>
  </tbody>
</table>

<p>Karar verirken bağış hacmi, ekip kapasitesi, veri gizliliği ve raporlama gereksinimleri birlikte değerlendirilmelidir. Kısacası CiviCRM ilişkiyi, GiveWP dönüşümü, Open Collective ise güveni ve şeffaflığı merkeze koyar. En iyi sistem en fazla özelliğe sahip olan değil, kuruluşunuzun günlük iş akışına en az sürtünmeyle uyum sağlayandır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="bağış" /><category term="civicrm" /><category term="givewp" /><category term="open-collective" /><category term="wordpress" /><category term="açık-kaynak" /><category term="fintech" /><summary type="html"><![CDATA[Bir bağış sistemi seçmek, web sitesine yalnızca renkli bir “Destek Ol” düğmesi eklemekten çok daha fazlasıdır. Bağışçı ilişkileri, ödeme altyapısı, kampanya takibi, şeffaflık ve raporlama gibi parçalar doğru biçimde birleşmelidir. CiviCRM, GiveWP ve Open Collective aynı amaca hizmet ediyor gibi görünse de farklı organizasyon modellerine hitap eder: biri kapsamlı bir ilişki yönetim sistemi, biri WordPress odaklı bağış eklentisi, diğeri ise şeffaf topluluk finansmanı platformudur.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/bagis-toplama-sistemleri-54.png" /><media:content medium="image" url="https://program.sonsuz.us/img/bagis-toplama-sistemleri-54.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Dijital Katılım Platformları: Decidim, CONSUL DEMOCRACY ve FixMyStreet</title><link href="https://program.sonsuz.us/posts/dijital-katilim-platformlari-decidim-consul-democracy-ve-fixmystreet/" rel="alternate" type="text/html" title="Dijital Katılım Platformları: Decidim, CONSUL DEMOCRACY ve FixMyStreet" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/dijital-katilim-platformlari-decidim-consul-democracy-ve-fixmystreet</id><content type="html" xml:base="https://program.sonsuz.us/posts/dijital-katilim-platformlari-decidim-consul-democracy-ve-fixmystreet/"><![CDATA[<p>Bir mahalledeki bozuk kaldırımı bildirmek, belediyeye yeni bir bisiklet yolu önermek veya belirli bir konuda binlerce imza toplamak istiyorsanız sıradan bir formdan fazlasına ihtiyacınız vardır. Decidim, CONSUL DEMOCRACY ve FixMyStreet; vatandaşlarla kurumlar arasında dijital köprü kuran açık kaynaklı platformlardır. Ancak aynı aileden görünseler de farklı problemleri çözerler.</p>

<p>``</p>

<h2 id="üç-platform-üç-yaklaşım">Üç platform, üç yaklaşım</h2>

<p><strong>Decidim</strong>, Barselona çıkışlı kapsamlı bir katılımcı demokrasi altyapısıdır. Teklif oluşturma, destek toplama, toplantı düzenleme, anket, bütçeleme ve sonuç takibi gibi süreçleri modüler biçimde sunar. Bir dilekçe sistemi kurmanın yanında tüm karar alma döngüsünü yönetmek isteyen kurumlara uygundur.</p>

<p><strong>CONSUL DEMOCRACY</strong>, vatandaş önerileri, tartışmalar, oylamalar ve katılımcı bütçeleme üzerine yoğunlaşır. Teklif belirli bir destek eşiğine ulaştığında değerlendirme ya da oylama aşamasına geçirilebilir. Bu nedenle klasik “öneri ver, imza topla, gündeme taşı” modeliyle oldukça uyumludur.</p>

<p><strong>FixMyStreet</strong> ise doğrudan bir dilekçe platformu değildir. Vatandaşların harita üzerinde çukur, kırık sokak lambası veya kaçak döküm gibi yerel sorunları bildirmesini sağlar. Bildirim, konuma göre sorumlu kuruma yönlendirilir ve çözüm durumu kamuya açık şekilde izlenebilir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Decidim</th>
      <th>CONSUL DEMOCRACY</th>
      <th>FixMyStreet</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Temel amaç</td>
      <td>Çok yönlü katılım</td>
      <td>Öneri ve oylama</td>
      <td>Coğrafi sorun bildirimi</td>
    </tr>
    <tr>
      <td>İmza/destek toplama</td>
      <td>Güçlü</td>
      <td>Güçlü</td>
      <td>Doğal özelliği değil</td>
    </tr>
    <tr>
      <td>Harita odaklı çalışma</td>
      <td>Ek modüllerle</td>
      <td>Sınırlı</td>
      <td>Çok güçlü</td>
    </tr>
    <tr>
      <td>Katılımcı bütçe</td>
      <td>Var</td>
      <td>Var</td>
      <td>Yok</td>
    </tr>
    <tr>
      <td>Uygun ölçek</td>
      <td>Kurum ve şehir</td>
      <td>Belediye ve ülke</td>
      <td>Belediye ve mahalle</td>
    </tr>
  </tbody>
</table>

<h2 id="i̇mza-sistemi-nasıl-düşünülmeli">İmza sistemi nasıl düşünülmeli?</h2>

<p>Basit modelde her dilekçenin bir destek sayısı ve hedefi bulunur. İlerleme oranı şöyle hesaplanabilir:</p>

\[P = 100 * S / H\]

<p>Burada $S$ doğrulanmış destek sayısını, $H$ hedeflenen desteği, $P$ ise yüzde ilerlemeyi ifade eder. Örneğin 2.000 destek hedefleyen bir öneri 1.250 doğrulanmış imzaya ulaştığında ilerleme oranı yüzde 62,5 olur.</p>

<p>Fakat yalnızca sayaç tutmak yeterli değildir. Aynı kişinin tekrar imza atması engellenmeli, e-posta veya kimlik doğrulaması yapılmalı ve kişisel veriler gereksiz yere yayımlanmamalıdır. İdeal süreç şu durum makinesini izleyebilir:</p>

<p><code class="language-plaintext highlighter-rouge">Taslak → Moderasyon → Yayında → Eşik Aşıldı → Kurumsal İnceleme → Sonuçlandı</code></p>

<p>Aşağıdaki basitleştirilmiş Python fonksiyonu, doğrulanmış ve benzersiz destekleri sayar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">petition_progress</span><span class="p">(</span><span class="n">signatures</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
    <span class="c1"># Doğrulanmış kullanıcı kimliklerini kümeye alarak tekrarları eler.
</span>    <span class="n">verified_users</span> <span class="o">=</span> <span class="p">{</span>
        <span class="n">item</span><span class="p">[</span><span class="sh">"</span><span class="s">user_id</span><span class="sh">"</span><span class="p">]</span>
        <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">signatures</span>
        <span class="k">if</span> <span class="n">item</span><span class="p">[</span><span class="sh">"</span><span class="s">verified</span><span class="sh">"</span><span class="p">]</span> <span class="ow">is</span> <span class="bp">True</span>
    <span class="p">}</span>

    <span class="n">support_count</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">verified_users</span><span class="p">)</span>
    <span class="n">percentage</span> <span class="o">=</span> <span class="nf">min</span><span class="p">((</span><span class="n">support_count</span> <span class="o">/</span> <span class="n">target</span><span class="p">)</span> <span class="o">*</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>

    <span class="k">return</span> <span class="p">{</span>
        <span class="sh">"</span><span class="s">support_count</span><span class="sh">"</span><span class="p">:</span> <span class="n">support_count</span><span class="p">,</span>
        <span class="sh">"</span><span class="s">percentage</span><span class="sh">"</span><span class="p">:</span> <span class="nf">round</span><span class="p">(</span><span class="n">percentage</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span>
        <span class="sh">"</span><span class="s">threshold_reached</span><span class="sh">"</span><span class="p">:</span> <span class="n">support_count</span> <span class="o">&gt;=</span> <span class="n">target</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>Gerçek sistemde <code class="language-plaintext highlighter-rouge">user_id</code> değerleri herkese açık gösterilmemeli; mümkünse tek yönlü özetler, yetkilendirme katmanları ve kayıt saklama politikaları kullanılmalıdır. Ayrıca kötüye kullanım önleme mekanizması erişilebilirliği bozmamalıdır: aşırı CAPTCHA kullanımı gerçek vatandaşları da kaçırabilir.</p>

<h2 id="hangisini-seçmelisiniz">Hangisini seçmelisiniz?</h2>

<table>
  <thead>
    <tr>
      <th>İhtiyaç</th>
      <th>Önerilen platform</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Dilekçe, toplantı ve bütçe tek yerde olsun</td>
      <td>Decidim</td>
    </tr>
    <tr>
      <td>Öneriler destek eşiğiyle oylamaya geçsin</td>
      <td>CONSUL DEMOCRACY</td>
    </tr>
    <tr>
      <td>Sorunlar haritada işaretlenip kuruma gönderilsin</td>
      <td>FixMyStreet</td>
    </tr>
  </tbody>
</table>

<p>Seçimde yalnızca özellik listesini değil; kurulum ekibinin Ruby/Rails deneyimini, barındırma bütçesini, moderasyon kapasitesini, çok dillilik ihtiyacını ve kurum içi süreçleri de değerlendirmek gerekir. En parlak arayüz bile arka tarafta dilekçeyi yanıtlayacak bir iş akışı yoksa dijital bir öneri kutusuna dönüşür.</p>

<p>Sonuç olarak Decidim geniş kapsamlı bir demokrasi laboratuvarı, CONSUL DEMOCRACY yapılandırılmış bir öneri ve oylama motoru, FixMyStreet ise konum tabanlı belediye sorunları için uzmanlaşmış bir araçtır. Başarılı seçim, “Hangisi daha güçlü?” sorusundan önce “Vatandaş hangi sürece katılacak?” sorusunu yanıtlamakla başlar.</p>

<p><img src="/img/dijital-katilim-platformlari-83.svg" alt="dijital-katilim-platformlari-83" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="decidim" /><category term="consul-democracy" /><category term="fixmystreet" /><category term="e-demokrasi" /><category term="açık-kaynak" /><category term="dijital-katılım" /><summary type="html"><![CDATA[Bir mahalledeki bozuk kaldırımı bildirmek, belediyeye yeni bir bisiklet yolu önermek veya belirli bir konuda binlerce imza toplamak istiyorsanız sıradan bir formdan fazlasına ihtiyacınız vardır. Decidim, CONSUL DEMOCRACY ve FixMyStreet; vatandaşlarla kurumlar arasında dijital köprü kuran açık kaynaklı platformlardır. Ancak aynı aileden görünseler de farklı problemleri çözerler.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/dijital-katilim-platformlari-83.png" /><media:content medium="image" url="https://program.sonsuz.us/img/dijital-katilim-platformlari-83.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Dijital Oylama Arenası: Helios Voting, Decidim ve CIVS</title><link href="https://program.sonsuz.us/posts/dijital-oylama-arenasi-helios-voting-decidim-ve-civs/" rel="alternate" type="text/html" title="Dijital Oylama Arenası: Helios Voting, Decidim ve CIVS" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/dijital-oylama-arenasi-helios-voting-decidim-ve-civs</id><content type="html" xml:base="https://program.sonsuz.us/posts/dijital-oylama-arenasi-helios-voting-decidim-ve-civs/"><![CDATA[<p>Bir dijital oylama sistemi seçmek, yalnızca “en çok oy alan kazansın” kodu yazmaktan ibaret değildir. Gizlilik, doğrulanabilirlik, kimlik denetimi ve seçim yöntemleri işin içine girdiğinde küçük bir anket hızla kriptografi laboratuvarına dönüşebilir. Bu yazıda Helios Voting, Decidim ve CIVS’nin farklı yaklaşımlarını karşılaştıracağız.</p>

<p>``</p>

<h2 id="oylamanın-teorik-temeli">Oylamanın teorik temeli</h2>

<p>Basit çoğunluk oylamasında aday $i$ için kullanılan oy sayısını $v_i$ ile gösterirsek kazanan şöyle bulunur:</p>

\[kazanan = argmax_i(v_i)\]

<p>Ancak gerçek dünyadaki her karar “tek aday seç” biçiminde değildir. Seçmenler adayları sıralayabilir, birden fazla seçeneği destekleyebilir veya bütçe önerilerine oy verebilir. Ayrıca sistemin dört temel beklentiyi dengelemesi gerekir:</p>

<ul>
  <li><strong>Gizlilik:</strong> Bir oyun kime ait olduğu açıklanmamalıdır.</li>
  <li><strong>Bütünlük:</strong> Oylar değiştirilememeli veya silinememelidir.</li>
  <li><strong>Doğrulanabilirlik:</strong> Seçmen, oyunun sayıma katıldığını kontrol edebilmelidir.</li>
  <li><strong>Uygunluk:</strong> Yalnızca yetkili kişiler ve izin verilen sayıda oy kullanabilmelidir.</li>
</ul>

<p>Bu özellikler bazen çatışır. Kimlik doğrulamasını güçlendirmek gizlilik riskini artırabilir; tamamen anonim katılım ise mükerrer oyları engellemeyi zorlaştırabilir.</p>

<h2 id="üç-platform-üç-farklı-karakter">Üç platform, üç farklı karakter</h2>

<table>
  <thead>
    <tr>
      <th>Platform</th>
      <th>Temel yaklaşım</th>
      <th>Güçlü olduğu alan</th>
      <th>Dikkat edilmesi gereken nokta</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Helios Voting</strong></td>
      <td>Uçtan uca doğrulanabilir kriptografik seçim</td>
      <td>Üniversite, dernek ve kurul seçimleri</td>
      <td>Zorlayıcıya karşı dayanıklılık ve cihaz güvenliği ayrıca değerlendirilmelidir</td>
    </tr>
    <tr>
      <td><strong>Decidim</strong></td>
      <td>Katılımcı demokrasi platformu</td>
      <td>Öneriler, toplantılar, süreçler ve katılımcı bütçeleme</td>
      <td>Tek başına özel amaçlı kriptografik seçim motoru değildir</td>
    </tr>
    <tr>
      <td><strong>CIVS</strong></td>
      <td>Condorcet tabanlı sıralamalı oylama</td>
      <td>Alternatifleri tercih sırasına koyma</td>
      <td>Sonuç yöntemi kullanıcıya önceden açıklanmalıdır</td>
    </tr>
  </tbody>
</table>

<h2 id="helios-voting-matematik-sandık-başında">Helios Voting: Matematik sandık başında</h2>

<p>Helios, oyları açık anahtarlı şifreleme ile korur ve seçim sonucunun doğrulanabilmesi için kriptografik kanıtlar üretir. Homomorfik şifrelemenin sadeleştirilmiş fikri şudur:</p>

\[E(v_1) \otimes E(v_2) = E(v_1 + v_2)\]

<p>Yani sistem, tek tek oyların içeriğini açmadan şifreli oyları birleştirip toplamı elde edebilir. Seçmen genellikle oyuna karşılık gelen bir takip değeri alır ve bu değerin yayımlanan sandık kayıtlarında bulunup bulunmadığını denetler. Böylece “oyum kayboldu mu?” sorusu teknik olarak kontrol edilebilir.</p>

<p>Bununla birlikte uçtan uca doğrulanabilirlik, seçmenin cihazında zararlı yazılım bulunmadığını otomatik olarak garanti etmez. Resmî ve yüksek riskli seçimlerde bağımsız güvenlik incelemesi şarttır.</p>

<h2 id="decidim-oylamadan-daha-büyük-bir-sahne">Decidim: Oylamadan daha büyük bir sahne</h2>

<p>Ruby on Rails tabanlı açık kaynak Decidim, yalnızca sandık kurmaz; karar alma sürecini baştan sona modellemeye çalışır. Katılımcılar öneri oluşturabilir, tartışabilir, toplantılara katılabilir ve bütçe projelerini destekleyebilir.</p>

<p>Bu nedenle Decidim’i “seçim uygulaması” yerine <strong>katılım altyapısı</strong> olarak düşünmek daha doğrudur. Bir belediyenin park önerilerini toplaması, projeleri tartışmaya açması ve ardından bütçe oylaması yapması için uygundur. Süreç şeffaflığı güçlüdür; fakat gizli oy gerektiren kritik seçimlerde kullanılacak özel bileşenler ayrıca incelenmelidir.</p>

<h2 id="civs-tercih-sıralarının-gücü">CIVS: Tercih sıralarının gücü</h2>

<p>CIVS, seçmenlerin adayları sıralamasına dayanır. Condorcet yaklaşımında bir aday, diğer her adayı ikili karşılaştırmada yeniyorsa kazanan kabul edilir. $P(a,b)$, $a$ adayını $b$ adayına tercih edenlerin sayısı olsun:</p>

\[a \succ b \quad eğer \quad P(a,b) &gt; P(b,a)\]

<p>Bu yöntem, yalnızca birinci tercihleri saymak yerine seçmenlerin genel eğilimini yakalar. Ancak döngüler oluşabilir: A, B’yi; B, C’yi; C de A’yı yenebilir. CIVS bu durumları çözmek için belirli Condorcet tamamlayıcı yöntemlerinden yararlanır.</p>

<p>Aşağıdaki Python kodu, iki aday arasındaki basit ikili üstünlüğü hesaplar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">pairwise_winner</span><span class="p">(</span><span class="n">rankings</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="n">scores</span> <span class="o">=</span> <span class="p">{</span><span class="n">a</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="mi">0</span><span class="p">}</span>

    <span class="k">for</span> <span class="n">ranking</span> <span class="ow">in</span> <span class="n">rankings</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">ranking</span><span class="p">.</span><span class="nf">index</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">ranking</span><span class="p">.</span><span class="nf">index</span><span class="p">(</span><span class="n">b</span><span class="p">):</span>
            <span class="n">scores</span><span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">scores</span><span class="p">[</span><span class="n">b</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">if</span> <span class="n">scores</span><span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">==</span> <span class="n">scores</span><span class="p">[</span><span class="n">b</span><span class="p">]:</span>
        <span class="k">return</span> <span class="sh">'</span><span class="s">berabere</span><span class="sh">'</span>
    <span class="k">return</span> <span class="nf">max</span><span class="p">(</span><span class="n">scores</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">scores</span><span class="p">.</span><span class="n">get</span><span class="p">)</span>
</code></pre></div></div>

<p>Fonksiyon, her sıralamada hangi adayın daha yukarıda bulunduğunu kontrol eder. Gerçek bir Condorcet sistemi, bu işlemi bütün aday çiftleri için yaparak bir karşılaştırma matrisi oluşturur.</p>

<h2 id="hangisini-seçmeli">Hangisini seçmeli?</h2>

<p>Kriptografik doğrulanabilirlik önceliğinizse <strong>Helios</strong>, kapsamlı katılımcı süreçler tasarlıyorsanız <strong>Decidim</strong>, seçenekleri adil biçimde sıralamak istiyorsanız <strong>CIVS</strong> güçlü adaylardır. Son karar; tehdit modeline, seçmen kitlesine, kimlik doğrulama ihtiyacına ve kullanılan seçim yönteminin anlaşılabilirliğine dayanmalıdır. Unutmayın: İyi bir dijital sandık yalnızca doğru sonucu üretmez, sonucun neden güvenilir olduğunu da gösterebilir.</p>

<p><img src="/img/dijital-oylama-arenasi-92.svg" alt="dijital-oylama-arenasi-92" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="oylama" /><category term="helios-voting" /><category term="decidim" /><category term="civs" /><category term="e-demokrasi" /><category term="açık-kaynak" /><summary type="html"><![CDATA[Bir dijital oylama sistemi seçmek, yalnızca “en çok oy alan kazansın” kodu yazmaktan ibaret değildir. Gizlilik, doğrulanabilirlik, kimlik denetimi ve seçim yöntemleri işin içine girdiğinde küçük bir anket hızla kriptografi laboratuvarına dönüşebilir. Bu yazıda Helios Voting, Decidim ve CIVS’nin farklı yaklaşımlarını karşılaştıracağız.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/dijital-oylama-arenasi-92.png" /><media:content medium="image" url="https://program.sonsuz.us/img/dijital-oylama-arenasi-92.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Dosya Arama Sistemi Kurmak: Elasticsearch, Meilisearch ve Typesense Karşılaştırması</title><link href="https://program.sonsuz.us/posts/dosya-arama-sistemi-kurmak-elasticsearch-meilisearch-ve-typesense-karsilastirmasi/" rel="alternate" type="text/html" title="Dosya Arama Sistemi Kurmak: Elasticsearch, Meilisearch ve Typesense Karşılaştırması" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/dosya-arama-sistemi-kurmak-elasticsearch-meilisearch-ve-typesense-karsilastirmasi</id><content type="html" xml:base="https://program.sonsuz.us/posts/dosya-arama-sistemi-kurmak-elasticsearch-meilisearch-ve-typesense-karsilastirmasi/"><![CDATA[<p>Binlerce PDF, Word belgesi ve metin dosyası arasında doğru dosyayı bulmaya çalışmak, dijital samanlıkta iğne aramaya benzeyebilir. Neyse ki Elasticsearch, Meilisearch ve Typesense gibi arama motorları; dosya içeriklerini indeksleyerek milisaniyeler içinde alakalı sonuçlar sunabilir. Peki bu üçlüden hangisi projenize daha uygun?</p>

<p>``</p>

<h2 id="dosya-arama-sistemi-nasıl-çalışır">Dosya arama sistemi nasıl çalışır?</h2>

<p>Bir arama motoru dosyaları doğrudan sihirli biçimde anlamaz. Önce dosyanın metni çıkarılır, temizlenir ve indekslenebilir bir belgeye dönüştürülür. Tipik veri akışı şöyledir:</p>

<ol>
  <li>Dosya sisteme yüklenir.</li>
  <li>Apache Tika, PDF.js veya benzeri bir araçla metin çıkarılır.</li>
  <li>Başlık, dosya yolu, uzantı ve kullanıcı izinleri gibi metadata eklenir.</li>
  <li>Belge arama motoruna gönderilir.</li>
  <li>Kullanıcı sorgusu indeks üzerinde çalıştırılır.</li>
</ol>

<p>Bu sistemlerin temelinde <strong>ters indeks</strong> bulunur. Geleneksel bir listede her belgenin içindeki kelimeler tutulurken ters indeks, her kelimenin hangi belgelerde geçtiğini saklar:</p>

<table>
  <thead>
    <tr>
      <th>Kelime</th>
      <th>Geçtiği belgeler</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>docker</td>
      <td>belge-1, belge-7</td>
    </tr>
    <tr>
      <td>güvenlik</td>
      <td>belge-2, belge-7</td>
    </tr>
    <tr>
      <td>yedekleme</td>
      <td>belge-3</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/dosya-arama-sistemi-35.svg" alt="dosya-arama-sistemi-35" /></p>

<p>Böylece motor, bütün dosyaları tek tek okumak yerine ilgili kayıtları doğrudan bulur. Alaka sıralamasında sık kullanılan BM25 yaklaşımının basitleştirilmiş fikri şöyledir:</p>

\[\text{skor}(q,d) = \sum_{t \in q} IDF(t) \cdot TF(t,d)\]

<p>Burada $TF$, kelimenin belgede ne kadar sık geçtiğini; $IDF$ ise kelimenin tüm koleksiyon içindeki ayırt ediciliğini temsil eder. Örneğin “dosya” kelimesi sıradanken “Kubernetes” daha yüksek ayırt ediciliğe sahip olabilir.</p>

<h2 id="üç-arama-motorunun-karşılaştırması">Üç arama motorunun karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Elasticsearch</th>
      <th>Meilisearch</th>
      <th>Typesense</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kurulum</td>
      <td>Daha karmaşık</td>
      <td>Çok kolay</td>
      <td>Kolay</td>
    </tr>
    <tr>
      <td>Ölçeklenebilirlik</td>
      <td>Çok yüksek</td>
      <td>Orta-yüksek</td>
      <td>Yüksek</td>
    </tr>
    <tr>
      <td>Yazım hatası toleransı</td>
      <td>Yapılandırılabilir</td>
      <td>Varsayılan olarak güçlü</td>
      <td>Varsayılan olarak güçlü</td>
    </tr>
    <tr>
      <td>Gelişmiş sorgular</td>
      <td>Çok kapsamlı</td>
      <td>Daha sade</td>
      <td>Dengeli</td>
    </tr>
    <tr>
      <td>Kaynak tüketimi</td>
      <td>Görece yüksek</td>
      <td>Düşük</td>
      <td>Düşük</td>
    </tr>
    <tr>
      <td>Uygun senaryo</td>
      <td>Büyük ve karmaşık sistemler</td>
      <td>Hızlı ürün geliştirme</td>
      <td>Hızlı, kontrollü arama</td>
    </tr>
  </tbody>
</table>

<p><strong>Elasticsearch</strong>, devasa veri kümeleri, dağıtık mimari ve ayrıntılı sorgu ihtiyacı olduğunda güçlüdür. Ancak shard, analyzer ve mapping gibi kavramları öğrenmek gerekir. Küçük bir proje için uzay mekiğiyle markete gitmek gibi hissedilebilir.</p>

<p><strong>Meilisearch</strong>, geliştirici deneyimine odaklanır. Yazım hatalarını otomatik tolere eder ve iyi sonuçlara ulaşmak için uzun yapılandırmalar istemez. MVP, kurum içi doküman araması ve içerik siteleri için oldukça pratiktir.</p>

<p><strong>Typesense</strong> ise sadelik ile kontrol arasında güzel bir denge kurar. Şema tanımı zorunludur; bu yaklaşım ilk aşamada ek iş çıkarsa da veri yapısının tutarlı kalmasını sağlar.</p>

<h2 id="örnek-belge-indeksleme">Örnek belge indeksleme</h2>

<p>Aşağıdaki JavaScript kodu, metni çıkarılmış bir dosyayı Meilisearch indeksine ekler:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">MeiliSearch</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">meilisearch</span><span class="dl">'</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">client</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">MeiliSearch</span><span class="p">({</span>
  <span class="na">host</span><span class="p">:</span> <span class="dl">'</span><span class="s1">http://localhost:7700</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">apiKey</span><span class="p">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">MEILI_MASTER_KEY</span>
<span class="p">});</span>

<span class="kd">const</span> <span class="nx">documents</span> <span class="o">=</span> <span class="nx">client</span><span class="p">.</span><span class="nf">index</span><span class="p">(</span><span class="dl">'</span><span class="s1">documents</span><span class="dl">'</span><span class="p">);</span>

<span class="k">await</span> <span class="nx">documents</span><span class="p">.</span><span class="nf">addDocuments</span><span class="p">([</span>
  <span class="p">{</span>
    <span class="na">id</span><span class="p">:</span> <span class="dl">'</span><span class="s1">rapor-2026</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">title</span><span class="p">:</span> <span class="dl">'</span><span class="s1">2026 Güvenlik Raporu</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">path</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/raporlar/guvenlik.pdf</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">extension</span><span class="p">:</span> <span class="dl">'</span><span class="s1">pdf</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">content</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Sunucu güvenliği, erişim kontrolü ve yedekleme...</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">allowedUsers</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">user-17</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">user-42</span><span class="dl">'</span><span class="p">]</span>
  <span class="p">}</span>
<span class="p">]);</span>

<span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">documents</span><span class="p">.</span><span class="nf">search</span><span class="p">(</span><span class="dl">'</span><span class="s1">sunucu güvenligi</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
  <span class="na">filter</span><span class="p">:</span> <span class="dl">'</span><span class="s1">allowedUsers = user-17</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">limit</span><span class="p">:</span> <span class="mi">10</span>
<span class="p">});</span>

<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">result</span><span class="p">.</span><span class="nx">hits</span><span class="p">);</span>
</code></pre></div></div>

<p>Kod, belgeyi <code class="language-plaintext highlighter-rouge">documents</code> indeksine ekler ve yazım hatası içeren bir sorgu çalıştırır. Gerçek projede erişim filtresi kritik önemdedir: Kullanıcının göremediği bir dosya, arama sonucunda da görünmemelidir. Ayrıca API anahtarını istemci tarafına koymak yerine backend üzerinde saklamak gerekir.</p>

<h2 id="hangisini-seçmeli">Hangisini seçmeli?</h2>

<p>Milyonlarca belge, karmaşık filtreler ve ayrıntılı analiz gerekiyorsa <strong>Elasticsearch</strong> doğru adaydır. Birkaç saatte çalışan, kullanıcı dostu bir arama deneyimi hedefleniyorsa <strong>Meilisearch</strong> öne çıkar. Düşük gecikme, güçlü yazım toleransı ve açık bir veri şeması isteniyorsa <strong>Typesense</strong> tercih edilebilir.</p>

<p>Motor seçiminden bağımsız olarak başarıyı belirleyen asıl unsurlar; kaliteli metin çıkarma, doğru metadata, Türkçe dil analizi, yetkilendirme ve düzenli indeks güncellemesidir. Motor arabanın kalbidir; fakat tekerlekler yoksa hiçbir yere gidemezsiniz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="elasticsearch" /><category term="meilisearch" /><category term="typesense" /><category term="arama-motoru" /><category term="dosya-indeksleme" /><category term="backend" /><summary type="html"><![CDATA[Binlerce PDF, Word belgesi ve metin dosyası arasında doğru dosyayı bulmaya çalışmak, dijital samanlıkta iğne aramaya benzeyebilir. Neyse ki Elasticsearch, Meilisearch ve Typesense gibi arama motorları; dosya içeriklerini indeksleyerek milisaniyeler içinde alakalı sonuçlar sunabilir. Peki bu üçlüden hangisi projenize daha uygun?]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/dosya-arama-sistemi-35.png" /><media:content medium="image" url="https://program.sonsuz.us/img/dosya-arama-sistemi-35.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Kendi Arama Motorunu Kur: SearXNG, YaCy ve Whoogle Karşılaştırması</title><link href="https://program.sonsuz.us/posts/kendi-arama-motorunu-kur-searxng-yacy-ve-whoogle-karsilastirmasi/" rel="alternate" type="text/html" title="Kendi Arama Motorunu Kur: SearXNG, YaCy ve Whoogle Karşılaştırması" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/kendi-arama-motorunu-kur-searxng-yacy-ve-whoogle-karsilastirmasi</id><content type="html" xml:base="https://program.sonsuz.us/posts/kendi-arama-motorunu-kur-searxng-yacy-ve-whoogle-karsilastirmasi/"><![CDATA[<p>Arama kutusuna birkaç kelime yazıp Enter tuşuna bastığımızda perde arkasında oldukça büyük bir sistem çalışır. SearXNG, YaCy ve Whoogle ise bu sistemi farklı yöntemlerle kontrolümüze almamızı sağlayan açık kaynaklı araçlardır. Biri birçok kaynaktan sonuç toplar, biri dağıtık bir indeks oluşturur, diğeri Google sonuçlarını daha sade ve mahremiyet odaklı biçimde sunar. Kısacası üçü de arama yapar; fakat aynı yoldan gitmez.
``</p>

<h2 id="önce-temel-teori-arama-motoru-ne-yapar">Önce temel teori: Arama motoru ne yapar?</h2>

<p>Klasik bir arama motoru üç ana aşamadan oluşur:</p>

<ol>
  <li><strong>Tarama:</strong> Botlar web sayfalarını ziyaret eder.</li>
  <li><strong>İndeksleme:</strong> Sayfalardaki kelimeler, bağlantılar ve meta veriler kaydedilir.</li>
  <li><strong>Sıralama:</strong> Kullanıcının sorgusuyla en alakalı belgeler seçilir.</li>
</ol>

<p>Basitleştirilmiş bir alaka puanı şöyle düşünülebilir:</p>

\[S(d,q) = \alpha T(d,q) + \beta L(d) + \gamma F(d)\]

<p>Burada $T(d,q)$ belgenin sorguyla metinsel uyumunu, $L(d)$ bağlantı otoritesini, $F(d)$ ise güncelliğini temsil eder. $\alpha$, $\beta$ ve $\gamma$ katsayıları sistemin nelere önem verdiğini belirler. Ancak incelediğimiz araçların hepsi bu zincirin tamamını kendisi gerçekleştirmez.</p>

<table>
  <thead>
    <tr>
      <th>Araç</th>
      <th>Temel yaklaşım</th>
      <th style="text-align: right">Kendi indeksi</th>
      <th>Sonuç kaynağı</th>
      <th>Güçlü yanı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>SearXNG</td>
      <td>Meta arama</td>
      <td style="text-align: right">Hayır</td>
      <td>Birden çok motor</td>
      <td>Kaynak çeşitliliği</td>
    </tr>
    <tr>
      <td>YaCy</td>
      <td>Dağıtık arama</td>
      <td style="text-align: right">Evet</td>
      <td>Eşler ve yerel tarayıcı</td>
      <td>Merkeziyetsizlik</td>
    </tr>
    <tr>
      <td>Whoogle</td>
      <td>Google vekili</td>
      <td style="text-align: right">Hayır</td>
      <td>Google</td>
      <td>Sadelik ve mahremiyet</td>
    </tr>
  </tbody>
</table>

<h2 id="searxng-arama-motorlarının-orkestra-şefi">SearXNG: Arama motorlarının orkestra şefi</h2>

<p>SearXNG, sorguyu yapılandırılmış biçimde Google, Bing, Brave, Wikipedia ve başka servislere göndererek sonuçları tek ekranda birleştiren bir <strong>meta arama motorudur</strong>. Kendisi tüm web’i taramaz; farklı kaynaklardan gelen sonuçları normalize eder ve sıralar.</p>

<p>Bu yaklaşım tek bir sağlayıcının bakış açısına bağlı kalmayı azaltır. Ayrıca kendi sunucunuza kurduğunuzda sorgu kayıtları ve çerez politikası üzerinde daha fazla denetim elde edersiniz. Yine de isteklerin hedef arama servislerine ulaştığını unutmamak gerekir; SearXNG sihirli görünmezlik pelerini değildir.</p>

<p>Docker ile hızlı bir deneme yapılabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">-d</span> <span class="nt">--name</span> searxng <span class="se">\</span>
  <span class="nt">-p</span> 8080:8080 <span class="se">\</span>
  searxng/searxng
</code></pre></div></div>

<p>Bu komut, SearXNG konteynerini çalıştırır ve arayüzü <code class="language-plaintext highlighter-rouge">8080</code> portundan erişilebilir hâle getirir. Gerçek kullanımda gizli anahtar, ters proxy, HTTPS ve hız sınırlaması ayrıca yapılandırılmalıdır.</p>

<h2 id="yacy-her-bilgisayar-küçük-bir-kütüphaneci">YaCy: Her bilgisayar küçük bir kütüphaneci</h2>

<p>YaCy, diğer ikisinden daha maceracıdır. Kendi web tarayıcısına ve indeksine sahiptir; ayrıca eşler arası ağ üzerinden başka YaCy düğümleriyle veri paylaşabilir. Böylece merkezî bir şirket yerine birçok katılımcının katkısıyla arama altyapısı oluşturulabilir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Merkezî indeks</th>
      <th>YaCy ağı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Yönetim</td>
      <td>Tek kuruluş</td>
      <td>Dağıtık düğümler</td>
    </tr>
    <tr>
      <td>Kaynak ihtiyacı</td>
      <td>Kullanıcı için düşük</td>
      <td>Disk, RAM ve bant genişliği ister</td>
    </tr>
    <tr>
      <td>Kapsam</td>
      <td>Genellikle çok geniş</td>
      <td>Ağa ve taramaya bağlı</td>
    </tr>
    <tr>
      <td>Denetim</td>
      <td>Sağlayıcıda</td>
      <td>Düğüm sahibinde</td>
    </tr>
  </tbody>
</table>

<p>YaCy özellikle intranet, akademik arşiv veya belirli sitelerden oluşan özel koleksiyonlar için ilgi çekicidir. Buna karşılık tüm web’de büyük ticari motorlarla aynı hız ve kaliteyi beklemek gerçekçi değildir. Özgürlük menüdeyse, yanında kaynak tüketimi de ikram edilir.</p>

<h2 id="whoogle-google-fakat-daha-az-süslemeli">Whoogle: Google, fakat daha az süslemeli</h2>

<p>Whoogle, Google sonuçları için çalışan bir vekil arayüzdür. JavaScript ağırlığını, reklamları ve bazı takip mekanizmalarını azaltmayı hedefler. Kullanımı kolaydır; fakat doğrudan Google’a bağımlı olduğu için istek engelleme, CAPTCHA veya HTML değişikliklerinden etkilenebilir.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">-d</span> <span class="nt">--name</span> whoogle <span class="se">\</span>
  <span class="nt">-p</span> 5000:5000 <span class="se">\</span>
  benbusby/whoogle-search
</code></pre></div></div>

<p>Bu örnek servisi yerel <code class="language-plaintext highlighter-rouge">5000</code> portunda başlatır. Herkese açık örnek çalıştırmak yerine erişimi sınırlandırmak daha güvenlidir; aksi hâlde sunucunuz kısa sürede robotların ücretsiz taksisine dönüşebilir.</p>

<h2 id="hangisini-seçmeli">Hangisini seçmeli?</h2>

<p>Çok kaynaklı ve özelleştirilebilir günlük arama için <strong>SearXNG</strong>, bağımsız indeksleme ve dağıtık deneyler için <strong>YaCy</strong>, sade Google sonuçları için <strong>Whoogle</strong> uygundur. En dengeli genel tercih çoğu kullanıcı açısından SearXNG’dir. Hangi aracı seçerseniz seçin HTTPS, güncel konteyner imajları, erişim kontrolü ve günlük politikası gibi güvenlik ayrıntılarını ihmal etmeyin. Mahremiyet yalnızca yazılım kurmakla değil, doğru yapılandırmakla kazanılır.</p>

<p><img src="/img/kendi-arama-motorunu-25.svg" alt="kendi-arama-motorunu-25" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="arama motoru" /><category term="searxng" /><category term="yacy" /><category term="whoogle" /><category term="gizlilik" /><category term="açık kaynak" /><summary type="html"><![CDATA[Arama kutusuna birkaç kelime yazıp Enter tuşuna bastığımızda perde arkasında oldukça büyük bir sistem çalışır. SearXNG, YaCy ve Whoogle ise bu sistemi farklı yöntemlerle kontrolümüze almamızı sağlayan açık kaynaklı araçlardır. Biri birçok kaynaktan sonuç toplar, biri dağıtık bir indeks oluşturur, diğeri Google sonuçlarını daha sade ve mahremiyet odaklı biçimde sunar. Kısacası üçü de arama yapar; fakat aynı yoldan gitmez.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/kendi-arama-motorunu-25.png" /><media:content medium="image" url="https://program.sonsuz.us/img/kendi-arama-motorunu-25.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Kendi Dijital Karargâhını Kur: Heimdall, Homer ve Flame Karşılaştırması</title><link href="https://program.sonsuz.us/posts/kendi-dijital-karargahini-kur-heimdall-homer-ve-flame-karsilastirmasi/" rel="alternate" type="text/html" title="Kendi Dijital Karargâhını Kur: Heimdall, Homer ve Flame Karşılaştırması" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/kendi-dijital-karargahini-kur-heimdall-homer-ve-flame-karsilastirmasi</id><content type="html" xml:base="https://program.sonsuz.us/posts/kendi-dijital-karargahini-kur-heimdall-homer-ve-flame-karsilastirmasi/"><![CDATA[<p>Ev sunucunuzda onlarca uygulama çalışıyor, fakat hangisinin hangi portta olduğunu hatırlamak için tarayıcı geçmişinde arkeolojik kazı yapıyorsanız kişisel portal zamanı gelmiş demektir. Heimdall, Homer ve Flame; servislerinizi düzenli kartlar, simgeler ve kategoriler altında toplayan popüler self-hosted başlangıç sayfalarıdır.
``</p>
<h2 id="kişisel-portal-ne-işe-yarar">Kişisel portal ne işe yarar?</h2>

<p>Portal sistemi, uygulamalarınızın kendisini barındırmaz; onlara ulaşabileceğiniz merkezi bir navigasyon katmanı oluşturur. Örneğin Jellyfin, Home Assistant, Grafana ve Portainer farklı adreslerde çalışırken portalınız tek bir URL üzerinden hepsine bağlantı sunar.</p>

<p>Bu yapıyı basitçe bir fonksiyon gibi düşünebiliriz:</p>

\[P: S \rightarrow U\]

<p>Burada $S$ servis adlarını, $U$ ise ilgili URL’leri temsil eder. Portalın asıl değeri bağlantı sayısı arttıkça ortaya çıkar. Kullanıcının ezberlemesi gereken adres sayısı $n$ iken iyi tasarlanmış bir portal bu zihinsel yükü yaklaşık olarak tek giriş noktasına indirir:</p>

\[L_{portal} \approx 1, \qquad L_{ezber} = n\]

<p>Elbette portal güvenlik duvarı veya kimlik doğrulama sistemi değildir. İnternete açılacaksa HTTPS, ters vekil sunucu ve mümkünse Authelia ya da Authentik gibi bir erişim katmanı kullanılmalıdır.</p>

<h2 id="üç-adayın-karakteri">Üç adayın karakteri</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Heimdall</th>
      <th>Homer</th>
      <th>Flame</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Yapı</td>
      <td>Dinamik web uygulaması</td>
      <td>Statik arayüz</td>
      <td>Dinamik web uygulaması</td>
    </tr>
    <tr>
      <td>Yapılandırma</td>
      <td>Web paneli</td>
      <td>YAML dosyası</td>
      <td>Web paneli ve Docker etiketleri</td>
    </tr>
    <tr>
      <td>Kaynak tüketimi</td>
      <td>Orta</td>
      <td>Çok düşük</td>
      <td>Düşük-orta</td>
    </tr>
    <tr>
      <td>Uygulama entegrasyonu</td>
      <td>Güçlü</td>
      <td>Temel bağlantılar</td>
      <td>Otomatik keşif odaklı</td>
    </tr>
    <tr>
      <td>İdeal kullanıcı</td>
      <td>Görsel yönetim isteyen</td>
      <td>GitOps ve sadelik seven</td>
      <td>Docker ağırlıklı homelab sahibi</td>
    </tr>
  </tbody>
</table>

<h3 id="heimdall-gösterişli-ve-kullanışlı">Heimdall: Gösterişli ve kullanışlı</h3>

<p>Heimdall, uygulama kartlarını tarayıcı üzerinden eklemeyi kolaylaştırır. Bazı servisler için geliştirilmiş uygulama desteği sayesinde kartlarda ek bilgiler gösterilebilir. Dosya düzenlemek istemeyen, portalını aile üyelerine de kullandıracak kişiler için iyi bir seçimdir. Buna karşılık veritabanı ve uygulama çalışma zamanı nedeniyle Homer’dan daha fazla kaynak tüketir.</p>

<h3 id="homer-yaml-seven-minimaliste">Homer: YAML seven minimaliste</h3>

<p>Homer büyük ölçüde statik çalışır ve yapılandırmasını YAML dosyasından alır. Bu dosyayı Git deposunda saklayabilir, değişiklik geçmişini izleyebilir ve farklı sunuculara kolayca taşıyabilirsiniz.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span>
<span class="na">title</span><span class="pi">:</span> <span class="s">Ev Laboratuvarım</span>
<span class="na">services</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Medya</span>
    <span class="na">items</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Jellyfin</span>
        <span class="na">subtitle</span><span class="pi">:</span> <span class="s">Film ve diziler</span>
        <span class="na">url</span><span class="pi">:</span> <span class="s">https://jellyfin.example.com</span>
        <span class="na">icon</span><span class="pi">:</span> <span class="s">fas fa-play-circle</span>
</code></pre></div></div>

<p>Bu yapılandırma bir <strong>Medya</strong> bölümü ve Jellyfin kartı oluşturur. Homer’ın sadeliği performans avantajıdır; ancak bağlantı eklemek için dosyayı düzenlemek, YAML girintilerine dikkat etmek gerekir. Tek bir hatalı boşluk küçük bir sabır sınavına dönüşebilir.</p>

<h3 id="flame-docker-ile-yakın-arkadaş">Flame: Docker ile yakın arkadaş</h3>

<p>Flame, görsel yönetim paneliyle uygulama ve yer imi eklemeyi kolaylaştırır. En dikkat çekici taraflarından biri, uygun Docker etiketleri kullanıldığında çalışan konteynerleri portalda gösterebilmesidir.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">services</span><span class="pi">:</span>
  <span class="na">uptime-kuma</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">louislam/uptime-kuma:1</span>
    <span class="na">labels</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">flame.type=application</span>
      <span class="pi">-</span> <span class="s">flame.name=Uptime Kuma</span>
      <span class="pi">-</span> <span class="s">flame.url=https://status.example.com</span>
</code></pre></div></div>

<p>Etiketler, Flame’e konteynerin adını ve açılacak adresi bildirir. Böylece servis tanımı uygulamanın Docker Compose dosyasıyla birlikte yaşar; yeni kurulumlarda portal kartını ayrıca oluşturmanız gerekmez.</p>

<h2 id="hangisini-seçmelisiniz">Hangisini seçmelisiniz?</h2>

<p>Sadece hızlı, taşınabilir ve sürüm kontrolüne uygun bir ana sayfa istiyorsanız <strong>Homer</strong> öne çıkar. Zengin uygulama kartları ve tamamen görsel yönetim arıyorsanız <strong>Heimdall</strong> daha rahattır. Servislerinizi Docker Compose ile yönetiyor ve otomatik keşif fikrini seviyorsanız <strong>Flame</strong> oldukça pratiktir.</p>

<p>Seçiminiz ne olursa olsun portalı yalnızca iç ağda yayınlamak, düzenli yedek almak ve yönetim arayüzünü güçlü parolayla korumak önemlidir. Sonuçta dijital karargâhınızın kapısını açık bırakmak, anahtarı paspasın altına koymanın teknolojik karşılığıdır.</p>

<p><img src="/img/kendi-dijital-karargahini-96.svg" alt="kendi-dijital-karargahini-96" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="self-hosted" /><category term="heimdall" /><category term="homer" /><category term="flame" /><category term="docker" /><category term="homelab" /><category term="dashboard" /><summary type="html"><![CDATA[Ev sunucunuzda onlarca uygulama çalışıyor, fakat hangisinin hangi portta olduğunu hatırlamak için tarayıcı geçmişinde arkeolojik kazı yapıyorsanız kişisel portal zamanı gelmiş demektir. Heimdall, Homer ve Flame; servislerinizi düzenli kartlar, simgeler ve kategoriler altında toplayan popüler self-hosted başlangıç sayfalarıdır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/kendi-dijital-karargahini-96.png" /><media:content medium="image" url="https://program.sonsuz.us/img/kendi-dijital-karargahini-96.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Lig ve Puan Tablosu Sistemi Tasarlamak: Fikstürden Şampiyonluğa</title><link href="https://program.sonsuz.us/posts/lig-ve-puan-tablosu-sistemi-tasarlamak-fiksturden-sampiyonluga/" rel="alternate" type="text/html" title="Lig ve Puan Tablosu Sistemi Tasarlamak: Fikstürden Şampiyonluğa" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/lig-ve-puan-tablosu-sistemi-tasarlamak-fiksturden-sampiyonluga</id><content type="html" xml:base="https://program.sonsuz.us/posts/lig-ve-puan-tablosu-sistemi-tasarlamak-fiksturden-sampiyonluga/"><![CDATA[<p>Bir lig yönetim sistemi dışarıdan yalnızca takımları sıralayan basit bir tablo gibi görünür. Oysa Open Tournament veya Tournament Software benzeri bir uygulama; fikstür oluşturma, sonuç kaydetme, eşitlik bozma, hükmen galibiyet ve farklı turnuva formatlarını yönetme gibi birçok kuralı aynı potada eritir. Gelin bu dijital hakemin nasıl tasarlanabileceğine bakalım.</p>

<p><img src="/img/lig-ve-puan-58.svg" alt="lig-ve-puan-58" /></p>

<p>``</p>
<h2 id="temel-veri-modeli">Temel veri modeli</h2>

<p>Sistemin merkezinde <strong>turnuva</strong>, <strong>katılımcı</strong>, <strong>karşılaşma</strong> ve <strong>puan durumu kaydı</strong> bulunur. Katılımcı bir takım olabileceği gibi tekil bir sporcu da olabilir. Bu nedenle veri modelinde <code class="language-plaintext highlighter-rouge">team</code> yerine daha genel olan <code class="language-plaintext highlighter-rouge">participant</code> adını kullanmak sistemi farklı spor dallarına uyarlamayı kolaylaştırır.</p>

<table>
  <thead>
    <tr>
      <th>Varlık</th>
      <th>Önemli alanlar</th>
      <th>Sorumluluk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tournament</td>
      <td>ad, format, kurallar</td>
      <td>Organizasyon ayarlarını saklar</td>
    </tr>
    <tr>
      <td>Participant</td>
      <td>ad, kategori, seri başı</td>
      <td>Takım veya oyuncuyu temsil eder</td>
    </tr>
    <tr>
      <td>Match</td>
      <td>taraflar, skor, durum</td>
      <td>Karşılaşma sonucunu tutar</td>
    </tr>
    <tr>
      <td>Standing</td>
      <td>puan, averaj, sıralama</td>
      <td>Hesaplanan tabloyu temsil eder</td>
    </tr>
  </tbody>
</table>

<p>Puan tablosunu kalıcı olarak saklamak yerine maç sonuçlarından yeniden hesaplamak çoğu zaman daha güvenlidir. Böylece bir skor düzeltildiğinde eski ve yeni değerlerin birbirine karışması önlenir. Performans gerekiyorsa hesaplanan tablo önbelleğe alınabilir.</p>

<h2 id="puan-hesabının-matematiği">Puan hesabının matematiği</h2>

<p>Klasik futbol sisteminde galibiyet 3, beraberlik 1 ve mağlubiyet 0 puandır. Bir katılımcının toplam puanı şu şekilde ifade edilir:</p>

\[P = 3G + 1B + 0M\]

<p>Burada $G$ galibiyet, $B$ beraberlik, $M$ ise mağlubiyet sayısıdır. Genel averaj da</p>

\[A = S_{atılan} - S_{yenilen}\]

<p>formülüyle hesaplanır. Ancak masa tenisi, badminton veya e-spor ligleri set oranı, harita farkı ya da doğrudan ikili averaj kullanabilir. Bu yüzden puan kurallarını kodun içine sabitlemek yerine turnuva ayarlarında tanımlamak iyi bir fikirdir.</p>

<table>
  <thead>
    <tr>
      <th>Kriter</th>
      <th>Avantajı</th>
      <th>Dezavantajı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Genel averaj</td>
      <td>Kolay hesaplanır</td>
      <td>Güçsüz rakiplere karşı farkı ödüllendirir</td>
    </tr>
    <tr>
      <td>İkili averaj</td>
      <td>Doğrudan rekabeti önemser</td>
      <td>Çoklu eşitlikte karmaşıklaşır</td>
    </tr>
    <tr>
      <td>Kazanılan maç</td>
      <td>Sonuç odaklıdır</td>
      <td>Beraberlik ağırlığını azaltır</td>
    </tr>
    <tr>
      <td>Fair-play puanı</td>
      <td>Disiplini teşvik eder</td>
      <td>Ana performansa dolaylı bağlıdır</td>
    </tr>
  </tbody>
</table>

<h2 id="hesaplama-motoru">Hesaplama motoru</h2>

<p>Aşağıdaki TypeScript fonksiyonu, tamamlanmış maçlardan temel puan tablosu üretir. Fonksiyon saf tutulduğu için aynı girdi her zaman aynı çıktıyı verir; test etmek de oldukça kolaydır.</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">type</span> <span class="nx">Match</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">homeId</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">awayId</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">homeScore</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">awayScore</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">status</span><span class="p">:</span> <span class="dl">"</span><span class="s2">finished</span><span class="dl">"</span> <span class="o">|</span> <span class="dl">"</span><span class="s2">scheduled</span><span class="dl">"</span><span class="p">;</span>
<span class="p">};</span>

<span class="kd">type</span> <span class="nx">Row</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">id</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">played</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">won</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">draw</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">lost</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">scored</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">conceded</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">points</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
<span class="p">};</span>

<span class="kd">function</span> <span class="nf">calculateTable</span><span class="p">(</span><span class="nx">ids</span><span class="p">:</span> <span class="kr">string</span><span class="p">[],</span> <span class="nx">matches</span><span class="p">:</span> <span class="nx">Match</span><span class="p">[]):</span> <span class="nx">Row</span><span class="p">[]</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">rows</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Map</span><span class="p">(</span><span class="nx">ids</span><span class="p">.</span><span class="nf">map</span><span class="p">(</span><span class="nx">id</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">id</span><span class="p">,</span> <span class="p">{</span>
    <span class="nx">id</span><span class="p">,</span> <span class="na">played</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="na">won</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="na">draw</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="na">lost</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
    <span class="na">scored</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="na">conceded</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="na">points</span><span class="p">:</span> <span class="mi">0</span>
  <span class="p">}]));</span>

  <span class="k">for </span><span class="p">(</span><span class="kd">const</span> <span class="nx">match</span> <span class="k">of</span> <span class="nx">matches</span><span class="p">.</span><span class="nf">filter</span><span class="p">(</span><span class="nx">m</span> <span class="o">=&gt;</span> <span class="nx">m</span><span class="p">.</span><span class="nx">status</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">finished</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">home</span> <span class="o">=</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="nx">match</span><span class="p">.</span><span class="nx">homeId</span><span class="p">)</span><span class="o">!</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">away</span> <span class="o">=</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="nx">match</span><span class="p">.</span><span class="nx">awayId</span><span class="p">)</span><span class="o">!</span><span class="p">;</span>

    <span class="nx">home</span><span class="p">.</span><span class="nx">played</span><span class="o">++</span><span class="p">;</span> <span class="nx">away</span><span class="p">.</span><span class="nx">played</span><span class="o">++</span><span class="p">;</span>
    <span class="nx">home</span><span class="p">.</span><span class="nx">scored</span> <span class="o">+=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">homeScore</span><span class="p">;</span>
    <span class="nx">home</span><span class="p">.</span><span class="nx">conceded</span> <span class="o">+=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">awayScore</span><span class="p">;</span>
    <span class="nx">away</span><span class="p">.</span><span class="nx">scored</span> <span class="o">+=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">awayScore</span><span class="p">;</span>
    <span class="nx">away</span><span class="p">.</span><span class="nx">conceded</span> <span class="o">+=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">homeScore</span><span class="p">;</span>

    <span class="k">if </span><span class="p">(</span><span class="nx">match</span><span class="p">.</span><span class="nx">homeScore</span> <span class="o">===</span> <span class="nx">match</span><span class="p">.</span><span class="nx">awayScore</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">home</span><span class="p">.</span><span class="nx">draw</span><span class="o">++</span><span class="p">;</span> <span class="nx">away</span><span class="p">.</span><span class="nx">draw</span><span class="o">++</span><span class="p">;</span>
      <span class="nx">home</span><span class="p">.</span><span class="nx">points</span><span class="o">++</span><span class="p">;</span> <span class="nx">away</span><span class="p">.</span><span class="nx">points</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
      <span class="kd">const</span> <span class="nx">winner</span> <span class="o">=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">homeScore</span> <span class="o">&gt;</span> <span class="nx">match</span><span class="p">.</span><span class="nx">awayScore</span> <span class="p">?</span> <span class="nx">home</span> <span class="p">:</span> <span class="nx">away</span><span class="p">;</span>
      <span class="kd">const</span> <span class="nx">loser</span> <span class="o">=</span> <span class="nx">winner</span> <span class="o">===</span> <span class="nx">home</span> <span class="p">?</span> <span class="nx">away</span> <span class="p">:</span> <span class="nx">home</span><span class="p">;</span>
      <span class="nx">winner</span><span class="p">.</span><span class="nx">won</span><span class="o">++</span><span class="p">;</span> <span class="nx">winner</span><span class="p">.</span><span class="nx">points</span> <span class="o">+=</span> <span class="mi">3</span><span class="p">;</span>
      <span class="nx">loser</span><span class="p">.</span><span class="nx">lost</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="p">[...</span><span class="nx">rows</span><span class="p">.</span><span class="nf">values</span><span class="p">()].</span><span class="nf">sort</span><span class="p">((</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span>
    <span class="nx">b</span><span class="p">.</span><span class="nx">points</span> <span class="o">-</span> <span class="nx">a</span><span class="p">.</span><span class="nx">points</span> <span class="o">||</span>
    <span class="p">(</span><span class="nx">b</span><span class="p">.</span><span class="nx">scored</span> <span class="o">-</span> <span class="nx">b</span><span class="p">.</span><span class="nx">conceded</span><span class="p">)</span> <span class="o">-</span> <span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">scored</span> <span class="o">-</span> <span class="nx">a</span><span class="p">.</span><span class="nx">conceded</span><span class="p">)</span> <span class="o">||</span>
    <span class="nx">b</span><span class="p">.</span><span class="nx">scored</span> <span class="o">-</span> <span class="nx">a</span><span class="p">.</span><span class="nx">scored</span>
  <span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Sıralama zinciri burada puan, averaj ve atılan skor biçimindedir. İkili averaj gerekiyorsa eşit puanlı katılımcılar belirlenmeli, yalnızca kendi aralarındaki maçlardan geçici bir mini tablo oluşturulmalıdır.</p>

<h2 id="fikstür-ve-operasyonel-ayrıntılar">Fikstür ve operasyonel ayrıntılar</h2>

<p>Tek devreli ligde $n$ katılımcı için toplam maç sayısı</p>

\[M = \frac{n(n-1)}{2}\]

<p>olur. Çift devreli ligde bu değer ikiyle çarpılır. Round-robin fikstür için kullanılan <strong>çember yöntemi</strong>, katılımcıları her tur döndürerek herkesin birbiriyle karşılaşmasını sağlar. Katılımcı sayısı tekse hayali bir <code class="language-plaintext highlighter-rouge">BYE</code> eklenir ve onunla eşleşen taraf haftayı maç yapmadan geçirir.</p>

<p>Gerçek dünyada maç erteleme, hükmen sonuç, katılımcı çekilmesi ve yönetici düzeltmeleri unutulmamalıdır. Her skor değişikliğini kullanıcı, zaman ve eski değer bilgisiyle bir denetim günlüğüne kaydetmek tartışmaları azaltır. Sonuç girişini yetkilendirme, eşzamanlı güncellemelerde transaction kullanma ve hesaplama motorunu bolca birim testiyle sınama da sistemin görünmeyen savunma hattıdır. Böylece puan tablosu yalnızca şık değil, son düdüğe kadar güvenilir olur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="typescript" /><category term="nodejs" /><category term="veritabanı" /><category term="algoritma" /><category term="turnuva" /><category term="puan-tablosu" /><summary type="html"><![CDATA[Bir lig yönetim sistemi dışarıdan yalnızca takımları sıralayan basit bir tablo gibi görünür. Oysa Open Tournament veya Tournament Software benzeri bir uygulama; fikstür oluşturma, sonuç kaydetme, eşitlik bozma, hükmen galibiyet ve farklı turnuva formatlarını yönetme gibi birçok kuralı aynı potada eritir. Gelin bu dijital hakemin nasıl tasarlanabileceğine bakalım.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/lig-ve-puan-58.png" /><media:content medium="image" url="https://program.sonsuz.us/img/lig-ve-puan-58.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">OpenStreetMap, uMap ve Leaflet ile Harita ve Konum Sistemleri</title><link href="https://program.sonsuz.us/posts/openstreetmap-umap-ve-leaflet-ile-harita-ve-konum-sistemleri/" rel="alternate" type="text/html" title="OpenStreetMap, uMap ve Leaflet ile Harita ve Konum Sistemleri" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/openstreetmap-umap-ve-leaflet-ile-harita-ve-konum-sistemleri</id><content type="html" xml:base="https://program.sonsuz.us/posts/openstreetmap-umap-ve-leaflet-ile-harita-ve-konum-sistemleri/"><![CDATA[<p>Dijital haritalar yalnızca “buradan şuraya nasıl giderim?” sorusunu yanıtlamaz. Mağaza buluculardan afet koordinasyonuna, gezi rotalarından sensör takibine kadar pek çok uygulamanın görünmez kahramanıdır. OpenStreetMap, uMap ve Leaflet üçlüsü sayesinde lisans engellerine takılmadan etkileşimli bir konum sistemi geliştirebiliriz. Üstelik bunun için harita mühendisi şapkası takmamız gerekmiyor!
``</p>
<h2 id="üç-araç-üç-farklı-görev">Üç araç, üç farklı görev</h2>

<p>Bu teknolojiler aynı ekosistemde çalışabilse de birbirlerinin alternatifi değildir. <strong>OpenStreetMap (OSM)</strong> topluluk tarafından üretilen coğrafi verileri sağlar. Yollar, binalar, parklar ve ilgi noktaları bu veri tabanında tutulur. <strong>uMap</strong>, OSM tabanlı kişisel haritaları kod yazmadan hazırlamaya yarar. <strong>Leaflet</strong> ise web sayfasında etkileşimli harita oluşturabileceğimiz hafif bir JavaScript kütüphanesidir.</p>

<table>
  <thead>
    <tr>
      <th>Araç</th>
      <th>Temel görevi</th>
      <th style="text-align: right">Kod gereksinimi</th>
      <th>Uygun kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>OpenStreetMap</td>
      <td>Coğrafi veri üretmek ve paylaşmak</td>
      <td style="text-align: right">Yok / isteğe bağlı</td>
      <td>Açık harita verisi</td>
    </tr>
    <tr>
      <td>uMap</td>
      <td>Özel haritayı görsel arayüzle hazırlamak</td>
      <td style="text-align: right">Yok</td>
      <td>Rotalar, etkinlikler, sunumlar</td>
    </tr>
    <tr>
      <td>Leaflet</td>
      <td>Programlanabilir web haritası oluşturmak</td>
      <td style="text-align: right">JavaScript</td>
      <td>Dinamik web uygulamaları</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/openstreetmap-umap-ve-88.svg" alt="openstreetmap-umap-ve-88" /></p>

<p>Kısacası OSM mutfaktaki malzemeler, uMap hazır yemek tezgâhı, Leaflet ise tarif üzerinde istediğimiz değişikliği yapabildiğimiz şef bıçağıdır.</p>

<h2 id="konum-bilgisinin-matematiği">Konum bilgisinin matematiği</h2>

<p>Dünya üzerindeki bir nokta genellikle enlem ve boylam çiftiyle ifade edilir:</p>

\[P = (\varphi, \lambda)\]

<p>Burada $\varphi$ enlemi, $\lambda$ ise boylamı temsil eder. Enlem kuzey-güney, boylam doğu-batı konumunu belirtir. Leaflet koordinatları çoğunlukla <code class="language-plaintext highlighter-rouge">[enlem, boylam]</code> sırasıyla bekler. GeoJSON standardında ise sıra <code class="language-plaintext highlighter-rouge">[boylam, enlem]</code> biçimindedir. Bu küçük fark, işaretçinizin İstanbul yerine okyanusta yüzmesine neden olabilecek kadar önemlidir.</p>

<p>İki konum arasındaki kuş uçuşu mesafe, küresel Dünya yaklaşımında Haversine formülüyle hesaplanabilir:</p>

\[a=\sin^2(\Delta\varphi/2)+\cos(\varphi_1)\cos(\varphi_2)\sin^2(\Delta\lambda/2)\]

\[d=2R\arcsin(\sqrt{a})\]

<p>$R$ yaklaşık $6371$ kilometredir. Yol mesafesi içinse yolların bağlantılarını içeren bir rota motoruna ihtiyaç duyulur; düz çizgi her zaman kullanılabilir bir cadde değildir.</p>

<h2 id="leaflet-ile-ilk-etkileşimli-harita">Leaflet ile ilk etkileşimli harita</h2>

<p>Önce sayfaya Leaflet CSS ve JavaScript dosyaları eklenmeli, ardından haritanın yerleşeceği elemana yükseklik verilmelidir. Aşağıdaki örnek İstanbul merkezli bir harita oluşturur:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"https://unpkg.com/leaflet/dist/leaflet.css"</span><span class="nt">&gt;</span>
<span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">"map"</span> <span class="na">style=</span><span class="s">"height: 420px"</span><span class="nt">&gt;&lt;/div&gt;</span>
<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"https://unpkg.com/leaflet/dist/leaflet.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script&gt;</span>
  <span class="kd">const</span> <span class="nx">map</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nf">map</span><span class="p">(</span><span class="dl">'</span><span class="s1">map</span><span class="dl">'</span><span class="p">).</span><span class="nf">setView</span><span class="p">([</span><span class="mf">41.0082</span><span class="p">,</span> <span class="mf">28.9784</span><span class="p">],</span> <span class="mi">12</span><span class="p">);</span>

  <span class="nx">L</span><span class="p">.</span><span class="nf">tileLayer</span><span class="p">(</span><span class="dl">'</span><span class="s1">https://tile.openstreetmap.org/{z}/{x}/{y}.png</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">maxZoom</span><span class="p">:</span> <span class="mi">19</span><span class="p">,</span>
    <span class="na">attribution</span><span class="p">:</span> <span class="dl">'</span><span class="s1">&amp;copy; OpenStreetMap katkıda bulunanlar</span><span class="dl">'</span>
  <span class="p">}).</span><span class="nf">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>

  <span class="kd">const</span> <span class="nx">marker</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nf">marker</span><span class="p">([</span><span class="mf">41.0082</span><span class="p">,</span> <span class="mf">28.9784</span><span class="p">]).</span><span class="nf">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
  <span class="nx">marker</span><span class="p">.</span><span class="nx">bindPopup</span><span class="p">(</span><span class="dl">'</span><span class="s1">&lt;strong&gt;İstanbul&lt;/strong&gt;&lt;br&gt;Harita burada başlıyor!</span><span class="dl">'</span><span class="p">);</span>

  <span class="nx">map</span><span class="p">.</span><span class="nf">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="nx">event</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">L</span><span class="p">.</span><span class="nf">popup</span><span class="p">()</span>
      <span class="p">.</span><span class="nf">setLatLng</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">latlng</span><span class="p">)</span>
      <span class="p">.</span><span class="nf">setContent</span><span class="p">(</span><span class="s2">`Konum: </span><span class="p">${</span><span class="nx">event</span><span class="p">.</span><span class="nx">latlng</span><span class="p">.</span><span class="nx">lat</span><span class="p">.</span><span class="nf">toFixed</span><span class="p">(</span><span class="mi">5</span><span class="p">)}</span><span class="s2">, </span><span class="p">${</span><span class="nx">event</span><span class="p">.</span><span class="nx">latlng</span><span class="p">.</span><span class="nx">lng</span><span class="p">.</span><span class="nf">toFixed</span><span class="p">(</span><span class="mi">5</span><span class="p">)}</span><span class="s2">`</span><span class="p">)</span>
      <span class="p">.</span><span class="nf">openOn</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
  <span class="p">});</span>
<span class="nt">&lt;/script&gt;</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">setView</code> başlangıç merkezini ve yakınlaştırma seviyesini belirler. <code class="language-plaintext highlighter-rouge">tileLayer</code>, OSM karo görüntülerini haritaya taşır. Tıklama olayı ise kullanıcının seçtiği koordinatı gösterir. Gerçek projelerde herkese açık karo sunucularının kullanım politikasını incelemek, yoğun trafik için uygun bir sağlayıcı seçmek gerekir.</p>

<h2 id="umap-ve-veri-paylaşımı">uMap ve veri paylaşımı</h2>

<p>Kod yazmadan başlamak isteyenler uMap üzerinde işaretçiler, çizgiler ve bölgeler ekleyebilir. Hazırlanan katmanlar GeoJSON olarak dışa aktarılıp Leaflet uygulamasına alınabilir:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">fetch</span><span class="p">(</span><span class="dl">'</span><span class="s1">noktalar.geojson</span><span class="dl">'</span><span class="p">)</span>
  <span class="p">.</span><span class="nf">then</span><span class="p">(</span><span class="nx">response</span> <span class="o">=&gt;</span> <span class="nx">response</span><span class="p">.</span><span class="nf">json</span><span class="p">())</span>
  <span class="p">.</span><span class="nf">then</span><span class="p">(</span><span class="nx">data</span> <span class="o">=&gt;</span> <span class="nx">L</span><span class="p">.</span><span class="nf">geoJSON</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">onEachFeature</span><span class="p">:</span> <span class="p">(</span><span class="nx">feature</span><span class="p">,</span> <span class="nx">layer</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">layer</span><span class="p">.</span><span class="nf">bindPopup</span><span class="p">(</span><span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">name</span> <span class="o">??</span> <span class="dl">'</span><span class="s1">İsimsiz nokta</span><span class="dl">'</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}).</span><span class="nf">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">));</span>
</code></pre></div></div>

<p>Bu yaklaşımda içerik ekibi uMap ile veriyi düzenlerken geliştirici Leaflet arayüzünü yönetir. OSM veriyi, uMap kolay düzenlemeyi, Leaflet ise özgür programlamayı sağlar. Böylece küçük bir gezi rehberinden kapsamlı bir konum platformuna kadar büyüyebilen, açık ve esnek bir mimari kurulur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="openstreetmap" /><category term="umap" /><category term="leaflet" /><category term="javascript" /><category term="harita" /><category term="konum" /><summary type="html"><![CDATA[Dijital haritalar yalnızca “buradan şuraya nasıl giderim?” sorusunu yanıtlamaz. Mağaza buluculardan afet koordinasyonuna, gezi rotalarından sensör takibine kadar pek çok uygulamanın görünmez kahramanıdır. OpenStreetMap, uMap ve Leaflet üçlüsü sayesinde lisans engellerine takılmadan etkileşimli bir konum sistemi geliştirebiliriz. Üstelik bunun için harita mühendisi şapkası takmamız gerekmiyor!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/openstreetmap-umap-ve-88.png" /><media:content medium="image" url="https://program.sonsuz.us/img/openstreetmap-umap-ve-88.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Üyelik ve Topluluk Sistemi Seçimi: HumHub, BuddyPress ve Discourse</title><link href="https://program.sonsuz.us/posts/uyelik-ve-topluluk-sistemi-secimi-humhub-buddypress-ve-discourse/" rel="alternate" type="text/html" title="Üyelik ve Topluluk Sistemi Seçimi: HumHub, BuddyPress ve Discourse" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/uyelik-ve-topluluk-sistemi-secimi-humhub-buddypress-ve-discourse</id><content type="html" xml:base="https://program.sonsuz.us/posts/uyelik-ve-topluluk-sistemi-secimi-humhub-buddypress-ve-discourse/"><![CDATA[<p><img src="/img/uyelik-ve-topluluk-97.svg" alt="uyelik-ve-topluluk-97" /></p>

<p>Bir topluluk platformu kurmak, yalnızca kullanıcıların kayıt olabileceği bir sayfa hazırlamak değildir. Profil yönetimi, içerik üretimi, bildirimler, moderasyon, yetkilendirme ve kullanıcıların geri dönmesini sağlayan sosyal mekanikler birlikte düşünülmelidir. HumHub, BuddyPress ve Discourse bu problemi farklı açılardan çözer: biri sosyal ağ, biri WordPress eklentisi, diğeri ise modern forum yaklaşımını benimser.</p>

<p>``</p>

<h2 id="önce-topluluk-sisteminin-mantığı">Önce topluluk sisteminin mantığı</h2>

<p>Bir üyelik sisteminin merkezinde <strong>kimlik</strong>, <strong>yetki</strong> ve <strong>etkileşim</strong> bulunur. Kimlik katmanı kullanıcının kim olduğunu; yetkilendirme katmanı hangi işlemleri yapabileceğini; etkileşim katmanı ise diğer üyelerle nasıl iletişim kuracağını belirler.</p>

<p>Basit bir topluluk veri modeli şöyle düşünülebilir:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Kullanıcı → Profil → Rol
Kullanıcı → İçerik → Yorum
Kullanıcı → Grup → Üyelik
İçerik → Bildirim → Kullanıcı
</code></pre></div></div>

<p>Topluluk sağlığını ölçmek için yalnızca kayıtlı kullanıcı sayısına bakmak yanıltıcıdır. Daha anlamlı bir ölçü, aktif kullanıcı oranıdır:</p>

\[A = \frac{Günlük\ aktif\ kullanıcı}{Toplam\ kayıtlı\ kullanıcı} \times 100\]

<p>Örneğin 10.000 üyenin yalnızca 200’ü günlük olarak geri dönüyorsa aktiflik oranı yüzde 2’dir. Dolayısıyla yazılım seçerken özellik listesinden çok, hedeflenen etkileşim biçimine odaklanmak gerekir.</p>

<h2 id="üç-platformun-karakteri">Üç platformun karakteri</h2>

<table>
  <thead>
    <tr>
      <th>Platform</th>
      <th>Temel yaklaşım</th>
      <th>Güçlü olduğu alan</th>
      <th>Teknik yapı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>HumHub</td>
      <td>Özel sosyal ağ</td>
      <td>Gruplar, profiller, kurum içi iletişim</td>
      <td>PHP, Yii, MySQL</td>
    </tr>
    <tr>
      <td>BuddyPress</td>
      <td>WordPress’e sosyal katman</td>
      <td>İçerik sitesiyle üyeliği birleştirme</td>
      <td>PHP, WordPress, MySQL</td>
    </tr>
    <tr>
      <td>Discourse</td>
      <td>Tartışma ve bilgi paylaşımı</td>
      <td>Forumlar, destek toplulukları</td>
      <td>Ruby on Rails, PostgreSQL, Redis</td>
    </tr>
  </tbody>
</table>

<h3 id="humhub">HumHub</h3>

<p>HumHub, Facebook benzeri akışların ve çalışma alanlarının önemli olduğu projelerde öne çıkar. Kullanıcılar profil oluşturabilir, alanlara katılabilir, gönderi paylaşabilir ve birbirlerini takip edebilir. Üniversite kulübü, şirket içi ağ veya kapalı meslek topluluğu için doğal bir seçimdir.</p>

<p>Modüler yapısı sayesinde takvim, görev ve dosya paylaşımı gibi yetenekler eklenebilir. Ancak tema ve modül ekosistemi WordPress kadar geniş değildir. Sunucu yönetimi konusunda temel Linux, PHP ve veritabanı bilgisi gerekir.</p>

<h3 id="buddypress">BuddyPress</h3>

<p>BuddyPress bağımsız bir uygulama değil, WordPress’i topluluk sistemine dönüştüren bir eklentidir. Mevcut sitenizde blog, kurs, mağaza veya üyelik altyapısı varsa oldukça pratiktir. WooCommerce ve LMS eklentileriyle beraber kullanıldığında ücretli topluluklar kurulabilir.</p>

<p>WordPress kancaları üzerinden davranış eklemek mümkündür:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">add_action</span><span class="p">(</span><span class="s1">'bp_init'</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="c1">// BuddyPress yüklendikten sonra özel topluluk işlemlerini başlatır.</span>
    <span class="k">if</span> <span class="p">(</span><span class="nf">is_user_logged_in</span><span class="p">())</span> <span class="p">{</span>
        <span class="nf">update_user_meta</span><span class="p">(</span><span class="nf">get_current_user_id</span><span class="p">(),</span> <span class="s1">'son_topluluk_girisi'</span><span class="p">,</span> <span class="nb">time</span><span class="p">());</span>
    <span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div>

<p>Bu kod, giriş yapmış üyenin son topluluk ziyaretini kaydeder. Böylece geri dönüş oranı veya pasif üyeler analiz edilebilir. Bununla birlikte çok sayıda eklenti kullanmak performans, güvenlik ve uyumluluk sorunları doğurabilir.</p>

<h3 id="discourse">Discourse</h3>

<p>Discourse, klasik forumları daha akıcı hale getirir. Güven seviyeleri, güçlü moderasyon araçları, e-posta ile yanıt, rozetler ve gerçek zamanlı bildirimler hazır gelir. Teknik destek, açık kaynak proje veya soru-cevap odaklı topluluklar için başarılıdır.</p>

<p>Platformun güven sistemi, olumlu davranış sergileyen kullanıcılara zamanla daha fazla yetki verir. Bu yaklaşım moderasyon yükünü topluluğa dağıtır. Docker tabanlı önerilen kurulum güvenilir olsa da düşük kaynaklı paylaşımlı hosting paketlerine pek uygun değildir.</p>

<h2 id="hangisini-seçmelisiniz">Hangisini seçmelisiniz?</h2>

<table>
  <thead>
    <tr>
      <th>İhtiyaç</th>
      <th>Öneri</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kurum içi sosyal ağ</td>
      <td>HumHub</td>
    </tr>
    <tr>
      <td>WordPress tabanlı üyelik sitesi</td>
      <td>BuddyPress</td>
    </tr>
    <tr>
      <td>Destek, tartışma ve bilgi arşivi</td>
      <td>Discourse</td>
    </tr>
    <tr>
      <td>E-ticaretle bütünleşme</td>
      <td>BuddyPress</td>
    </tr>
    <tr>
      <td>Güçlü yerleşik moderasyon</td>
      <td>Discourse</td>
    </tr>
  </tbody>
</table>

<p>Karar verirken toplam maliyeti $M = K + B + E$ biçiminde değerlendirebilirsiniz. Burada $K$ kurulum, $B$ bakım, $E$ ise eklenti ve entegrasyon gideridir. Yazılımların açık kaynak olması, işletmenin tamamen ücretsiz olacağı anlamına gelmez.</p>

<p>Özetle sosyal akış ve gruplar için HumHub, WordPress ekosistemi için BuddyPress, uzun ömürlü tartışmalar için Discourse daha uygundur. En iyi platform, en çok özelliğe sahip olan değil; üyelerin neden geri geleceği sorusuna en net cevabı verendir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="humhub" /><category term="buddypress" /><category term="discourse" /><category term="topluluk" /><category term="üyelik" /><category term="açık-kaynak" /><summary type="html"><![CDATA[Bir topluluk platformu kurmak, yalnızca kullanıcıların kayıt olabileceği bir sayfa hazırlamak değildir. Profil yönetimi, içerik üretimi, bildirimler, moderasyon, yetkilendirme ve kullanıcıların geri dönmesini sağlayan sosyal mekanikler birlikte düşünülmelidir. HumHub, BuddyPress ve Discourse bu problemi farklı açılardan çözer: biri sosyal ağ, biri WordPress eklentisi, diğeri ise modern forum yaklaşımını benimser.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/uyelik-ve-topluluk-97.png" /><media:content medium="image" url="https://program.sonsuz.us/img/uyelik-ve-topluluk-97.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Yapay Zekâ Sohbet Arayüzleri: Open WebUI, LibreChat ve Chatbot UI Karşılaştırması</title><link href="https://program.sonsuz.us/posts/yapay-zeka-sohbet-arayuzleri-open-webui-librechat-ve-chatbot-ui-karsilastirmasi/" rel="alternate" type="text/html" title="Yapay Zekâ Sohbet Arayüzleri: Open WebUI, LibreChat ve Chatbot UI Karşılaştırması" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/yapay-zeka-sohbet-arayuzleri-open-webui-librechat-ve-chatbot-ui-karsilastirmasi</id><content type="html" xml:base="https://program.sonsuz.us/posts/yapay-zeka-sohbet-arayuzleri-open-webui-librechat-ve-chatbot-ui-karsilastirmasi/"><![CDATA[<p>ChatGPT benzeri bir sohbet deneyimi oluşturmak için arayüzü sıfırdan geliştirmek zorunda değilsiniz. Open WebUI, LibreChat ve Chatbot UI; yerel ya da bulut tabanlı büyük dil modellerini kullanışlı bir web ekranıyla buluşturan üç güçlü açık kaynak seçenektir. Ancak görünüşleri benzer olsa da kurulum kolaylığı, model desteği ve hedef kullanıcı bakımından farklı karakterlere sahiptirler.</p>

<p>``</p>

<h2 id="sohbet-arayüzü-gerçekte-ne-yapar">Sohbet arayüzü gerçekte ne yapar?</h2>

<p>Bir yapay zekâ sohbet arayüzü yalnızca renkli mesaj balonlarından ibaret değildir. Kullanıcının mesajını alır, konuşma geçmişini düzenler, uygun model sağlayıcısına istek gönderir ve yanıtı çoğunlukla akış hâlinde ekrana taşır. Temel akış şöyle özetlenebilir:</p>

\[Kullanıcı\ Mesajı \rightarrow Arayüz \rightarrow API \rightarrow LLM \rightarrow Yanıt\]

<p>Dil modellerinde bağlam penceresi sınırlıdır. Arayüz, önceki mesajları modele tekrar gönderdiği için yaklaşık toplam kullanım şu şekilde düşünülebilir:</p>

\[T_{toplam} = T_{sistem} + T_{geçmiş} + T_{mesaj} + T_{yanıt}\]

<p>Buradaki $T$, token sayısını temsil eder. Sohbet uzadıkça geçmiş büyür; maliyet ve bellek ihtiyacı artar. İyi bir arayüz bu nedenle konuşma yönetimi, model seçimi, belge yükleme, kullanıcı yetkilendirme ve geçmiş arama gibi görevleri de üstlenir.</p>

<h2 id="üç-adayın-kısa-karşılaştırması">Üç adayın kısa karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Open WebUI</th>
      <th>LibreChat</th>
      <th>Chatbot UI</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ana yaklaşım</td>
      <td>Yerel model ve Ollama odaklı</td>
      <td>Çoklu sağlayıcı merkezi</td>
      <td>Sade ve özelleştirilebilir arayüz</td>
    </tr>
    <tr>
      <td>Kurulum</td>
      <td>Çok kolay</td>
      <td>Orta düzey</td>
      <td>Orta düzey</td>
    </tr>
    <tr>
      <td>Model desteği</td>
      <td>Ollama, OpenAI uyumlu API’ler</td>
      <td>OpenAI, Anthropic, Google ve diğerleri</td>
      <td>Yapılandırmaya bağlı sağlayıcılar</td>
    </tr>
    <tr>
      <td>Çoklu kullanıcı</td>
      <td>Güçlü</td>
      <td>Güçlü</td>
      <td>Dağıtıma göre değişir</td>
    </tr>
    <tr>
      <td>RAG/belge kullanımı</td>
      <td>Yerleşik ve pratik</td>
      <td>Gelişmiş seçenekler</td>
      <td>Ek yapılandırma gerekebilir</td>
    </tr>
    <tr>
      <td>En uygun senaryo</td>
      <td>Yerel yapay zekâ laboratuvarı</td>
      <td>Kurumsal ve çok sağlayıcılı kullanım</td>
      <td>Kendi ürün arayüzünü geliştirme</td>
    </tr>
  </tbody>
</table>

<h2 id="open-webui-yerel-model-meraklısı">Open WebUI: Yerel model meraklısı</h2>

<p>Open WebUI özellikle Ollama ile iyi anlaşır. Bilgisayarınızda Llama, Qwen veya Mistral çalıştırıyorsanız birkaç dakika içinde tarayıcı tabanlı bir sohbet ekranı kurabilirsiniz. Model yönetimi, kullanıcı hesapları, belge tabanlı soru-cevap ve OpenAI uyumlu bağlantılar sunması önemli avantajlarıdır.</p>

<p>Aşağıdaki komut, arayüzü Docker üzerinden çalıştırır ve Ollama servisine bağlanmasını sağlar:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">-d</span> <span class="se">\</span>
  <span class="nt">-p</span> 3000:8080 <span class="se">\</span>
  <span class="nt">-e</span> <span class="nv">OLLAMA_BASE_URL</span><span class="o">=</span>http://host.docker.internal:11434 <span class="se">\</span>
  <span class="nt">-v</span> open-webui:/app/backend/data <span class="se">\</span>
  <span class="nt">--name</span> open-webui <span class="se">\</span>
  ghcr.io/open-webui/open-webui:main
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">-v</code> seçeneği sohbetlerin ve ayarların kalıcı olmasını sağlar. Kurulumdan sonra arayüze <code class="language-plaintext highlighter-rouge">http://localhost:3000</code> adresinden erişilir.</p>

<h2 id="librechat-modeller-arasında-i̇sviçre-çakısı">LibreChat: Modeller arasında İsviçre çakısı</h2>

<p>LibreChat, birden fazla ticari ve açık model sağlayıcısını aynı panelde toplamak isteyenlere hitap eder. Kullanıcı yönetimi, hazır istemler, eklentiler, dosya etkileşimi ve farklı asistan yapılandırmaları bakımından zengindir. Bunun bedeli, Open WebUI’ye kıyasla daha fazla servis ve çevre değişkeniyle uğraşmaktır.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/danny-avila/LibreChat.git
<span class="nb">cd </span>LibreChat
<span class="nb">cp</span> .env.example .env
docker compose up <span class="nt">-d</span>
</code></pre></div></div>

<p>Bu komutlar projeyi indirir, örnek yapılandırmayı oluşturur ve gerekli bileşenleri başlatır. API anahtarları kullanılmadan önce <code class="language-plaintext highlighter-rouge">.env</code> dosyasına eklenmelidir; dosya kesinlikle Git deposuna gönderilmemelidir.</p>

<h2 id="chatbot-ui-özelleştirme-isteyen-geliştirici">Chatbot UI: Özelleştirme isteyen geliştirici</h2>

<p>Chatbot UI, sade yapısı ve modern web teknolojileri sayesinde kendi yapay zekâ ürününü şekillendirmek isteyen geliştiriciler için çekicidir. Tasarımı değiştirmek, yeni iş akışları eklemek veya arayüzü mevcut bir ürüne uyarlamak görece rahattır. Buna karşılık bazı gelişmiş yönetim ve RAG özelliklerini sizin tamamlamanız gerekebilir.</p>

<h2 id="hangisini-seçmelisiniz">Hangisini seçmelisiniz?</h2>

<p>Yerel modellerle hızlıca başlamak ve veriyi kendi cihazınızda tutmak istiyorsanız <strong>Open WebUI</strong> en rahat seçimdir. Çok sayıda sağlayıcıyı, kullanıcıyı ve gelişmiş özelliği tek merkezde yönetmek istiyorsanız <strong>LibreChat</strong> öne çıkar. Arayüzü çatallayıp kendi markanıza ve iş mantığınıza göre dönüştürmek istiyorsanız <strong>Chatbot UI</strong> daha uygun bir temel sunar.</p>

<p>Kısacası tek bir mutlak kazanan yoktur: Open WebUI pratik laboratuvar, LibreChat kapsamlı kontrol merkezi, Chatbot UI ise geliştirilebilir bir tuval gibidir. Seçimi ekran görüntülerine göre değil; kullanacağınız modeller, gizlilik beklentiniz ve bakım kapasiteniz üzerinden yapmak en sağlıklı yaklaşımdır.</p>

<p><img src="/img/yapay-zeka-sohbet-14.svg" alt="yapay-zeka-sohbet-14" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="yapay zekâ" /><category term="open webui" /><category term="librechat" /><category term="chatbot ui" /><category term="llm" /><category term="docker" /><summary type="html"><![CDATA[ChatGPT benzeri bir sohbet deneyimi oluşturmak için arayüzü sıfırdan geliştirmek zorunda değilsiniz. Open WebUI, LibreChat ve Chatbot UI; yerel ya da bulut tabanlı büyük dil modellerini kullanışlı bir web ekranıyla buluşturan üç güçlü açık kaynak seçenektir. Ancak görünüşleri benzer olsa da kurulum kolaylığı, model desteği ve hedef kullanıcı bakımından farklı karakterlere sahiptirler.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/yapay-zeka-sohbet-14.png" /><media:content medium="image" url="https://program.sonsuz.us/img/yapay-zeka-sohbet-14.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>