{"id":34855,"date":"2025-11-22T22:01:44","date_gmt":"2025-11-22T19:01:44","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/"},"modified":"2025-11-22T22:01:44","modified_gmt":"2025-11-22T19:01:44","slug":"neden-dinamik-bir-sidebara-ihtiyac-duyariz","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/","title":{"rendered":"Neden Dinamik Bir Sidebar&#8217;a \u0130htiya\u00e7 Duyar\u0131z?"},"content":{"rendered":"<h1>Docusaurus Benzeri FastAPI Sitesinde Dinamik Sidebar Olu\u015fturma Rehberi<\/h1>\n<p>Modern dok\u00fcmantasyon siteleri, kullan\u0131c\u0131lar\u0131n arad\u0131klar\u0131 bilgiye h\u0131zl\u0131ca ula\u015fmalar\u0131n\u0131 sa\u011flayan, iyi d\u00fczenlenmi\u015f ve etkile\u015fimli sidebar (kenar \u00e7ubu\u011fu) navigasyonuna sahiptir. Docusaurus gibi pop\u00fcler statik site \u00fcreticileri bu konuda standartlar\u0131 belirlerken, FastAPI ile dinamik bir web sitesi geli\u015ftirirken benzer bir deneyimi nas\u0131l sunabiliriz? Bu makalede, FastAPI ve Jinja2 kullanarak, dosya sistemi tabanl\u0131 veya yap\u0131land\u0131rma dosyalar\u0131 \u00fczerinden dinamik olarak olu\u015fturulan, Docusaurus benzeri bir sidebar yap\u0131s\u0131n\u0131 ad\u0131m ad\u0131m in\u015fa edece\u011fiz. Bu sayede, projenizin dok\u00fcmantasyonunu y\u00f6netmek ve kullan\u0131c\u0131lar\u0131n\u0131za kesintisiz bir gezinme deneyimi sunmak art\u0131k \u00e7ok daha kolay olacak. Haz\u0131r m\u0131s\u0131n\u0131z?<\/p>\n<hr>\n<p>G\u00fcn\u00fcm\u00fcz\u00fcn h\u0131zla de\u011fi\u015fen yaz\u0131l\u0131m d\u00fcnyas\u0131nda, projelerin dok\u00fcmantasyonu da s\u00fcrekli g\u00fcncellenme ihtiyac\u0131 hisseder. Manuel olarak y\u00f6netilen statik HTML sayfalar\u0131ndaki navigasyon men\u00fcleri, her de\u011fi\u015fiklikte tek tek g\u00fcncellenmesi gereken bir kabusa d\u00f6n\u00fc\u015febilir. \u00d6zellikle b\u00fcy\u00fck ve \u00e7ok say\u0131da sayfa i\u00e7eren dok\u00fcmantasyon sitelerinde, bu durum geli\u015ftiriciler i\u00e7in ciddi bir zaman kayb\u0131 ve hata kayna\u011f\u0131d\u0131r. \u0130\u015fte bu noktada dinamik bir sidebar \u00e7\u00f6z\u00fcm\u00fc devreye girer. Peki, bu dinamik yakla\u015f\u0131m bize ne gibi avantajlar sunar?<\/p>\n<p>\u00d6ncelikle, <strong>bak\u0131m kolayl\u0131\u011f\u0131<\/strong> en b\u00fcy\u00fck art\u0131d\u0131r. Yeni bir dok\u00fcman sayfas\u0131 ekledi\u011finizde veya mevcut bir sayfay\u0131 sildi\u011finizde, sidebar&#8217;\u0131n\u0131z otomatik olarak g\u00fcncellenir. Bu, geli\u015ftiricilerin sadece i\u00e7erik olu\u015fturmaya odaklanmas\u0131n\u0131 sa\u011flar ve navigasyon elementleriyle u\u011fra\u015fma y\u00fck\u00fcn\u00fc ortadan kald\u0131r\u0131r. Bu durum, \u00f6zellikle \u00e7evik geli\u015ftirme metodolojileri uygulayan ekipler i\u00e7in hayati \u00f6nem ta\u015f\u0131r; zira i\u00e7erik ve yap\u0131land\u0131rma aras\u0131ndaki ayr\u0131m netle\u015fir, geli\u015ftirme s\u00fcre\u00e7leri h\u0131zlan\u0131r.<\/p>\n<p>\u0130kinci olarak, <strong>tutarl\u0131l\u0131k<\/strong> sa\u011flar. T\u00fcm dok\u00fcmantasyon sayfalar\u0131n\u0131zda ayn\u0131 navigasyon yap\u0131s\u0131n\u0131n kullan\u0131lmas\u0131, kullan\u0131c\u0131 deneyimi a\u00e7\u0131s\u0131ndan kritik \u00f6neme sahiptir. Dinamik sidebar, tutarl\u0131 bir gezinme hiyerar\u015fisi olu\u015fturarak kullan\u0131c\u0131lar\u0131n sitenizde kaybolmas\u0131n\u0131 engeller ve bilgiyi daha kolay bulmalar\u0131na yard\u0131mc\u0131 olur. Ayr\u0131ca, markan\u0131z\u0131n veya projenizin genel g\u00f6rsel kimli\u011fini yans\u0131tan tek tip bir aray\u00fcz sunar.<\/p>\n<p>\u00dc\u00e7\u00fcnc\u00fc bir avantaj ise <strong>\u00f6l\u00e7eklenebilirlik<\/strong>tir. Projeniz b\u00fcy\u00fcd\u00fck\u00e7e ve dok\u00fcmantasyonunuz geni\u015fledik\u00e7e, dinamik bir sistem bu b\u00fcy\u00fcmeye rahatl\u0131kla ayak uydurabilir. Y\u00fczlerce sayfa bar\u0131nd\u0131ran kompleks dok\u00fcmantasyon siteleri bile, iyi tasarlanm\u0131\u015f dinamik bir yap\u0131yla kolayca y\u00f6netilebilir. Bu durum, uzun vadeli projeler i\u00e7in olmazsa olmaz bir \u00f6zelliktir. Ek olarak, i\u00e7erik y\u00f6netimi i\u00e7in farkl\u0131 kaynaklardan (veritaban\u0131, API&#8217;ler, farkl\u0131 dosya t\u00fcrleri) veri \u00e7ekme yetene\u011fi sunar, bu da statik \u00e7\u00f6z\u00fcmlerle m\u00fcmk\u00fcn olmayan bir esneklik sa\u011flar.<\/p>\n<p>Son olarak, <strong>esneklik ve \u00f6zelle\u015ftirme<\/strong> imkanlar\u0131 sunar. Sidebar&#8217;\u0131n\u0131z\u0131n g\u00f6r\u00fcn\u00fcm\u00fcn\u00fc ve davran\u0131\u015f\u0131n\u0131 merkezi bir yerden, genellikle bir yap\u0131land\u0131rma dosyas\u0131 (YAML veya JSON) arac\u0131l\u0131\u011f\u0131yla veya dosya sisteminin kendisini tarayarak kolayca de\u011fi\u015ftirebilirsiniz. Bu sayede, farkl\u0131 kullan\u0131c\u0131 gruplar\u0131 veya farkl\u0131 ba\u011flamlar i\u00e7in \u00f6zelle\u015ftirilmi\u015f navigasyon men\u00fcleri olu\u015fturmak m\u00fcmk\u00fcn hale gelir. \u00d6rne\u011fin, belirli rollerdeki kullan\u0131c\u0131lar i\u00e7in farkl\u0131 men\u00fc \u00f6\u011feleri g\u00f6sterebilir veya projenin farkl\u0131 versiyonlar\u0131na \u00f6zel navigasyonlar sunabilirsiniz. Bu t\u00fcr dinamik \u00f6zelle\u015ftirmeler, kullan\u0131c\u0131 deneyimini zenginle\u015ftirirken ayn\u0131 zamanda geli\u015ftiricilere de b\u00fcy\u00fck bir kontrol sa\u011flar.<\/p>\n<p>Peki, Docusaurus gibi ara\u00e7lar bunu zaten yaparken, neden FastAPI ile kendi \u00e7\u00f6z\u00fcm\u00fcm\u00fcz\u00fc in\u015fa etmeliyiz? Docusaurus harika bir ara\u00e7t\u0131r, ancak bazen daha fazla esnekli\u011fe, \u00f6zel bir arka u\u00e7 entegrasyonuna veya sadece Python ekosistemi i\u00e7inde kalma iste\u011fine ihtiyac\u0131m\u0131z olabilir. \u00d6zellikle dok\u00fcmantasyonunuz bir web uygulamas\u0131yla i\u00e7 i\u00e7e ge\u00e7mi\u015fse veya i\u00e7eri\u011fi dinamik olarak bir veritaban\u0131ndan \u00e7ekmek gibi daha karma\u015f\u0131k gereksinimleriniz varsa, FastAPI ile kendi \u00e7\u00f6z\u00fcm\u00fcn\u00fcz\u00fc olu\u015fturmak size tam kontrol sa\u011flayacakt\u0131r. Bu yakla\u015f\u0131m, dok\u00fcmantasyonunuzu bir statik site s\u0131n\u0131rlar\u0131n\u0131n \u00f6tesine ta\u015f\u0131yarak, API entegrasyonlar\u0131, kullan\u0131c\u0131 kimlik do\u011frulamas\u0131 veya ki\u015fiselle\u015ftirilmi\u015f i\u00e7erik sunumu gibi \u00f6zelliklerle zenginle\u015ftirme potansiyeli sunar. K\u0131sacas\u0131, kontrol\u00fcn tamamen sizde oldu\u011fu, projenizin \u00f6zel ihtiya\u00e7lar\u0131na g\u00f6re \u015fekillenebilen bir \u00e7\u00f6z\u00fcm in\u015fa etmek istiyorsan\u0131z, do\u011fru yerdesiniz.<\/p>\n<aside class=\"expert-tip\">\n  Uzman \u0130pucu: Dinamik sidebar yap\u0131s\u0131 sadece dok\u00fcmantasyon siteleri i\u00e7in de\u011fil, ayn\u0131 zamanda CMS (\u0130\u00e7erik Y\u00f6netim Sistemi) benzeri uygulamalar veya geni\u015f idari paneller i\u00e7in de temel bir ihtiya\u00e7t\u0131r. FastAPI ile bu yap\u0131y\u0131 kurmak, gelecekteki geni\u015fletmelere kar\u015f\u0131 projenizi daha diren\u00e7li hale getirir.<br \/>\n<\/aside>\n<h2>Sidebar Olu\u015fturma S\u00fcrecinin Temel Kavramlar\u0131 ve Mimarisi<\/h2>\n<p>FastAPI ile Docusaurus benzeri bir sidebar olu\u015fturmak, asl\u0131nda birka\u00e7 temel teknolojinin ve yakla\u015f\u0131m\u0131n birle\u015fimini gerektirir. Bu s\u00fcre\u00e7te neler kullanaca\u011f\u0131m\u0131z\u0131 ve genel mimarinin nas\u0131l i\u015fleyece\u011fini anlamak, ad\u0131mlar\u0131 daha kolay takip etmenizi sa\u011flayacakt\u0131r. Temelde, bir &#8220;yap\u0131land\u0131rma&#8221; katman\u0131, bir &#8220;i\u015fleme&#8221; katman\u0131 ve bir &#8220;sunum&#8221; katman\u0131ndan bahsedebiliriz.<\/p>\n<h3>Yap\u0131land\u0131rma Katman\u0131: \u0130\u00e7eri\u011fimizi Nas\u0131l Tan\u0131mlar\u0131z?<\/h3>\n<p>Docusaurus gibi sistemler genellikle Markdown dosyalar\u0131n\u0131 ve bunlar\u0131n dizin yap\u0131s\u0131n\u0131 otomatik olarak alg\u0131layarak veya <code>_category_.json<\/code>, <code>sidebar.js<\/code> gibi yap\u0131land\u0131rma dosyalar\u0131yla \u00e7al\u0131\u015f\u0131r. Bizim de benzer bir yakla\u015f\u0131ma ihtiyac\u0131m\u0131z var. \u0130\u00e7eri\u011fimizin (dok\u00fcmanlar\u0131m\u0131z\u0131n) hangi s\u0131rayla ve hangi ba\u015fl\u0131klar alt\u0131nda sidebar&#8217;da g\u00f6r\u00fcnece\u011fini belirlemeliyiz. Bunun i\u00e7in iki yayg\u0131n y\u00f6ntem izlenebilir:<\/p>\n<ol>\n<li><strong>Dosya Sistemi Tabanl\u0131 Yap\u0131land\u0131rma:<\/strong> Dok\u00fcmanlar\u0131n\u0131z\u0131 belirli bir klas\u00f6r yap\u0131s\u0131 i\u00e7inde tutars\u0131n\u0131z (\u00f6rne\u011fin, <code>docs\/getting_started\/introduction.md<\/code>, <code>docs\/features\/feature_x.md<\/code>). FastAPI uygulamam\u0131z, bu klas\u00f6r yap\u0131s\u0131n\u0131 tarar ve her bir Markdown dosyas\u0131n\u0131 bir sidebar \u00f6\u011fesi olarak alg\u0131lar. Klas\u00f6r isimleri kategorileri, dosya isimleri ise sayfalar\u0131 temsil edebilir. Bu y\u00f6ntem, \u00f6zellikle dosya tabanl\u0131 bir i\u00e7erik y\u00f6netimi tercih edenler i\u00e7in olduk\u00e7a pratik ve s\u00fcrd\u00fcr\u00fclebilirdir. Ancak, \u00f6\u011felerin s\u0131ras\u0131n\u0131 veya ba\u015fl\u0131klar\u0131n\u0131 dosya adlar\u0131ndan ba\u011f\u0131ms\u0131z olarak kontrol etmek istedi\u011finizde s\u0131n\u0131rlay\u0131c\u0131 olabilir.<\/li>\n<li><strong>Harici Yap\u0131land\u0131rma Dosyas\u0131 (YAML\/JSON):<\/strong> Sidebar&#8217;\u0131n\u0131z\u0131n t\u00fcm yap\u0131s\u0131n\u0131 (kategoriler, alt kategoriler, sayfalar ve bunlar\u0131n s\u0131ras\u0131) bir YAML veya JSON dosyas\u0131 i\u00e7inde a\u00e7\u0131k\u00e7a tan\u0131mlars\u0131n\u0131z (\u00f6rne\u011fin, <code>sidebar.yaml<\/code>). Bu dosya, uygulaman\u0131z taraf\u0131ndan okunur ve sidebar bu tan\u0131ma g\u00f6re in\u015fa edilir. Bu y\u00f6ntem, dosya sistemi yap\u0131s\u0131ndan ba\u011f\u0131ms\u0131z olarak daha esnek bir s\u0131ralama ve ba\u015fl\u0131kland\u0131rma kontrol\u00fc sa\u011flar. Ayr\u0131ca, tek bir merkezden sidebar&#8217;\u0131n t\u00fcm g\u00f6r\u00fcn\u00fcm\u00fcn\u00fc ve i\u00e7eri\u011fini y\u00f6netme imkan\u0131 sunar.<\/li>\n<\/ol>\n<p>Biz bu makalede ikinci y\u00f6nteme, yani harici bir YAML yap\u0131land\u0131rma dosyas\u0131na odaklanaca\u011f\u0131z \u00e7\u00fcnk\u00fc bu, daha esnek ve Docusaurus&#8217;un &#8220;sidebar.js&#8221; mant\u0131\u011f\u0131na daha yak\u0131n bir kontrol sunar. YAML, hem okunabilirli\u011fi hem de hiyerar\u015fik veri tan\u0131mlama yetene\u011fi sayesinde bu t\u00fcr yap\u0131land\u0131rmalar i\u00e7in idealdir.<\/p>\n<h3>\u0130\u015fleme Katman\u0131: FastAPI ve Python&#8217;\u0131n G\u00fcc\u00fc<\/h3>\n<p>Yap\u0131land\u0131rma dosyam\u0131z\u0131 veya dosya sistemimizi okuduktan sonra, bu ham veriyi HTML&#8217;e d\u00f6n\u00fc\u015ft\u00fcrebilece\u011fimiz anlaml\u0131 bir Python veri yap\u0131s\u0131na \u00e7evirmemiz gerekir. \u0130\u015fte burada FastAPI&#8217;nin g\u00fcc\u00fcn\u00fc kullanaca\u011f\u0131z:<\/p>\n<ul>\n<li><strong>Dosya Okuma ve Ayr\u0131\u015ft\u0131rma:<\/strong> FastAPI uygulamam\u0131z, <code>sidebar.yaml<\/code> dosyas\u0131n\u0131 okuyacak ve i\u00e7eri\u011fini Python objelerine (listeler, dictionary&#8217;ler) d\u00f6n\u00fc\u015ft\u00fcrecek. Python&#8217;\u0131n <code>yaml<\/code> k\u00fct\u00fcphanesi bu i\u015flem i\u00e7in bi\u00e7ilmi\u015f kaftand\u0131r.<\/li>\n<li><strong>Veri Yap\u0131s\u0131n\u0131n Olu\u015fturulmas\u0131:<\/strong> Okunan yap\u0131land\u0131rmaya g\u00f6re, her bir sidebar \u00f6\u011fesi i\u00e7in uygun bir veri modeli (\u00f6rne\u011fin, <code>SidebarItem<\/code> ad\u0131nda bir Pydantic modeli) olu\u015fturabiliriz. Bu modeller, \u00f6\u011fenin ba\u015fl\u0131\u011f\u0131n\u0131, URL&#8217;sini, alt \u00f6\u011felerini (e\u011fer varsa) ve di\u011fer metadata&#8217;s\u0131n\u0131 i\u00e7erecektir. Bu ad\u0131m, hem veriyi d\u00fczenli tutar hem de tip g\u00fcvenli\u011fi sa\u011flar.<\/li>\n<li><strong>\u0130\u00e7erik Y\u00f6netimi (Markdown):<\/strong> Sidebar \u00f6\u011felerinin i\u015faret etti\u011fi ger\u00e7ek dok\u00fcman i\u00e7erikleri genellikle Markdown dosyalar\u0131d\u0131r. Uygulamam\u0131z, bu Markdown dosyalar\u0131n\u0131 okumal\u0131 ve HTML&#8217;e \u00e7evirmelidir. <code>python-markdown<\/code> veya <code>markdown-it-py<\/code> gibi k\u00fct\u00fcphaneler bu d\u00f6n\u00fc\u015f\u00fcm i\u00e7in kullan\u0131labilir. Bu sayede, yazarlar sadece Markdown ile i\u00e7erik olu\u015ftururken, web aray\u00fcz\u00fcnde bu i\u00e7erik otomatik olarak zengin HTML&#8217;e d\u00f6n\u00fc\u015ft\u00fcr\u00fcl\u00fcr.<\/li>\n<\/ul>\n<h3>Sunum Katman\u0131: Jinja2 ile HTML Olu\u015fturma<\/h3>\n<p>FastAPI do\u011frudan HTML \u00fcretmek yerine, genellikle \u015fablon motorlar\u0131yla entegre \u00e7al\u0131\u015f\u0131r. Jinja2, Python d\u00fcnyas\u0131nda en pop\u00fcler ve g\u00fc\u00e7l\u00fc \u015fablon motorlar\u0131ndan biridir. \u0130\u015fte nas\u0131l kullanaca\u011f\u0131m\u0131z:<\/p>\n<ul>\n<li><strong>\u015eablon Y\u00fckleme:<\/strong> FastAPI, Jinja2 \u015fablonlar\u0131n\u0131 belirli bir klas\u00f6rden (\u00f6rne\u011fin, <code>templates<\/code>) y\u00fckleyecek \u015fekilde yap\u0131land\u0131r\u0131labilir.<\/li>\n<li><strong>Dinamik HTML Olu\u015fturma:<\/strong> \u0130\u015fleme katman\u0131nda haz\u0131rlad\u0131\u011f\u0131m\u0131z Python veri yap\u0131s\u0131n\u0131 (sidebar men\u00fc \u00f6\u011feleri ve dok\u00fcman i\u00e7eri\u011fi), bir Jinja2 \u015fablonuna (\u00f6rne\u011fin, <code>base.html<\/code> veya <code>docs.html<\/code>) parametre olarak g\u00f6nderece\u011fiz.<\/li>\n<li><strong>Sidebar&#8217;\u0131n Render Edilmesi:<\/strong> Jinja2 \u015fablonu, bu veri yap\u0131s\u0131n\u0131 kullanarak dinamik olarak bir <code>\n<ul><\/code> ve <code><\/p>\n<li><\/code> etiketlerinden olu\u015fan bir sidebar men\u00fcs\u00fc olu\u015fturacak. Bu \u015fablon i\u00e7inde d\u00f6ng\u00fcler (<code>for<\/code> loop), ko\u015fullu ifadeler (<code>if<\/code> statement) ve de\u011fi\u015fkenler kullan\u0131larak kompleks men\u00fc yap\u0131lar\u0131 in\u015fa edilebilir. Ayr\u0131ca, ana i\u00e7erik alan\u0131 i\u00e7in de Markdown&#8217;dan d\u00f6n\u00fc\u015ft\u00fcr\u00fclen HTML i\u00e7eri\u011fi buraya yerle\u015ftirilecektir. Bu sayede, t\u00fcm sayfan\u0131n HTML yap\u0131s\u0131 tek bir yerden y\u00f6netilirken, sidebar ve i\u00e7erik dinamik olarak de\u011fi\u015febilir.<\/li>\n<\/ul>\n<p>Bu \u00fc\u00e7 katman\u0131 bir araya getirerek, sadece birka\u00e7 dosya de\u011fi\u015fikli\u011fiyle otomatik olarak g\u00fcncellenen, g\u00fc\u00e7l\u00fc ve esnek bir dok\u00fcmantasyon sitesi navigasyonu olu\u015fturabiliriz. Bu mimari, mod\u00fclerli\u011fi ve ayr\u0131m\u0131 destekleyerek projenizi daha s\u00fcrd\u00fcr\u00fclebilir hale getirir. \u015eimdi bu teorik bilgiyi prati\u011fe d\u00f6kme zaman\u0131!<\/p>\n<aside class=\"expert-tip\">\n  Uzman \u0130pucu: Mimariyi tasarlarken &#8220;Tek Sorumluluk Prensibi&#8221;ni (Single Responsibility Principle) uygulamak, her bir katman\u0131n (yap\u0131land\u0131rma, i\u015fleme, sunum) sadece kendi i\u015fine odaklanmas\u0131n\u0131 sa\u011flar. Bu durum, kodunuzu daha okunabilir, bak\u0131m\u0131 daha kolay ve test edilebilir hale getirir.<br \/>\n<\/aside>\n<h2>Ad\u0131m 1: Proje Yap\u0131s\u0131n\u0131 Olu\u015fturma ve Gerekli K\u00fct\u00fcphaneleri Kurma<\/h2>\n<p>Her b\u00fcy\u00fck projenin temelinde sa\u011flam bir yap\u0131land\u0131rma yatar. Docusaurus benzeri bir dok\u00fcmantasyon sitesi olu\u015ftururken de benzer bir yakla\u015f\u0131ma ihtiyac\u0131m\u0131z var. \u0130lk ad\u0131m olarak, projemizin temel dizin yap\u0131s\u0131n\u0131 olu\u015ftural\u0131m ve gerekli Python k\u00fct\u00fcphanelerini kural\u0131m. Bu ad\u0131m, daha sonraki geli\u015ftirmeler i\u00e7in d\u00fczenli ve anla\u015f\u0131l\u0131r bir temel sa\u011flayacakt\u0131r.<\/p>\n<h3>Proje Dizini Yap\u0131s\u0131<\/h3>\n<p>A\u015fa\u011f\u0131daki gibi bir dizin yap\u0131s\u0131, hem dok\u00fcmantasyon i\u00e7eri\u011fimizi hem de FastAPI uygulamam\u0131z\u0131n kodunu d\u00fczenli bir \u015fekilde bar\u0131nd\u0131rmam\u0131z\u0131 sa\u011flar:<\/p>\n<pre><code>\nfastapi-docs-site\/\n\u251c\u2500\u2500 docs\/\n\u2502   \u251c\u2500\u2500 getting-started\/\n\u2502   \u2502   \u251c\u2500\u2500 introduction.md\n\u2502   \u2502   \u2514\u2500\u2500 installation.md\n\u2502   \u251c\u2500\u2500 features\/\n\u2502   \u2502   \u251c\u2500\u2500 feature-x.md\n\u2502   \u2502   \u2514\u2500\u2500 feature-y.md\n\u2502   \u2514\u2500\u2500 _category_.yaml  # \u0130ste\u011fe ba\u011fl\u0131, kategoriler i\u00e7in metadata\n\u251c\u2500\u2500 templates\/\n\u2502   \u251c\u2500\u2500 base.html\n\u2502   \u2514\u2500\u2500 doc_page.html\n\u251c\u2500\u2500 static\/\n\u2502   \u251c\u2500\u2500 css\/\n\u2502   \u2502   \u2514\u2500\u2500 style.css\n\u2502   \u2514\u2500\u2500 js\/\n\u2502       \u2514\u2500\u2500 main.js\n\u251c\u2500\u2500 sidebar.yaml\n\u251c\u2500\u2500 main.py\n\u251c\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 .gitignore\n<\/pre>\n<p><\/code><\/p>\n<p>Bu yap\u0131y\u0131 biraz a\u00e7al\u0131m:<\/p>\n<ul>\n<li><code>fastapi-docs-site\/<\/code>: Projemizin ana dizini.<\/li>\n<li><code>docs\/<\/code>: T\u00fcm Markdown dok\u00fcmanlar\u0131m\u0131z\u0131n bulundu\u011fu ana klas\u00f6r. \u0130\u00e7indeki alt klas\u00f6rler (\u00f6rne\u011fin, <code>getting-started<\/code>, <code>features<\/code>) do\u011frudan sidebar kategorilerini temsil edebilir veya yap\u0131land\u0131rma dosyam\u0131zda referans g\u00f6sterece\u011fimiz gruplamalar\u0131 olu\u015fturur. Her bir <code>.md<\/code> dosyas\u0131, tek bir dok\u00fcman sayfas\u0131na kar\u015f\u0131l\u0131k gelir.<\/li>\n<li><code>templates\/<\/code>: Jinja2 \u015fablon dosyalar\u0131m\u0131z\u0131n yer alaca\u011f\u0131 dizin. <code>base.html<\/code> genel sayfa yap\u0131m\u0131z\u0131 (header, footer, sidebar konteyneri vb.) tan\u0131mlarken, <code>doc_page.html<\/code> spesifik olarak dok\u00fcman i\u00e7eri\u011finin nas\u0131l yerle\u015ftirilece\u011fini ve <code>base.html<\/code>'i nas\u0131l geni\u015fletece\u011fini belirler.<\/li>\n<li><code>static\/<\/code>: CSS, JavaScript ve resimler gibi statik dosyalar\u0131m\u0131z\u0131n bulundu\u011fu dizin. Bu dosyalar do\u011frudan taray\u0131c\u0131 taraf\u0131ndan eri\u015filebilir olacakt\u0131r.<\/li>\n<li><code>sidebar.yaml<\/code>: Sidebar'\u0131m\u0131z\u0131n yap\u0131s\u0131n\u0131 ve i\u00e7eri\u011fini tan\u0131mlayaca\u011f\u0131m\u0131z YAML yap\u0131land\u0131rma dosyas\u0131. Bu dosya, <code>docs\/<\/code> klas\u00f6r\u00fcndeki i\u00e7eri\u011fin nas\u0131l grupland\u0131r\u0131laca\u011f\u0131n\u0131 ve hangi s\u0131rada g\u00f6sterilece\u011fini belirleyecek.<\/li>\n<li><code>main.py<\/code>: FastAPI uygulamam\u0131z\u0131n ana kodu, rotalar\u0131 ve mant\u0131\u011f\u0131 burada yer alacak.<\/li>\n<li><code>requirements.txt<\/code>: Projemizin ba\u011f\u0131ml\u0131l\u0131klar\u0131n\u0131 listeleyen dosya.<\/li>\n<li><code>.gitignore<\/code>: Git versiyon kontrol sistemi taraf\u0131ndan g\u00f6rmezden gelinecek dosyalar\u0131 belirler (\u00f6rne\u011fin, sanal ortamlar, ge\u00e7ici dosyalar).<\/li>\n<\/ul>\n<h3>Gerekli K\u00fct\u00fcphaneleri Kurma<\/h3>\n<p>Projemizin \u00e7al\u0131\u015fabilmesi i\u00e7in birka\u00e7 temel Python k\u00fct\u00fcphanesine ihtiyac\u0131m\u0131z var. Bu k\u00fct\u00fcphaneler, FastAPI uygulamas\u0131n\u0131 \u00e7al\u0131\u015ft\u0131rmak, Jinja2 \u015fablonlar\u0131n\u0131 i\u015flemek, YAML yap\u0131land\u0131rmalar\u0131n\u0131 okumak ve Markdown i\u00e7eri\u011fini HTML'e d\u00f6n\u00fc\u015ft\u00fcrmek i\u00e7in kullan\u0131lacak. <code>requirements.txt<\/code> dosyan\u0131z\u0131 a\u015fa\u011f\u0131daki gibi olu\u015fturabilirsiniz:<\/p>\n<pre><code class=\"language-plaintext\">\nfastapi==0.111.0\nuvicorn==0.29.0\nJinja2==3.1.4\nPyYAML==6.0.1\nmarkdown==3.6\npython-multipart==0.0.9 # FastAPI'nin form verilerini i\u015flemesi i\u00e7in gerekli olabilir\n<\/pre>\n<p><\/code><\/p>\n<p>Daha sonra, bu ba\u011f\u0131ml\u0131l\u0131klar\u0131 bir sanal ortamda (virtual environment) kurmak en iyi uygulamad\u0131r. B\u00f6ylece projenizin ba\u011f\u0131ml\u0131l\u0131klar\u0131 sisteminizdeki di\u011fer Python projelerinden izole edilmi\u015f olur:<\/p>\n<pre><code class=\"language-bash\">\n# Sanal ortam olu\u015fturma\npython -m venv venv\n\n# Sanal ortam\u0131 etkinle\u015ftirme (Linux\/macOS)\nsource venv\/bin\/activate\n\n# Sanal ortam\u0131 etkinle\u015ftirme (Windows)\n.\\venv\\Scripts\\activate\n\n# Ba\u011f\u0131ml\u0131l\u0131klar\u0131 kurma\npip install -r requirements.txt\n<\/pre>\n<p><\/code><\/p>\n<p>Bu komutlar, projeniz i\u00e7in gerekli t\u00fcm ara\u00e7lar\u0131 y\u00fckleyecek ve geli\u015ftirme ortam\u0131n\u0131z\u0131 haz\u0131rlayacakt\u0131r. Art\u0131k temel altyap\u0131m\u0131z haz\u0131r oldu\u011funa g\u00f6re, bir sonraki ad\u0131mda sidebar yap\u0131land\u0131rma dosyam\u0131z\u0131 olu\u015fturmaya ge\u00e7ebiliriz. Bu d\u00fczenli kurulum, gelecekteki olas\u0131 sorunlar\u0131 minimize eder ve projenizi daha y\u00f6netilebilir k\u0131lar. Bu sayede, i\u00e7erik geli\u015ftirmeye ve uygulaman\u0131n mant\u0131\u011f\u0131na daha fazla odaklanabilirsiniz.<\/p>\n<aside class=\"expert-tip\">\n  Uzman \u0130pucu: Sanal ortam kullanmak, Python projelerinde ba\u011f\u0131ml\u0131l\u0131k \u00e7ak\u0131\u015fmalar\u0131n\u0131 \u00f6nlemenin alt\u0131n kural\u0131d\u0131r. Her projeye \u00f6zel bir sanal ortam olu\u015fturarak, farkl\u0131 projelerin farkl\u0131 k\u00fct\u00fcphane versiyonlar\u0131na ihtiya\u00e7 duymas\u0131 durumunda ortaya \u00e7\u0131kabilecek sorunlardan ka\u00e7\u0131nabilirsiniz.<br \/>\n<\/aside>\n<h2>Ad\u0131m 2: Sidebar Yap\u0131land\u0131rmas\u0131n\u0131 Tan\u0131mlama (sidebar.yaml ile)<\/h2>\n<p>Dinamik sidebar'\u0131m\u0131z\u0131n kalbi, onun nas\u0131l g\u00f6r\u00fcnece\u011fini ve hangi sayfalar\u0131 i\u00e7erece\u011fini belirleyen yap\u0131land\u0131rma dosyas\u0131d\u0131r. Docusaurus'un <code>sidebar.js<\/code> dosyalar\u0131na benzer \u015fekilde, biz de bir <code>sidebar.yaml<\/code> dosyas\u0131 kullanarak bu yap\u0131y\u0131 tan\u0131mlayaca\u011f\u0131z. YAML, hiyerar\u015fik verileri insan taraf\u0131ndan okunabilir bir formatta ifade etmek i\u00e7in idealdir ve bu nedenle dok\u00fcmantasyon yap\u0131land\u0131rmas\u0131 i\u00e7in m\u00fckemmel bir se\u00e7imdir.<\/p>\n<h3>sidebar.yaml Dosyas\u0131n\u0131n Yap\u0131s\u0131<\/h3>\n<p><code>sidebar.yaml<\/code> dosyas\u0131n\u0131n, dok\u00fcmanlar\u0131n\u0131z\u0131n mant\u0131ksal gruplamalar\u0131n\u0131 ve bu gruplar i\u00e7indeki sayfalar\u0131n s\u0131ras\u0131n\u0131 net bir \u015fekilde belirtmesi gerekmektedir. \u0130\u015fte \u00f6rnek bir <code>sidebar.yaml<\/code> i\u00e7eri\u011fi:<\/p>\n<pre><code class=\"language-yaml\">\n- type: category\n  label: Ba\u015flang\u0131\u00e7\n  collapsible: true\n  collapsed: false\n  items:\n    - type: doc\n      id: getting-started\/introduction\n      label: Giri\u015f\n    - type: doc\n      id: getting-started\/installation\n      label: Kurulum\n    - type: doc\n      id: getting-started\/first-steps\n      label: \u0130lk Ad\u0131mlar\n\n- type: category\n  label: \u00d6zellikler\n  collapsible: true\n  collapsed: true\n  items:\n    - type: doc\n      id: features\/feature-x\n      label: X \u00d6zelli\u011fi\n    - type: doc\n      id: features\/feature-y\n      label: Y \u00d6zelli\u011fi\n\n- type: link\n  label: Harici Ba\u011flant\u0131\n  href: https:\/\/fastapi.tiangolo.com\/\n  target: _blank\n\n- type: doc\n  id: legal\/privacy-policy\n  label: Gizlilik Politikas\u0131\n<\/pre>\n<p><\/code><\/p>\n<p>Bu yap\u0131land\u0131rma dosyas\u0131n\u0131 daha yak\u0131ndan inceleyelim:<\/p>\n<ul>\n<li>Her bir ana \u00f6\u011fe, bir kategori, dok\u00fcman veya harici bir ba\u011flant\u0131 olabilir. Bu, <code>type<\/code> anahtar\u0131yla belirtilir.<\/li>\n<li><strong><code>type: category<\/code><\/strong>: Bir grup dok\u00fcman\u0131 temsil eder.\n<ul>\n<li><code>label<\/code>: Sidebar'da g\u00f6r\u00fcnecek kategori ba\u015fl\u0131\u011f\u0131.<\/li>\n<li><code>collapsible<\/code>: (\u0130ste\u011fe ba\u011fl\u0131, varsay\u0131lan <code>true<\/code>) Kategorinin geni\u015fletilebilir\/daralt\u0131labilir olup olmad\u0131\u011f\u0131n\u0131 belirler.<\/li>\n<li><code>collapsed<\/code>: (\u0130ste\u011fe ba\u011fl\u0131, varsay\u0131lan <code>true<\/code>) Sayfa y\u00fcklendi\u011finde kategorinin varsay\u0131lan olarak daralt\u0131lm\u0131\u015f m\u0131 (<code>true<\/code>) yoksa a\u00e7\u0131k m\u0131 (<code>false<\/code>) olaca\u011f\u0131n\u0131 belirtir.<\/li>\n<li><code>items<\/code>: Bu kategoriye ait olan dok\u00fcmanlar\u0131 veya alt kategorileri i\u00e7eren bir liste.<\/li>\n<\/ul>\n<\/li>\n<li><strong><code>type: doc<\/code><\/strong>: Tek bir dok\u00fcman sayfas\u0131n\u0131 temsil eder.\n<ul>\n<li><code>id<\/code>: Dok\u00fcman dosyas\u0131n\u0131n <code>docs\/<\/code> klas\u00f6r\u00fc i\u00e7indeki yolunu belirtir, ancak <code>.md<\/code> uzant\u0131s\u0131 olmadan. \u00d6rne\u011fin, <code>getting-started\/introduction<\/code> ID'si, <code>docs\/getting-started\/introduction.md<\/code> dosyas\u0131na kar\u015f\u0131l\u0131k gelir. Bu ID ayn\u0131 zamanda URL yolu olarak da kullan\u0131lacakt\u0131r (\u00f6rn. <code>\/docs\/getting-started\/introduction<\/code>).<\/li>\n<li><code>label<\/code>: Sidebar'da g\u00f6r\u00fcnecek dok\u00fcman ba\u015fl\u0131\u011f\u0131.<\/li>\n<\/ul>\n<\/li>\n<li><strong><code>type: link<\/code><\/strong>: Harici bir web sitesine y\u00f6nlendiren bir ba\u011flant\u0131y\u0131 temsil eder.\n<ul>\n<li><code>label<\/code>: Sidebar'da g\u00f6r\u00fcnecek ba\u011flant\u0131 ba\u015fl\u0131\u011f\u0131.<\/li>\n<li><code>href<\/code>: Ba\u011flant\u0131n\u0131n y\u00f6nlendirece\u011fi URL.<\/li>\n<li><code>target<\/code>: (\u0130ste\u011fe ba\u011fl\u0131) Ba\u011flant\u0131n\u0131n yeni bir sekmede a\u00e7\u0131l\u0131p a\u00e7\u0131lmayaca\u011f\u0131n\u0131 belirler (\u00f6rne\u011fin, <code>_blank<\/code>).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>Dok\u00fcman \u0130\u00e7erik Dosyalar\u0131n\u0131 Olu\u015fturma<\/h3>\n<p>Yukar\u0131daki <code>sidebar.yaml<\/code> dosyas\u0131yla e\u015fle\u015fecek \u015fekilde, <code>docs\/<\/code> klas\u00f6r\u00fcn\u00fczde baz\u0131 Markdown dosyalar\u0131 olu\u015fturmal\u0131s\u0131n\u0131z. \u00d6rne\u011fin:<\/p>\n<h4><code>docs\/getting-started\/introduction.md<\/code><\/h4>\n<pre><code class=\"language-markdown\">\n# Ho\u015f Geldiniz!\n\nBu, projemizin ba\u015flang\u0131\u00e7 dok\u00fcmantasyonudur. Amac\u0131m\u0131z, sizi h\u0131zl\u0131ca al\u0131\u015ft\u0131rmak ve projenin temel prensiplerini anlaman\u0131z\u0131 sa\u011flamakt\u0131r.\n\n<strong>Projemiz Hakk\u0131nda<\/strong>\n\nBu proje, modern web uygulamalar\u0131 geli\u015ftirmek i\u00e7in tasarlanm\u0131\u015f bir ara\u00e7 setidir.\n\n<strong>\u0130lgili Ba\u011flant\u0131lar:<\/strong>\n- [Kurulum](\/docs\/getting-started\/installation)\n<\/pre>\n<p><\/code><\/p>\n<h4><code>docs\/getting-started\/installation.md<\/code><\/h4>\n<pre><code class=\"language-markdown\">\n# Kurulum Rehberi\n\nProjemizi bilgisayar\u0131n\u0131za kurmak i\u00e7in a\u015fa\u011f\u0131daki ad\u0131mlar\u0131 izleyin:\n\n1. Python 3.9 veya \u00fczeri y\u00fckl\u00fc oldu\u011fundan emin olun.\n2. Proje dizinine gidin ve ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00fckleyin:\n   <pre><code class=\"language-bash\">pip install -r requirements.txt<\/pre>\n<p><\/code><\/p>\n<pre><code class=\"language-bash\">3. Uygulamay\u0131 ba\u015flat\u0131n:<\/pre>\n<p><\/code>uvicorn main:app --reload<\/code><\/p>\n<p><strong>Gereksinimler<\/strong><\/p>\n<p>- Python 3.9+<br \/>\n- FastAPI<br \/>\n- Uvicorn<br \/>\n<\/code><\/p>\n<p>Bu <code>.md<\/code> dosyalar\u0131n\u0131n her biri, <code>sidebar.yaml<\/code>'deki <code>id<\/code> alanlar\u0131yla e\u015fle\u015fen yollarda yer almaktad\u0131r. Markdown dosyalar\u0131n\u0131z\u0131n ba\u015fl\u0131klar\u0131 (\u00f6rne\u011fin, <code># Ho\u015f Geldiniz!<\/code>) genellikle sayfa i\u00e7inde g\u00f6r\u00fcn\u00fcrken, sidebar'da g\u00f6sterilecek ba\u015fl\u0131klar <code>sidebar.yaml<\/code>'deki <code>label<\/code> alan\u0131ndan gelecektir. Bu ayr\u0131m, hem SEO dostu URL'ler olu\u015fturman\u0131za hem de kullan\u0131c\u0131 dostu men\u00fc ba\u015fl\u0131klar\u0131 kullanman\u0131za olanak tan\u0131r.<\/p>\n<p>Bu yap\u0131land\u0131rma, dok\u00fcmantasyonunuzun hem statik yap\u0131s\u0131n\u0131 hem de dinamik gezinme mant\u0131\u011f\u0131n\u0131 belirler. Bir sonraki ad\u0131mda, FastAPI uygulamam\u0131z\u0131n bu YAML dosyas\u0131n\u0131 nas\u0131l okuyaca\u011f\u0131n\u0131 ve i\u015fleyece\u011fini inceleyece\u011fiz. Bu ad\u0131m, statik yap\u0131land\u0131rmay\u0131 dinamik bir Python nesnesine d\u00f6n\u00fc\u015ft\u00fcrmenin ve web uygulamam\u0131z\u0131n anlayabilece\u011fi bir formata getirmenin temelini olu\u015fturur.<\/p>\n<aside class=\"expert-tip\">\n  Uzman \u0130pucu: B\u00fcy\u00fck projelerde <code>sidebar.yaml<\/code> dosyas\u0131n\u0131 k\u00fc\u00e7\u00fck par\u00e7alara ay\u0131rmak ve her birini bir kategorinin alt\u0131na yerle\u015ftirmek daha y\u00f6netilebilir olabilir (\u00f6rne\u011fin, <code>docs\/getting-started\/_sidebar.yaml<\/code>). Bu durumda, ana <code>sidebar.yaml<\/code> bu k\u00fc\u00e7\u00fck dosyalar\u0131 i\u00e7erecek \u015fekilde d\u00fczenlenebilir, b\u00f6ylece mod\u00fcler bir yap\u0131 elde edilir.<br \/>\n<\/aside>\n<h2>Ad\u0131m 3: FastAPI ile Yap\u0131land\u0131rmay\u0131 Okuma ve \u0130\u015fleme<\/h2>\n<p>\u015eimdi s\u0131ra, olu\u015fturdu\u011fumuz <code>sidebar.yaml<\/code> dosyas\u0131n\u0131 FastAPI uygulamam\u0131z i\u00e7inde kullan\u0131\u015fl\u0131 bir veri yap\u0131s\u0131na d\u00f6n\u00fc\u015ft\u00fcrmeye geldi. Bu ad\u0131mda Python'\u0131n <code>yaml<\/code> k\u00fct\u00fcphanesini kullanarak dosyay\u0131 okuyacak, ard\u0131ndan bu veriyi FastAPI'nin Jinja2 \u015fablonlar\u0131na aktarabilece\u011fi bir formata getirece\u011fiz. Ayr\u0131ca, Markdown dok\u00fcmanlar\u0131n\u0131 HTML'e \u00e7evirme i\u015flevini de bu b\u00f6l\u00fcmde ele alaca\u011f\u0131z.<\/p>\n<h3>YAML Yap\u0131land\u0131rmas\u0131n\u0131 Y\u00fckleme Fonksiyonu<\/h3>\n<p>\u00d6ncelikle, <code>main.py<\/code> dosyan\u0131za YAML dosyas\u0131n\u0131 okuyacak bir yard\u0131mc\u0131 fonksiyon ekleyelim:<\/p>\n<pre><code class=\"language-python\">\n# main.py\n\nimport yaml\nfrom pathlib import Path\nfrom markdown import markdown\nfrom fastapi import FastAPI, Request\nfrom fastapi.responses import HTMLResponse\nfrom fastapi.staticfiles import StaticFiles\nfrom fastapi.templating import Jinja2Templates\n\n# Projenin k\u00f6k dizini\nBASE_DIR = Path(__file__).resolve().parent\n\n# YAML dosyas\u0131n\u0131 y\u00fckleme fonksiyonu\ndef load_sidebar_config(config_path: Path):\n    with open(config_path, 'r', encoding='utf-8') as file:\n        return yaml.safe_load(file)\n\n# Markdown'\u0131 HTML'e \u00e7evirme fonksiyonu\ndef convert_markdown_to_html(md_path: Path) -> str:\n    with open(md_path, 'r', encoding='utf-8') as file:\n        md_content = file.read()\n    return markdown(md_content, extensions=['fenced_code', 'tables', 'attr_list'])\n\n# FastAPI uygulamas\u0131n\u0131 ba\u015flat\napp = FastAPI()\n\n# Statik dosyalar\u0131 ba\u011fla (CSS, JS vb.)\napp.mount(\"\/static\", StaticFiles(directory=BASE_DIR \/ \"static\"), name=\"static\")\n\n# Jinja2 \u015fablonlar\u0131n\u0131 y\u00fckle\ntemplates = Jinja2Templates(directory=BASE_DIR \/ \"templates\")\n\n# Sidebar yap\u0131land\u0131rmas\u0131n\u0131 y\u00fckle\ntry:\n    sidebar_config = load_sidebar_config(BASE_DIR \/ \"sidebar.yaml\")\nexcept FileNotFoundError:\n    print(\"Hata: sidebar.yaml dosyas\u0131 bulunamad\u0131. L\u00fctfen kontrol edin.\")\n    sidebar_config = [] # Bo\u015f liste ile devam et\nexcept Exception as e:\n    print(f\"Hata: sidebar.yaml y\u00fcklenirken bir sorun olu\u015ftu: {e}\")\n    sidebar_config = []\n<\/pre>\n<p><\/code><\/p>\n<p>Bu kod blo\u011funda:<\/p>\n<ul>\n<li><code>BASE_DIR<\/code>: Projenizin k\u00f6k dizinini belirler. Bu, t\u00fcm dosya yollar\u0131n\u0131n g\u00f6receli olarak y\u00f6netilmesini kolayla\u015ft\u0131r\u0131r.<\/li>\n<li><code>load_sidebar_config<\/code>: Verilen yoldaki YAML dosyas\u0131n\u0131 okur ve Python'\u0131n s\u00f6zl\u00fck\/liste yap\u0131s\u0131na d\u00f6n\u00fc\u015ft\u00fcr\u00fcr. Hata y\u00f6netimi de eklenmi\u015ftir.<\/li>\n<li><code>convert_markdown_to_html<\/code>: Belirtilen yoldaki Markdown dosyas\u0131n\u0131 okur ve <code>markdown<\/code> k\u00fct\u00fcphanesi kullanarak HTML'e d\u00f6n\u00fc\u015ft\u00fcr\u00fcr. <code>extensions<\/code> parametresi, daha zengin Markdown \u00f6zelliklerini (kod bloklar\u0131, tablolar vb.) desteklemek i\u00e7in \u00f6nemlidir.<\/li>\n<li><code>app = FastAPI()<\/code>: Uygulamam\u0131z\u0131 ba\u015flat\u0131r.<\/li>\n<li><code>app.mount(\"\/static\", ...)<\/code>: <code>static\/<\/code> klas\u00f6r\u00fcm\u00fczdeki CSS ve JS gibi dosyalar\u0131 <code>\/static<\/code> URL yolu \u00fczerinden eri\u015filebilir k\u0131lar.<\/li>\n<li><code>templates = Jinja2Templates(...)<\/code>: Jinja2 \u015fablon motorumuzu <code>templates\/<\/code> klas\u00f6r\u00fcm\u00fcz\u00fc i\u015faret ederek ba\u015flat\u0131r.<\/li>\n<li><code>sidebar_config = load_sidebar_config(...)<\/code>: Uygulama ba\u015flat\u0131l\u0131rken <code>sidebar.yaml<\/code> dosyas\u0131n\u0131 y\u00fckler ve <code>sidebar_config<\/code> de\u011fi\u015fkeninde tutar\u0131z. Bu sayede her istekte dosyay\u0131 okumak zorunda kalmay\u0131z.<\/li>\n<\/ul>\n<h3>Dok\u00fcman Sayfalar\u0131 i\u00e7in FastAPI Rotas\u0131<\/h3>\n<p>\u015eimdi, <code>\/docs\/<\/code> prefix'i alt\u0131ndaki t\u00fcm dok\u00fcman sayfalar\u0131n\u0131 dinamik olarak i\u015fleyecek bir FastAPI rotas\u0131 tan\u0131mlayal\u0131m. Bu rota, URL'deki dok\u00fcman ID'sini alacak, ilgili Markdown dosyas\u0131n\u0131 bulacak, onu HTML'e \u00e7evirecek ve Jinja2 \u015fablonuna g\u00f6nderecektir.<\/p>\n<pre><code class=\"language-python\">\n# main.py dosyas\u0131na ekleyin\n\n@app.get(\"\/docs\/{doc_id:path}\", response_class=HTMLResponse)\nasync def read_doc(request: Request, doc_id: str):\n    \"\"\"\n    Dinamik olarak dok\u00fcman sayfalar\u0131n\u0131 y\u00fckler ve render eder.\n    doc_id: URL'deki dok\u00fcman yolu (\u00f6rn. getting-started\/introduction)\n    \"\"\"\n    doc_path = BASE_DIR \/ \"docs\" \/ f\"{doc_id}.md\"\n\n    if not doc_path.is_file():\n        # E\u011fer dosya yoksa 404 hatas\u0131 d\u00f6nd\u00fcr\n        return templates.TemplateResponse(\n            \"404.html\",\n            {\"request\": request, \"sidebar_config\": sidebar_config, \"title\": \"Sayfa Bulunamad\u0131\"},\n            status_code=404\n        )\n\n    # Markdown i\u00e7eri\u011fini HTML'e \u00e7evir\n    doc_content_html = convert_markdown_to_html(doc_path)\n\n    # Sayfa ba\u015fl\u0131\u011f\u0131n\u0131 Markdown dosyas\u0131n\u0131n ilk H1 ba\u015fl\u0131\u011f\u0131ndan veya doc_id'den al\n    # Daha sofistike bir ba\u015fl\u0131k \u00e7ekme mekanizmas\u0131 kurulabilir.\n    # \u015eimdilik, sadece doc_id'yi kullanabiliriz veya Markdown i\u00e7eri\u011finden ilk H1'i parse edebiliriz.\n    first_h1_match = next((line for line in doc_content_html.split('\\n') if line.strip().startswith('<h1>')), None)\n    page_title = doc_id.replace('-', ' ').replace('\/', ' ').title() # Varsay\u0131lan ba\u015fl\u0131k\n    if first_h1_match:\n        # <h1> ve <\/h1> etiketlerini temizle\n        page_title = first_h1_match.replace(\"<h1>\", \"\").replace(\"<\/h1>\", \"\").strip()\n\n\n    # Jinja2 \u015fablonunu render et\n    return templates.TemplateResponse(\n        \"doc_page.html\",\n        {\n            \"request\": request,\n            \"sidebar_config\": sidebar_config,\n            \"doc_content\": doc_content_html,\n            \"current_doc_id\": doc_id, # Aktif sayfay\u0131 i\u015faretlemek i\u00e7in\n            \"title\": page_title\n        }\n    )\n\n@app.get(\"\/\", response_class=HTMLResponse)\nasync def read_root(request: Request):\n    \"\"\"\n    Ana sayfa y\u00f6nlendirmesi veya varsay\u0131lan bir ba\u015flang\u0131\u00e7 sayfas\u0131.\n    \"\"\"\n    # \u0130ste\u011fe ba\u011fl\u0131 olarak, ana sayfadan direkt ilk dok\u00fcmana y\u00f6nlendirebilirsiniz.\n    if sidebar_config and sidebar_config[0].get('type') == 'category' and sidebar_config[0].get('items'):\n        first_doc_id = sidebar_config[0]['items'][0]['id']\n        return templates.TemplateResponse(\n            \"doc_page.html\",\n            {\n                \"request\": request,\n                \"sidebar_config\": sidebar_config,\n                \"doc_content\": convert_markdown_to_html(BASE_DIR \/ \"docs\" \/ f\"{first_doc_id}.md\"),\n                \"current_doc_id\": first_doc_id,\n                \"title\": sidebar_config[0]['items'][0]['label']\n            }\n        )\n    return templates.TemplateResponse(\n        \"home.html\", # E\u011fer home.html yoksa, doc_page.html'i kullan\u0131p bo\u015f i\u00e7erik ge\u00e7ebilirsiniz\n        {\"request\": request, \"sidebar_config\": sidebar_config, \"title\": \"Ana Sayfa\", \"doc_content\": \"<h1>Ho\u015f Geldiniz!<\/h1><p>L\u00fctfen soldaki men\u00fcden bir dok\u00fcman se\u00e7in.<\/p>\"}\n    )\n<\/pre>\n<p><\/code><\/p>\n<p>Bu rotada yap\u0131lanlar:<\/p>\n<ul>\n<li><code>@app.get(\"\/docs\/{doc_id:path}\", ...)<\/code>: <code>\/docs\/<\/code> ile ba\u015flayan ve sonras\u0131nda herhangi bir yola sahip olan t\u00fcm istekleri yakalar. <code>{doc_id:path}<\/code> k\u0131sm\u0131, <code>\/<\/code> karakterlerini de i\u00e7eren bir yolu <code>doc_id<\/code> de\u011fi\u015fkenine atamam\u0131z\u0131 sa\u011flar.<\/li>\n<li><code>doc_path = BASE_DIR \/ \"docs\" \/ f\"{doc_id}.md\"<\/code>: Gelen <code>doc_id<\/code> ile <code>docs\/<\/code> klas\u00f6r\u00fcndeki ilgili Markdown dosyas\u0131n\u0131n tam yolunu olu\u015fturur.<\/li>\n<li><code>if not doc_path.is_file()<\/code>: Dosyan\u0131n ger\u00e7ekten var olup olmad\u0131\u011f\u0131n\u0131 kontrol eder. Yoksa, bir 404 (Sayfa Bulunamad\u0131) \u015fablonu d\u00f6nd\u00fcr\u00fcl\u00fcr.<\/li>\n<li><code>doc_content_html = convert_markdown_to_html(doc_path)<\/code>: Markdown dosyas\u0131n\u0131 HTML'e \u00e7evirir.<\/li>\n<li><code>page_title = ...<\/code>: Sayfa ba\u015fl\u0131\u011f\u0131n\u0131, URL'den veya Markdown i\u00e7eri\u011findeki ilk H1 etiketinden dinamik olarak al\u0131r. Bu, taray\u0131c\u0131 sekmesinde veya sayfa i\u00e7inde do\u011fru ba\u015fl\u0131\u011f\u0131n g\u00f6r\u00fcnt\u00fclenmesi i\u00e7in \u00f6nemlidir.<\/li>\n<li><code>return templates.TemplateResponse(...)<\/code>: <code>doc_page.html<\/code> \u015fablonunu render ederken, <code>request<\/code> objesini, <code>sidebar_config<\/code> (men\u00fc i\u00e7in), <code>doc_content<\/code> (ana i\u00e7erik i\u00e7in), <code>current_doc_id<\/code> (aktif men\u00fc \u00f6\u011fesini i\u015faretlemek i\u00e7in) ve <code>title<\/code> de\u011fi\u015fkenlerini \u015fablona g\u00f6nderir.<\/li>\n<li><code>@app.get(\"\/\")<\/code>: Ana sayfa iste\u011fini kar\u015f\u0131lar. Varsay\u0131lan olarak ilk dok\u00fcman\u0131 y\u00fcklemeyi veya basit bir kar\u015f\u0131lama sayfas\u0131 g\u00f6stermeyi se\u00e7ebilirsiniz.<\/li>\n<\/ul>\n<p>Bu ad\u0131mlarla, FastAPI uygulamam\u0131z art\u0131k YAML yap\u0131land\u0131rmas\u0131n\u0131 okuyabiliyor ve dok\u00fcman i\u00e7eri\u011fini i\u015fleyip HTML'e \u00e7evirebiliyor. S\u0131rada, bu veriyi kullanarak dinamik sidebar'\u0131m\u0131z\u0131 HTML \u015fablonlar\u0131nda nas\u0131l olu\u015fturaca\u011f\u0131m\u0131z var.<\/p>\n<h2>Ad\u0131m 4: Jinja2 \u015eablonlar\u0131 ile Sidebar'\u0131 Olu\u015fturma<\/h2>\n<p>\u015eimdiye kadar, FastAPI uygulamam\u0131z <code>sidebar.yaml<\/code> dosyam\u0131z\u0131 okuyabiliyor ve Markdown i\u00e7eri\u011fini HTML'e \u00e7evirebiliyor. Ancak bu veriyi bir web aray\u00fcz\u00fcne ta\u015f\u0131mam\u0131z gerekiyor. \u0130\u015fte bu noktada Jinja2 \u015fablonlar\u0131 devreye giriyor. <code>templates\/<\/code> klas\u00f6r\u00fcm\u00fczde <code>base.html<\/code> ve <code>doc_page.html<\/code> olmak \u00fczere iki ana \u015fablon olu\u015fturaca\u011f\u0131z. Bu \u015fablonlar, uygulaman\u0131n genel yap\u0131s\u0131n\u0131 ve sidebar'\u0131n render edilme mant\u0131\u011f\u0131n\u0131 i\u00e7erecek.<\/p>\n<h3><code>templates\/base.html<\/code> (Temel Sayfa Yap\u0131s\u0131)<\/h3>\n<p>Bu \u015fablon, HTML sayfam\u0131z\u0131n temel iskeletini, <code><head><\/code> etiketini, genel CSS ba\u011flant\u0131lar\u0131n\u0131 ve ana layout elementlerini (header, footer, ana i\u00e7erik alan\u0131 ve sidebar'\u0131n yer tutucusu) tan\u0131mlar. Di\u011fer \u015fablonlar bu dosyay\u0131 geni\u015fleterek kendi i\u00e7eriklerini yerle\u015ftireceklerdir.<\/p>\n<pre><code class=\"language-html\">\n<!DOCTYPE html>\n<html lang=\"tr\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>{{ title }} | Proje Dok\u00fcmantasyon<\/title>\n    <link rel=\"stylesheet\" href=\"{{ url_for('static', path='\/css\/style.css') }}\">\n    <!-- SEO Meta A\u00e7\u0131klamas\u0131 -->\n    <meta name=\"description\" content=\"FastAPI ile olu\u015fturulmu\u015f Docusaurus benzeri dinamik dok\u00fcmantasyon sitesi. Projenizin t\u00fcm \u00f6zelliklerini ke\u015ffedin.\">\n    <meta name=\"keywords\" content=\"FastAPI, Docusaurus, Sidebar, Dok\u00fcmantasyon, Python, Web Sitesi, Jinja2, Dinamik Navigasyon\">\n<\/head>\n<body>\n    <header class=\"navbar\">\n        <div class=\"container\">\n            <a href=\"\/\" class=\"navbar-brand\">Proje Docs<\/a>\n            <!-- Arama \u00e7ubu\u011fu veya di\u011fer navigasyon \u00f6\u011feleri buraya gelebilir -->\n        <\/div>\n    <\/header>\n\n    <div class=\"wrapper\">\n        <aside class=\"sidebar\">\n            <!-- Sidebar i\u00e7eri\u011fi buraya yerle\u015ftirilecek -->\n            <ul class=\"sidebar-nav\">\n                {% for item in sidebar_config %}\n                    {% if item.type == 'category' %}\n                        <li class=\"sidebar-category {% if not item.collapsed %}open{% endif %}\">\n                            <div class=\"category-header\">\n                                <span>{{ item.label }}<\/span>\n                                <span class=\"toggle-icon\"><\/span>\n                            <\/div>\n                            <ul class=\"category-items {% if item.collapsed %}collapsed{% endif %}\">\n                                {% for sub_item in item.items %}\n                                    {% if sub_item.type == 'doc' %}\n                                        <li class=\"sidebar-item {% if current_doc_id == sub_item.id %}active{% endif %}\">\n                                            <a href=\"{{ url_for('read_doc', doc_id=sub_item.id) }}\">{{ sub_item.label }}<\/a>\n                                        <\/li>\n                                    {% elif sub_item.type == 'link' %}\n                                        <li class=\"sidebar-item\">\n                                            <a href=\"{{ sub_item.href }}\" {% if sub_item.target %}target=\"{{ sub_item.target }}\"{% endif %}>{{ sub_item.label }}<\/a>\n                                        <\/li>\n                                    {% endif %}\n                                {% endfor %}\n                            <\/ul>\n                        <\/li>\n                    {% elif item.type == 'doc' %}\n                         <li class=\"sidebar-item {% if current_doc_id == item.id %}active{% endif %}\">\n                            <a href=\"{{ url_for('read_doc', doc_id=item.id) }}\">{{ item.label }}<\/a>\n                        <\/li>\n                    {% elif item.type == 'link' %}\n                        <li class=\"sidebar-item\">\n                            <a href=\"{{ item.href }}\" {% if item.target %}target=\"{{ item.target }}\"{% endif %}>{{ item.label }}<\/a>\n                        <\/li>\n                    {% endif %}\n                {% endfor %}\n            <\/ul>\n        <\/aside>\n\n        <main class=\"content\">\n            {% block content %}{% endblock %} <!-- Buraya i\u00e7erik yerle\u015ftirilecek -->\n        <\/main>\n    <\/div>\n\n    <footer class=\"footer\">\n        <div class=\"container\">\n            <p>&copy; 2023 Proje Dok\u00fcmantasyon. T\u00fcm Haklar\u0131 Sakl\u0131d\u0131r.<\/p>\n        <\/div>\n    <\/footer>\n\n    <script src=\"{{ url_for('static', path='\/js\/main.js') }}\"><\/script>\n<\/body>\n<\/html>\n<\/pre>\n<p><\/code><\/p>\n<p>Yukar\u0131daki <code>base.html<\/code> \u015fablonunda dikkat etmemiz gerekenler:<\/p>\n<ul>\n<li><code>{{ title }}<\/code>: FastAPI'den gelen sayfa ba\u015fl\u0131\u011f\u0131 buraya yerle\u015ftirilir.<\/li>\n<li><code>url_for(&#039;static&#039;, path=&#039;\/css\/style.css&#039;)<\/code>: FastAPI'nin <code>StaticFiles<\/code> mount'u \u00fczerinden CSS dosyas\u0131na dinamik olarak yol olu\u015fturur.<\/li>\n<li><code><meta name=\"description\"><\/code>, <code><meta name=\"keywords\"><\/code>: SEO i\u00e7in \u00f6nemli meta etiketleridir.<\/li>\n<li><code><br \/>\n<aside class=\"sidebar\"><\/code>: Sidebar men\u00fcm\u00fcz\u00fc bar\u0131nd\u0131ran ana eleman.<\/li>\n<li><code>{% for item in sidebar_config %}<\/code>: FastAPI'den gelen <code>sidebar_config<\/code> listesi \u00fczerinde d\u00f6ng\u00fc yapar\u0131z. Bu, her bir kategori, dok\u00fcman veya harici ba\u011flant\u0131 i\u00e7in HTML olu\u015fturmam\u0131z\u0131 sa\u011flar.<\/li>\n<li><code>{% if item.type == &#039;category&#039; %}<\/code>: E\u011fer \u00f6\u011fe bir kategoriyse, geni\u015fletilebilir bir yap\u0131 olu\u015ftururuz. \u0130\u00e7 i\u00e7e d\u00f6ng\u00fc ile kategori i\u00e7indeki alt \u00f6\u011feleri (dok\u00fcmanlar veya ba\u011flant\u0131lar) i\u015fleriz. <code>collapsed<\/code> ve <code>collapsible<\/code> bayraklar\u0131 dinamik olarak CSS s\u0131n\u0131flar\u0131n\u0131 kontrol eder.<\/li>\n<li><code>{% if current_doc_id == sub_item.id %}<\/code>: Aktif olarak g\u00f6r\u00fcnt\u00fclenen dok\u00fcman sayfas\u0131n\u0131 sidebar'da i\u015faretlemek i\u00e7in kullan\u0131l\u0131r, b\u00f6ylece kullan\u0131c\u0131 nerede oldu\u011funu bilir.<\/li>\n<li><code>url_for(&#039;read_doc&#039;, doc_id=sub_item.id)<\/code>: FastAPI rotam\u0131za (<code>read_doc<\/code>) dinamik URL olu\u015fturur.<\/li>\n<li><code>{% block content %}{% endblock %}<\/code>: Buras\u0131, <code>base.html<\/code>'i geni\u015fleten di\u011fer \u015fablonlar\u0131n kendi i\u00e7eriklerini yerle\u015ftirece\u011fi ana aland\u0131r.<\/li>\n<\/ul>\n<h3><code>templates\/doc_page.html<\/code> (Dok\u00fcman Sayfas\u0131 \u015eablonu)<\/h3>\n<p>Bu \u015fablon, <code>base.html<\/code>'i geni\u015fleterek ana dok\u00fcman i\u00e7eri\u011fini (<code>doc_content<\/code>) <code>content<\/code> blo\u011funa yerle\u015ftirir.<\/p>\n<pre><code class=\"language-html\">\n{% extends \"base.html\" %}\n\n{% block content %}\n    <article class=\"doc-article\">\n        {{ doc_content | safe }} <!-- Markdown'dan \u00e7evrilen HTML i\u00e7eri\u011fi -->\n    <\/article>\n{% endblock %}\n<\/pre>\n<p><\/code><\/p>\n<p>Burada <code>{{ doc_content | safe }}<\/code> ifadesi \u00f6nemlidir. Jinja2 varsay\u0131lan olarak HTML i\u00e7eri\u011fini ka\u00e7\u0131\u015f karakterlerine d\u00f6n\u00fc\u015ft\u00fcr\u00fcr (g\u00fcvenlik i\u00e7in). Ancak Markdown'dan \u00e7evrilen i\u00e7eri\u011fimiz zaten g\u00fcvenli bir HTML oldu\u011fu i\u00e7in, <code>| safe<\/code> filtresini kullanarak Jinja2'ye bu i\u00e7eri\u011fi oldu\u011fu gibi render etmesini s\u00f6yleriz.<\/p>\n<h3><code>templates\/404.html<\/code> (Sayfa Bulunamad\u0131 \u015eablonu)<\/h3>\n<p>Olmayan bir dok\u00fcman sayfas\u0131na eri\u015fildi\u011finde g\u00f6sterilecek basit bir hata sayfas\u0131:<\/p>\n<pre><code class=\"language-html\">\n{% extends \"base.html\" %}\n\n{% block content %}\n    <div class=\"error-page\">\n        <h1>404 - Sayfa Bulunamad\u0131<\/h1>\n        <p>Arad\u0131\u011f\u0131n\u0131z dok\u00fcman sayfas\u0131 bulunamad\u0131. L\u00fctfen URL'yi kontrol edin veya sidebar'dan ba\u015fka bir sayfa se\u00e7in.<\/p>\n        <p><a href=\"\/\">Ana Sayfaya D\u00f6n<\/a><\/p>\n    <\/div>\n{% endblock %}\n<\/pre>\n<p><\/code><\/p>\n<h3><code>static\/css\/style.css<\/code> (Temel Stil Tan\u0131mlar\u0131)<\/h3>\n<p>Sidebar'\u0131m\u0131z\u0131n ve genel layout'umuzun d\u00fczg\u00fcn g\u00f6r\u00fcnmesi i\u00e7in biraz CSS ekleyelim. Bu CSS ayn\u0131 zamanda mobil uyumlulu\u011fu da g\u00f6z \u00f6n\u00fcnde bulunduracakt\u0131r.<\/p>\n<pre><code class=\"language-css\">\n\/* style.css *\/\n:root {\n    --primary-color: #007bff;\n    --secondary-color: #6c757d;\n    --bg-color: #f8f9fa;\n    --text-color: #343a40;\n    --sidebar-width: 280px;\n    --navbar-height: 60px;\n}\n\nbody {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif;\n    margin: 0;\n    padding: 0;\n    background-color: var(--bg-color);\n    color: var(--text-color);\n    line-height: 1.6;\n}\n\n.navbar {\n    background-color: var(--primary-color);\n    color: white;\n    padding: 0.8rem 1rem;\n    position: fixed;\n    width: 100%;\n    top: 0;\n    left: 0;\n    z-index: 1000;\n    box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n    height: var(--navbar-height);\n    display: flex;\n    align-items: center;\n}\n\n.navbar-brand {\n    color: white;\n    text-decoration: none;\n    font-size: 1.5rem;\n    font-weight: bold;\n    margin-left: 1rem;\n}\n\n.wrapper {\n    display: flex;\n    min-height: calc(100vh - var(--navbar-height)); \/* Topbar y\u00fcksekli\u011fini d\u00fc\u015f *\/\n    padding-top: var(--navbar-height); \/* Topbar kadar bo\u015fluk b\u0131rak *\/\n}\n\n.sidebar {\n    width: var(--sidebar-width);\n    background-color: #ffffff;\n    border-right: 1px solid #e0e0e0;\n    padding: 1.5rem 0;\n    box-shadow: 2px 0 5px rgba(0,0,0,0.05);\n    position: fixed;\n    height: calc(100% - var(--navbar-height));\n    overflow-y: auto;\n    top: var(--navbar-height);\n    left: 0;\n}\n\n.sidebar-nav {\n    list-style: none;\n    padding: 0;\n    margin: 0;\n}\n\n.sidebar-category {\n    margin-bottom: 0.5rem;\n}\n\n.category-header {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    padding: 0.75rem 1.5rem;\n    cursor: pointer;\n    font-weight: bold;\n    color: var(--primary-color);\n    background-color: #e9ecef;\n    border-bottom: 1px solid #dee2e6;\n}\n\n.category-header:hover {\n    background-color: #e2e6ea;\n}\n\n.toggle-icon {\n    width: 0;\n    height: 0;\n    border-left: 5px solid transparent;\n    border-right: 5px solid transparent;\n    border-top: 5px solid var(--primary-color);\n    transition: transform 0.2s ease-in-out;\n}\n\n.sidebar-category.open .toggle-icon {\n    transform: rotate(180deg);\n}\n\n.category-items {\n    list-style: none;\n    padding: 0;\n    margin: 0;\n    overflow: hidden; \/* Collapse animation *\/\n    transition: max-height 0.3s ease-out;\n}\n\n.category-items.collapsed {\n    max-height: 0;\n}\n\n.category-items:not(.collapsed) {\n    max-height: 500px; \/* B\u00fcy\u00fck bir de\u011fer verin *\/\n}\n\n\n.sidebar-item a {\n    display: block;\n    padding: 0.75rem 1.5rem 0.75rem 2rem; \/* Alt \u00f6\u011feleri biraz i\u00e7eriden ba\u015flat *\/\n    color: var(--text-color);\n    text-decoration: none;\n    transition: background-color 0.2s, color 0.2s;\n    font-size: 0.95rem;\n}\n\n.sidebar-item a:hover {\n    background-color: #f0f0f0;\n    color: var(--primary-color);\n}\n\n.sidebar-item.active a {\n    background-color: var(--primary-color);\n    color: white;\n    font-weight: bold;\n}\n\n.content {\n    margin-left: var(--sidebar-width);\n    flex-grow: 1;\n    padding: 2rem;\n    max-width: 900px;\n}\n\n.doc-article h1, .doc-article h2, .doc-article h3, .doc-article h4, .doc-article h5, .doc-article h6 {\n    color: var(--primary-color);\n    margin-top: 2rem;\n    margin-bottom: 1rem;\n}\n\n.doc-article p {\n    margin-bottom: 1rem;\n}\n\n.doc-article pre {\n    background-color: #272727;\n    color: #f8f8f2;\n    padding: 1rem;\n    border-radius: 5px;\n    overflow-x: auto;\n    font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;\n    margin-bottom: 1.5rem;\n}\n\n.doc-article code {\n    background-color: rgba(0,0,0,0.05);\n    padding: 0.2em 0.4em;\n    border-radius: 3px;\n    font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;\n    font-size: 0.9em;\n}\n\n.doc-article pre code {\n    background-color: transparent;\n    padding: 0;\n    border-radius: 0;\n}\n\n.doc-article table {\n    width: 100%;\n    border-collapse: collapse;\n    margin: 1rem 0;\n}\n\n.doc-article th, .doc-article td {\n    border: 1px solid #ddd;\n    padding: 8px;\n    text-align: left;\n}\n\n.doc-article th {\n    background-color: #f2f2f2;\n    font-weight: bold;\n}\n\n.footer {\n    background-color: var(--secondary-color);\n    color: white;\n    text-align: center;\n    padding: 1rem;\n    font-size: 0.9rem;\n    margin-top: auto; \/* Footer'\u0131 alta sabitlemek i\u00e7in *\/\n}\n\n.error-page {\n    text-align: center;\n    padding: 5rem 2rem;\n}\n\n.expert-tip {\n    background-color: #fff3cd; \/* Sar\u0131ms\u0131 arka plan *\/\n    border-left: 4px solid #ffc107; \/* Sar\u0131 kenarl\u0131k *\/\n    padding: 1rem 1.5rem;\n    margin: 1.5rem 0;\n    color: #664d03; \/* Koyu sar\u0131ms\u0131 metin *\/\n    border-radius: 4px;\n    font-style: italic;\n    box-shadow: 0 1px 3px rgba(0,0,0,0.1);\n}\n\n\/* Mobil Uyumlu Tasar\u0131m *\/\n@media (max-width: 992px) {\n    .sidebar {\n        width: 250px;\n    }\n    .content {\n        margin-left: 250px;\n        padding: 1rem;\n    }\n}\n\n@media (max-width: 768px) {\n    .wrapper {\n        flex-direction: column;\n        padding-top: calc(var(--navbar-height) + 1rem); \/* Topbar ve biraz daha bo\u015fluk *\/\n    }\n    .sidebar {\n        position: static; \/* Mobil'de sidebar'\u0131 statik yap *\/\n        width: 100%;\n        height: auto;\n        border-right: none;\n        border-bottom: 1px solid #e0e0e0;\n        box-shadow: 0 2px 5px rgba(0,0,0,0.05);\n        padding: 0; \/* \u0130\u00e7 dolguyu kald\u0131r *\/\n    }\n    .content {\n        margin-left: 0;\n        padding: 1.5rem;\n    }\n    .category-items {\n        max-height: 0; \/* Mobil'de varsay\u0131lan olarak daralt\u0131lm\u0131\u015f *\/\n    }\n    .sidebar-category.open .category-items {\n        max-height: 500px; \/* A\u00e7\u0131k oldu\u011funda geni\u015flet *\/\n    }\n    .category-header {\n        padding: 1rem;\n        font-size: 1.1rem;\n    }\n    .sidebar-item a {\n        padding: 0.75rem 1.5rem 0.75rem 1.5rem;\n    }\n    .navbar-brand {\n        font-size: 1.2rem;\n    }\n}\n<\/pre>\n<p><\/code><\/p>\n<h3><code>static\/js\/main.js<\/code> (Sidebar Etkile\u015fimleri)<\/h3>\n<p>Kategorilerin daralt\u0131l\u0131p geni\u015fletilmesi i\u00e7in basit bir JavaScript kodu ekleyelim:<\/p>\n<pre><code class=\"language-javascript\">\n\/\/ main.js\ndocument.addEventListener('DOMContentLoaded', function() {\n    const categoryHeaders = document.querySelectorAll('.category-header');\n\n    categoryHeaders.forEach(header => {\n        header.addEventListener('click', function() {\n            const category = this.closest('.sidebar-category');\n            const categoryItems = category.querySelector('.category-items');\n            \n            \/\/ Toggle 'open' class on the category\n            category.classList.toggle('open');\n            \n            \/\/ Toggle 'collapsed' class on category items for CSS transition\n            categoryItems.classList.toggle('collapsed');\n        });\n    });\n\n    \/\/ Sayfa y\u00fcklendi\u011finde mevcut aktif kategoriyi a\u00e7\n    const activeItem = document.querySelector('.sidebar-item.active');\n    if (activeItem) {\n        let parentCategoryItems = activeItem.closest('.category-items');\n        while (parentCategoryItems) {\n            parentCategoryItems.classList.remove('collapsed');\n            let parentCategory = parentCategoryItems.closest('.sidebar-category');\n            if (parentCategory) {\n                parentCategory.classList.add('open');\n            }\n            parentCategoryItems = parentCategoryItems.parentElement.closest('.category-items');\n        }\n    }\n});\n<\/pre>\n<p><\/code><\/p>\n<p>Bu JS kodu, kategori ba\u015fl\u0131klar\u0131na t\u0131klan\u0131ld\u0131\u011f\u0131nda ilgili <code>category-items<\/code> listesini geni\u015fletir veya daralt\u0131r. Ayr\u0131ca, sayfa y\u00fcklendi\u011finde aktif olan dok\u00fcman \u00f6\u011fesinin \u00fcst kategorilerini otomatik olarak a\u00e7ar, b\u00f6ylece kullan\u0131c\u0131 nerede oldu\u011funu kolayca g\u00f6rebilir. Bu basit JavaScript, Docusaurus benzeri kullan\u0131c\u0131 deneyimini sa\u011flamak i\u00e7in yeterli olacakt\u0131r.<\/p>\n<p>Bu \u015fablonlar ve stil dosyalar\u0131yla, FastAPI uygulamam\u0131z art\u0131k dinamik olarak olu\u015fturulan bir sidebar'a sahip, okunabilir ve modern g\u00f6r\u00fcn\u00fcml\u00fc bir dok\u00fcmantasyon sitesi sunabilir. Bir sonraki ve son ad\u0131mda, bu par\u00e7alar\u0131 bir araya getirip FastAPI uygulamas\u0131n\u0131 nas\u0131l ba\u015flataca\u011f\u0131m\u0131za ve \u00e7al\u0131\u015ft\u0131raca\u011f\u0131m\u0131za bakaca\u011f\u0131z.<\/p>\n<h2>Ad\u0131m 5: FastAPI Uygulamas\u0131n\u0131 Entegre Etme ve \u00c7al\u0131\u015ft\u0131rma<\/h2>\n<p>\u015eimdiye kadar t\u00fcm gerekli bile\u015fenleri haz\u0131rlad\u0131k: Proje yap\u0131s\u0131n\u0131 kurduk, <code>sidebar.yaml<\/code> ile navigasyonu tan\u0131mlad\u0131k, Markdown dok\u00fcmanlar\u0131m\u0131z\u0131 olu\u015fturduk ve Jinja2 \u015fablonlar\u0131m\u0131zla HTML \u00e7\u0131kt\u0131s\u0131 i\u00e7in zemini haz\u0131rlad\u0131k. Art\u0131k <code>main.py<\/code> dosyam\u0131zda t\u00fcm bu par\u00e7alar\u0131 bir araya getirerek FastAPI uygulamam\u0131z\u0131 \u00e7al\u0131\u015f\u0131r hale getirebiliriz.<\/p>\n<p>A\u015fa\u011f\u0131da, <code>main.py<\/code> dosyas\u0131n\u0131n son hali bulunmaktad\u0131r. \u00d6nceki ad\u0131mlarda olu\u015fturdu\u011fumuz fonksiyonlar\u0131 ve rotalar\u0131 i\u00e7erir.<\/p>\n<pre><code class=\"language-python\">\n# main.py\n\nimport yaml\nfrom pathlib import Path\nfrom markdown import markdown\nfrom fastapi import FastAPI, Request\nfrom fastapi.responses import HTMLResponse\nfrom fastapi.staticfiles import StaticFiles\nfrom fastapi.templating import Jinja2Templates\n\n# Projenin k\u00f6k dizini\nBASE_DIR = Path(__file__).resolve().parent\n\n# YAML dosyas\u0131n\u0131 y\u00fckleme fonksiyonu\ndef load_sidebar_config(config_path: Path):\n    try:\n        with open(config_path, 'r', encoding='utf-8') as file:\n            return yaml.safe_load(file)\n    except FileNotFoundError:\n        print(f\"Hata: Yap\u0131land\u0131rma dosyas\u0131 bulunamad\u0131: {config_path}\")\n        return []\n    except yaml.YAMLError as e:\n        print(f\"Hata: YAML ayr\u0131\u015ft\u0131rma hatas\u0131: {e}\")\n        return []\n    except Exception as e:\n        print(f\"Hata: load_sidebar_config s\u0131ras\u0131nda beklenmeyen hata: {e}\")\n        return []\n\n# Markdown'\u0131 HTML'e \u00e7evirme fonksiyonu\ndef convert_markdown_to_html(md_path: Path) -> str:\n    try:\n        with open(md_path, 'r', encoding='utf-8') as file:\n            md_content = file.read()\n        # Kod bloklar\u0131, tablolar ve \u00f6zellik listeleri i\u00e7in uzant\u0131lar\u0131 ekle\n        return markdown(md_content, extensions=['fenced_code', 'tables', 'attr_list', 'nl2br'])\n    except FileNotFoundError:\n        return \"Dok\u00fcman bulunamad\u0131.\"\n    except Exception as e:\n        return f\"Markdown d\u00f6n\u00fc\u015ft\u00fcrme hatas\u0131: {e}\"\n\n# FastAPI uygulamas\u0131n\u0131 ba\u015flat\napp = FastAPI(\n    title=\"Proje Dok\u00fcmantasyon Sitesi\",\n    description=\"FastAPI ile dinamik olarak olu\u015fturulmu\u015f dok\u00fcmantasyon sayfas\u0131.\",\n    version=\"1.0.0\",\n)\n\n# Statik dosyalar\u0131 ba\u011fla (CSS, JS vb.)\n# Bu, taray\u0131c\u0131n\u0131n \/static\/css\/style.css gibi yollardan dosyalara eri\u015fmesini sa\u011flar\napp.mount(\"\/static\", StaticFiles(directory=BASE_DIR \/ \"static\"), name=\"static\")\n\n# Jinja2 \u015fablonlar\u0131n\u0131 y\u00fckle\ntemplates = Jinja2Templates(directory=BASE_DIR \/ \"templates\")\n\n# Sidebar yap\u0131land\u0131rmas\u0131n\u0131 uygulama ba\u015flad\u0131\u011f\u0131nda bir kez y\u00fckle\nsidebar_config = load_sidebar_config(BASE_DIR \/ \"sidebar.yaml\")\n\n# --- Rotlar ---\n\n@app.get(\"\/docs\/{doc_id:path}\", response_class=HTMLResponse)\nasync def read_doc(request: Request, doc_id: str):\n    \"\"\"\n    Dinamik olarak dok\u00fcman sayfalar\u0131n\u0131 y\u00fckler ve render eder.\n    doc_id: URL'deki dok\u00fcman yolu (\u00f6rn. getting-started\/introduction)\n    \"\"\"\n    doc_path = BASE_DIR \/ \"docs\" \/ f\"{doc_id}.md\"\n\n    if not doc_path.is_file():\n        # E\u011fer dosya yoksa 404 hatas\u0131 d\u00f6nd\u00fcr\n        return templates.TemplateResponse(\n            \"404.html\",\n            {\"request\": request, \"sidebar_config\": sidebar_config, \"title\": \"Sayfa Bulunamad\u0131\"},\n            status_code=404\n        )\n\n    # Markdown i\u00e7eri\u011fini HTML'e \u00e7evir\n    doc_content_html = convert_markdown_to_html(doc_path)\n\n    # Sayfa ba\u015fl\u0131\u011f\u0131n\u0131 Markdown dosyas\u0131n\u0131n ilk H1 ba\u015fl\u0131\u011f\u0131ndan veya doc_id'den al\n    # Burada daha sa\u011flam bir ba\u015fl\u0131k \u00e7\u0131karma mekanizmas\u0131 kullan\u0131labilir.\n    # \u00d6rne\u011fin, Markdown metnini parse edip ilk H1'i bulmak gibi.\n    # Basitlik ad\u0131na, \u015fimdilik doc_id'den t\u00fcretilmi\u015f bir ba\u015fl\u0131k veya do\u011frudan Markdown i\u00e7eri\u011finden ilk H1.\n    page_title_candidate = doc_id.replace('-', ' ').replace('\/', ' ').title()\n    \n    # Markdown i\u00e7eri\u011finden ilk H1'i \u00e7ekmek i\u00e7in daha dikkatli bir yakla\u015f\u0131m\n    # Markdown \u00e7\u0131kt\u0131s\u0131 HTML oldu\u011fu i\u00e7in, HTML i\u00e7indeki <h1> etiketini arayal\u0131m.\n    import re\n    h1_match = re.search(r'<h1>(.*?)<\\\/h1>', doc_content_html, re.IGNORECASE)\n    if h1_match:\n        page_title = h1_match.group(1).strip()\n    else:\n        page_title = page_title_candidate\n\n    # Jinja2 \u015fablonunu render et\n    return templates.TemplateResponse(\n        \"doc_page.html\",\n        {\n            \"request\": request,\n            \"sidebar_config\": sidebar_config,\n            \"doc_content\": doc_content_html,\n            \"current_doc_id\": doc_id, # Aktif sayfay\u0131 i\u015faretlemek i\u00e7in\n            \"title\": page_title\n        }\n    )\n\n@app.get(\"\/\", response_class=HTMLResponse)\nasync def read_root(request: Request):\n    \"\"\"\n    Ana sayfa y\u00f6nlendirmesi veya varsay\u0131lan bir ba\u015flang\u0131\u00e7 sayfas\u0131.\n    \"\"\"\n    # Ana sayfay\u0131 direkt ilk dok\u00fcmana y\u00f6nlendirelim veya \u00f6zel bir ana sayfa g\u00f6sterebiliriz.\n    if sidebar_config and isinstance(sidebar_config, list) and sidebar_config:\n        first_doc_item = None\n        # Sidebar'daki ilk 'doc' tipindeki \u00f6\u011feyi bul\n        for item in sidebar_config:\n            if item.get('type') == 'doc':\n                first_doc_item = item\n                break\n            elif item.get('type') == 'category' and item.get('items'):\n                for sub_item in item['items']:\n                    if sub_item.get('type') == 'doc':\n                        first_doc_item = sub_item\n                        break\n            if first_doc_item:\n                break\n        \n        if first_doc_item:\n            first_doc_id = first_doc_item['id']\n            # \u0130lk dok\u00fcman\u0131n i\u00e7eri\u011fini y\u00fckleyip ana sayfa olarak g\u00f6ster\n            return templates.TemplateResponse(\n                \"doc_page.html\",\n                {\n                    \"request\": request,\n                    \"sidebar_config\": sidebar_config,\n                    \"doc_content\": convert_markdown_to_html(BASE_DIR \/ \"docs\" \/ f\"{first_doc_id}.md\"),\n                    \"current_doc_id\": first_doc_id,\n                    \"title\": first_doc_item.get('label', first_doc_id.replace('-', ' ').replace('\/', ' ').title())\n                }\n            )\n    \n    # E\u011fer sidebar bo\u015fsa veya ilk dok\u00fcman bulunamazsa, genel bir kar\u015f\u0131lama sayfas\u0131 g\u00f6ster\n    return templates.TemplateResponse(\n        \"home.html\", # Bu \u015fablonu olu\u015fturman\u0131z gerekebilir veya doc_page.html kullanabilirsiniz\n        {\n            \"request\": request,\n            \"sidebar_config\": sidebar_config,\n            \"title\": \"Ho\u015f Geldiniz\",\n            \"doc_content\": \"<h1>Ho\u015f Geldiniz!<\/h1><p>Soldaki men\u00fcden bir dok\u00fcman se\u00e7erek ba\u015flay\u0131n.<\/p>\"\n        }\n    )\n<\/pre>\n<p><\/code><\/p>\n<h3>Uygulamay\u0131 \u00c7al\u0131\u015ft\u0131rma<\/h3>\n<p>Projenizi olu\u015fturdunuz, k\u00fct\u00fcphanelerinizi kurdunuz ve t\u00fcm kodlar\u0131 yerle\u015ftirdiniz. \u015eimdi uygulamay\u0131 \u00e7al\u0131\u015ft\u0131rman\u0131n zaman\u0131 geldi. Terminalinizi a\u00e7\u0131n, projenizin ana dizinine (<code>fastapi-docs-site\/<\/code>) gidin ve a\u015fa\u011f\u0131daki komutu \u00e7al\u0131\u015ft\u0131r\u0131n:<\/p>\n<pre><code class=\"language-bash\">\nuvicorn main:app --reload\n<\/pre>\n<p><\/code><\/p>\n<p>Bu komut:<\/p>\n<ul>\n<li><code>uvicorn<\/code>: FastAPI uygulamalar\u0131n\u0131 \u00e7al\u0131\u015ft\u0131rmak i\u00e7in kullan\u0131lan ASGI sunucusudur.<\/li>\n<li><code>main:app<\/code>: <code>main.py<\/code> dosyas\u0131ndaki <code>app<\/code> isimli FastAPI uygulamas\u0131n\u0131 ifade eder.<\/li>\n<li><code>--reload<\/code>: Bu bayrak, kodunuzda her de\u011fi\u015fiklik yapt\u0131\u011f\u0131n\u0131zda uygulaman\u0131n otomatik olarak yeniden y\u00fcklenmesini sa\u011flar. Geli\u015ftirme s\u00fcrecinde \u00e7ok faydal\u0131d\u0131r.<\/li>\n<\/ul>\n<p>Uygulama ba\u015far\u0131yla ba\u015flat\u0131ld\u0131\u011f\u0131nda, terminalinizde \u015funa benzer bir \u00e7\u0131kt\u0131 g\u00f6receksiniz:<\/p>\n<pre><code class=\"language-plaintext\">\nINFO:     Will watch for changes in these directories: ['\/path\/to\/your\/fastapi-docs-site']\nINFO:     Uvicorn running on http:\/\/127.0.0.1:8000 (Press CTRL+C to quit)\nINFO:     Started reloader process [xxxxx]\nINFO:     Started server process [xxxxx]\nINFO:     Waiting for application startup.\nINFO:     Application startup complete.\n<\/pre>\n<p><\/code><\/p>\n<p>Art\u0131k taray\u0131c\u0131n\u0131z\u0131 a\u00e7\u0131p <code>http:\/\/127.0.0.1:8000<\/code> adresine giderek dinamik dok\u00fcmantasyon sitenizi g\u00f6rebilirsiniz. Sidebar'\u0131n\u0131z\u0131n <code>sidebar.yaml<\/code> dosyas\u0131nda tan\u0131mlad\u0131\u011f\u0131n\u0131z gibi g\u00f6r\u00fcnd\u00fc\u011f\u00fcn\u00fc, linklere t\u0131klad\u0131\u011f\u0131n\u0131zda Markdown dosyalar\u0131n\u0131z\u0131n HTML'e \u00e7evrilerek y\u00fcklendi\u011fini ve aktif sayfan\u0131n sidebar'da vurguland\u0131\u011f\u0131n\u0131 fark edeceksiniz. Mobil cihazlarda sidebar'\u0131n nas\u0131l davranaca\u011f\u0131n\u0131 g\u00f6rmek i\u00e7in taray\u0131c\u0131n\u0131z\u0131n geli\u015ftirici ara\u00e7lar\u0131n\u0131 kullanarak ekran boyutunu k\u00fc\u00e7\u00fcltebilirsiniz. CSS'deki <code>@media<\/code> sorgular\u0131 sayesinde, daha k\u00fc\u00e7\u00fck ekranlarda sidebar'\u0131n farkl\u0131 bir d\u00fczende (\u00f6rne\u011fin, \u00fcstte geni\u015fletilebilir men\u00fc olarak) g\u00f6r\u00fcnd\u00fc\u011f\u00fcn\u00fc g\u00f6receksiniz. Bu, kullan\u0131c\u0131 deneyimini her boyuttaki ekran i\u00e7in optimize etmenize yard\u0131mc\u0131 olur.<\/p>\n<aside class=\"expert-tip\">\n  Uzman \u0130pucu: Uygulaman\u0131z\u0131 canl\u0131ya al\u0131rken <code>--reload<\/code> bayra\u011f\u0131n\u0131 kullanmamal\u0131s\u0131n\u0131z. \u00dcretim ortamlar\u0131nda Gunicorn gibi bir WSGI sunucusunun arkas\u0131nda Uvicorn'u \u00e7al\u0131\u015ft\u0131rmak, daha stabil ve performansl\u0131 bir \u00e7\u00f6z\u00fcm sunar. \u00d6rne\u011fin: <code>gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app<\/code>.<br \/>\n<\/aside>\n<h2>\u0130leri Seviye Optimizasyonlar ve Geli\u015ftirmeler<\/h2>\n<p>Art\u0131k temel dinamik sidebar yap\u0131m\u0131z\u0131 kurdu\u011fumuza g\u00f6re, projemizi daha sa\u011flam, performansl\u0131 ve kullan\u0131c\u0131 dostu hale getirecek ileri seviye konulara de\u011finelim. Bu optimizasyonlar, b\u00fcy\u00fck \u00f6l\u00e7ekli dok\u00fcmantasyon siteleri veya \u00f6zel gereksinimleri olan projeler i\u00e7in kritik \u00f6neme sahiptir.<\/p>\n<h3>1. Dinamik \u0130\u00e7erik G\u00fcncellemeleri i\u00e7in Dosya Takibi<\/h3>\n<p>Mevcut kurulumumuzda, <code>sidebar.yaml<\/code> dosyas\u0131n\u0131 veya Markdown i\u00e7eri\u011fini de\u011fi\u015ftirdi\u011finizde, de\u011fi\u015fikliklerin web sitesinde g\u00f6r\u00fcnmesi i\u00e7in FastAPI uygulamas\u0131n\u0131 yeniden ba\u015flatman\u0131z gerekir (e\u011fer <code>uvicorn --reload<\/code> kullanm\u0131yorsan\u0131z). \u00dcretim ortam\u0131nda bu pratik de\u011fildir. <code>watchdog<\/code> gibi bir k\u00fct\u00fcphane kullanarak <code>docs\/<\/code> klas\u00f6r\u00fcndeki veya <code>sidebar.yaml<\/code> dosyas\u0131ndaki de\u011fi\u015fiklikleri dinleyebilir ve bir de\u011fi\u015fiklik alg\u0131land\u0131\u011f\u0131nda <code>sidebar_config<\/code>'i otomatik olarak yeniden y\u00fckleyebiliriz. Bu, uygulaman\u0131n \u00e7al\u0131\u015fmaya devam ederken i\u00e7eri\u011fin canl\u0131 olarak g\u00fcncellenmesini sa\u011flar.<\/p>\n<pre><code class=\"language-python\">\n# \u00d6rnek: main.py i\u00e7inde bir background task veya event listener olarak\nimport asyncio\nfrom watchdog.observers import Observer\nfrom watchdog.events import FileSystemEventHandler\n\nclass ConfigChangeHandler(FileSystemEventHandler):\n    def __init__(self, app_instance, config_path):\n        super().__init__()\n        self.app = app_instance\n        self.config_path = config_path\n\n    def on_modified(self, event):\n        if event.src_path == str(self.config_path):\n            print(f\"[{event.src_path}] g\u00fcncellendi, sidebar yap\u0131land\u0131rmas\u0131 yeniden y\u00fckleniyor...\")\n            # Bu i\u015flem senkron oldu\u011fu i\u00e7in dikkatli olun, b\u00fcy\u00fck dosyalarda bloklama yapabilir.\n            # Alternatif olarak, g\u00fcncellemeyi bir Queue'ye at\u0131p ba\u015fka bir process'te i\u015fleyebilirsiniz.\n            self.app.state.sidebar_config = load_sidebar_config(self.config_path) # FastAPI uygulamas\u0131 i\u00e7indeki state'i g\u00fcncelleyin\n\n# Uygulama ba\u015flang\u0131c\u0131nda observer'\u0131 ba\u015flatma (FastAPI lifecycle events ile)\n# @app.on_event(\"startup\")\n# async def startup_event():\n#     event_handler = ConfigChangeHandler(app, BASE_DIR \/ \"sidebar.yaml\")\n#     observer = Observer()\n#     observer.schedule(event_handler, path=str(BASE_DIR), recursive=True)\n#     observer.start()\n#     app.state.observer = observer # Kapan\u0131\u015fta durdurmak i\u00e7in sakla\n\n# @app.on_event(\"shutdown\")\n# def shutdown_event():\n#     if hasattr(app.state, 'observer'):\n#         app.state.observer.stop()\n#         app.state.observer.join()\n<\/pre>\n<p><\/code><\/p>\n<p>Bu yakla\u015f\u0131m, i\u00e7erik y\u00f6netimini daha dinamik hale getirir ve geli\u015ftirici deneyimini \u00f6nemli \u00f6l\u00e7\u00fcde iyile\u015ftirir.<\/p>\n<h3>2. Caching (\u00d6nbellekleme) Mekanizmalar\u0131<\/h3>\n<p>Her istekte Markdown dosyas\u0131n\u0131 okumak ve HTML'e \u00e7evirmek, \u00f6zellikle y\u00fcksek trafikli sitelerde performans sorunlar\u0131na yol a\u00e7abilir. Bu sorunu \u00e7\u00f6zmek i\u00e7in \u00f6nbellekleme kullanabiliriz:<\/p>\n<ul>\n<li><strong>Lru Cache:<\/strong> Python'\u0131n <code>functools.lru_cache<\/code> dekorat\u00f6r\u00fc, fonksiyon \u00e7a\u011fr\u0131lar\u0131n\u0131n sonu\u00e7lar\u0131n\u0131 \u00f6nbelle\u011fe almak i\u00e7in basit ama etkili bir yoldur. Markdown'dan HTML'e \u00e7eviren fonksiyona uygulayabiliriz.<\/li>\n<li><strong>Redis\/Memcached:<\/strong> Daha b\u00fcy\u00fck \u00f6l\u00e7ekli veya da\u011f\u0131t\u0131k sistemler i\u00e7in, Redis veya Memcached gibi harici \u00f6nbellekleme sistemleri kullan\u0131labilir. FastAPI i\u00e7inde bir <code>Cache<\/code> ba\u011f\u0131ml\u0131l\u0131\u011f\u0131 olu\u015fturarak, sayfa i\u00e7eriklerini veya hatta t\u00fcm render edilmi\u015f HTML par\u00e7alar\u0131n\u0131 \u00f6nbelle\u011fe alabilirsiniz.<\/li>\n<\/ul>\n<pre><code class=\"language-python\">\n# functools.lru_cache kullan\u0131m\u0131\nfrom functools import lru_cache\n\n@lru_cache(maxsize=128) # Son 128 farkl\u0131 dosyan\u0131n sonucunu \u00f6nbelle\u011fe al\ndef convert_markdown_to_html(md_path: Path) -> str:\n    # ... mevcut kod ...\n<\/pre>\n<p><\/code><\/p>\n<p>Bu basit ekleme, Markdown d\u00f6n\u00fc\u015ft\u00fcrme performans\u0131n\u0131 belirgin \u015fekilde art\u0131racakt\u0131r.<\/p>\n<h3>3. Arama Fonksiyonu Entegrasyonu<\/h3>\n<p>Dok\u00fcmantasyon sitelerinin vazge\u00e7ilmezi olan arama i\u015flevi, kullan\u0131c\u0131lar\u0131n bilgiye h\u0131zl\u0131ca ula\u015fmas\u0131n\u0131 sa\u011flar. FastAPI \u00fczerinde bir arama motoru entegre edebilirsiniz:<\/p>\n<ul>\n<li><strong>Basit Metin Aramas\u0131:<\/strong> T\u00fcm Markdown dosyalar\u0131n\u0131 tarayarak ve arama terimini i\u00e7eren dosyalar\u0131 listeleyerek basit bir arama yapabilirsiniz. Bu, k\u00fc\u00e7\u00fck dok\u00fcmantasyon siteleri i\u00e7in yeterli olabilir.<\/li>\n<li><strong>Tam Metin Arama Motorlar\u0131:<\/strong> Elasticsearch, Algolia veya Whoosh (Python tabanl\u0131) gibi daha geli\u015fmi\u015f tam metin arama motorlar\u0131n\u0131 entegre etmek, daha h\u0131zl\u0131, daha alakal\u0131 ve esnek arama sonu\u00e7lar\u0131 sunar. \u0130\u00e7erik g\u00fcncellendi\u011finde arama indeksini de g\u00fcncellemek \u00f6nemlidir.<\/li>\n<\/ul>\n<pre><code class=\"language-python\">\n# Arama endpoint'i \u00f6rne\u011fi\n# @app.get(\"\/search\", response_class=HTMLResponse)\n# async def search_docs(request: Request, query: str):\n#     results = []\n#     # Ger\u00e7ek d\u00fcnyada burada bir arama motoru (Elasticsearch, Whoosh vb.) entegrasyonu olur.\n#     # Basit bir \u00f6rnek olarak, sadece dosya isimlerinde arama yapal\u0131m.\n#     for item in sidebar_config:\n#         if item.get('type') == 'doc' and query.lower() in item['label'].lower():\n#             results.append(item)\n#         elif item.get('type') == 'category':\n#             for sub_item in item.get('items', []):\n#                 if sub_item.get('type') == 'doc' and query.lower() in sub_item['label'].lower():\n#                     results.append(sub_item)\n#     \n#     return templates.TemplateResponse(\n#         \"search_results.html\", # Arama sonu\u00e7lar\u0131 i\u00e7in ayr\u0131 bir \u015fablon\n#         {\"request\": request, \"sidebar_config\": sidebar_config, \"title\": f\"Arama Sonu\u00e7lar\u0131: {query}\", \"query\": query, \"results\": results}\n#     )\n<\/pre>\n<p><\/code><\/p>\n<h3>4. \u00c7ok Dilli Destek<\/h3>\n<p>Uluslararas\u0131 projeler i\u00e7in dok\u00fcmantasyonun birden \u00e7ok dilde sunulmas\u0131 gerekebilir. Bunu uygulamak i\u00e7in:<\/p>\n<ul>\n<li>Her dil i\u00e7in ayr\u0131 <code>docs\/<\/code> klas\u00f6rleri (\u00f6rn. <code>docs\/en\/<\/code>, <code>docs\/tr\/<\/code>) ve ayr\u0131 <code>sidebar.yaml<\/code> dosyalar\u0131 tutulabilir.<\/li>\n<li>Kullan\u0131c\u0131n\u0131n dil tercihini (taray\u0131c\u0131 ayarlar\u0131ndan veya URL parametresinden) alg\u0131layarak dinamik olarak do\u011fru dil setini y\u00fckleyebilirsiniz.<\/li>\n<\/ul>\n<p>Bu, kullan\u0131c\u0131lar\u0131n kendi ana dillerinde dok\u00fcmantasyona eri\u015fmesini sa\u011flayarak genel kullan\u0131c\u0131 deneyimini art\u0131r\u0131r.<\/p>\n<h3>5. \u00d6zelle\u015ftirilebilir Temalar<\/h3>\n<p>Docusaurus gibi sistemlerde tema deste\u011fi yayg\u0131nd\u0131r. Bizim kurulumumuzda, <code>templates\/<\/code> ve <code>static\/<\/code> klas\u00f6rlerini farkl\u0131 temalar\u0131 destekleyecek \u015fekilde geni\u015fletebiliriz. Kullan\u0131c\u0131lar URL parametresi veya bir ayarla tema se\u00e7imi yapabilir ve FastAPI bu se\u00e7ime g\u00f6re farkl\u0131 \u015fablon ve CSS dosyalar\u0131n\u0131 y\u00fckleyebilir. Bu, projenizin g\u00f6rsel kimli\u011fini esnek bir \u015fekilde y\u00f6netmenizi sa\u011flar.<\/p>\n<p>Bu ileri d\u00fczey optimizasyonlar, FastAPI ile kurdu\u011funuz dok\u00fcmantasyon sitesinin sadece i\u015flevsel de\u011fil, ayn\u0131 zamanda performansl\u0131, \u00f6l\u00e7eklenebilir ve \u00e7e\u015fitli kullan\u0131c\u0131 ihtiya\u00e7lar\u0131na yan\u0131t verebilir olmas\u0131n\u0131 sa\u011flayacakt\u0131r. Her bir ad\u0131m, projenizin olgunluk seviyesini art\u0131r\u0131rken, geli\u015ftirici ve kullan\u0131c\u0131 deneyimini de iyile\u015ftirmeye odaklanm\u0131\u015ft\u0131r.<\/p>\n<aside class=\"expert-tip\">\n  Uzman \u0130pucu: Kapsaml\u0131 bir dok\u00fcmantasyon sitesi i\u00e7in <code>robots.txt<\/code> ve <code>sitemap.xml<\/code> dosyalar\u0131n\u0131 da dinamik olarak olu\u015fturmay\u0131 d\u00fc\u015f\u00fcn\u00fcn. Bu, arama motorlar\u0131n\u0131n sitenizi daha iyi indekslemesine yard\u0131mc\u0131 olur ve SEO performans\u0131n\u0131 art\u0131r\u0131r.<br \/>\n<\/aside>\n<h2>Sonu\u00e7 ve S\u0131k\u00e7a Sorulan Sorular<\/h2>\n<p>Bu makalede, FastAPI ve Jinja2'nin g\u00fcc\u00fcn\u00fc kullanarak, Docusaurus benzeri dinamik ve esnek bir dok\u00fcmantasyon sitesi sidebar'\u0131 nas\u0131l olu\u015fturulaca\u011f\u0131n\u0131 ad\u0131m ad\u0131m \u00f6\u011frendik. <code>sidebar.yaml<\/code> gibi yap\u0131land\u0131rma dosyalar\u0131 arac\u0131l\u0131\u011f\u0131yla men\u00fc \u00f6\u011felerini tan\u0131mlaman\u0131n, Markdown i\u00e7eri\u011fini HTML'e \u00e7evirmenin ve t\u00fcm bu bile\u015fenleri FastAPI uygulamas\u0131nda bir araya getirmenin inceliklerini ke\u015ffettik. Ortaya \u00e7\u0131kan \u00e7\u00f6z\u00fcm, statik site \u00fcreticilerinin sundu\u011fu kolayl\u0131\u011f\u0131 dinamik bir web uygulamas\u0131n\u0131n esnekli\u011fiyle birle\u015ftirerek, projenizin dok\u00fcmantasyonunu y\u00f6netmek i\u00e7in g\u00fc\u00e7l\u00fc bir temel sunmaktad\u0131r. Bu yakla\u015f\u0131m, sadece i\u00e7erik olu\u015fturmaya odaklanman\u0131z\u0131 sa\u011flamakla kalmaz, ayn\u0131 zamanda bak\u0131m kolayl\u0131\u011f\u0131, tutarl\u0131l\u0131k ve \u00f6l\u00e7eklenebilirlik gibi \u00f6nemli avantajlar\u0131 da beraberinde getirir.<\/p>\n<p>Uygulamam\u0131z art\u0131k Markdown dok\u00fcmanlar\u0131n\u0131 otomatik olarak HTML'e d\u00f6n\u00fc\u015ft\u00fcrebiliyor, yap\u0131land\u0131r\u0131labilir bir men\u00fc ile gezinme sa\u011fl\u0131yor ve basit CSS\/JS entegrasyonuyla modern bir g\u00f6r\u00fcn\u00fcm sunuyor. Ayr\u0131ca, mobil uyumlu tasar\u0131m ipu\u00e7lar\u0131 ve ileri seviye optimizasyon \u00f6nerileriyle (\u00f6nbellekleme, dosya takibi, arama entegrasyonu), projenizi daha da geli\u015ftirebilece\u011finiz yollar\u0131 g\u00f6sterdik. FastAPI'nin sundu\u011fu performans ve Jinja2'nin \u015fablonlama yetenekleriyle birle\u015fen bu mimari, kendi \u00f6zel dok\u00fcmantasyon \u00e7\u00f6z\u00fcm\u00fcn\u00fcz\u00fc in\u015fa etmek isteyen herkese ilham verecektir.<\/p>\n<h3>S\u0131k\u00e7a Sorulan Sorular (SSS)<\/h3>\n<ol>\n<li>\n        <strong>S: Neden Docusaurus gibi haz\u0131r bir arac\u0131 kullanmak yerine kendi \u00e7\u00f6z\u00fcm\u00fcm\u00fcz\u00fc FastAPI ile in\u015fa etmeliyiz?<\/strong><br \/>\n        <strong>C:<\/strong> Docusaurus harika bir ara\u00e7 olsa da, FastAPI ile kendi \u00e7\u00f6z\u00fcm\u00fcn\u00fcz\u00fc in\u015fa etmek size daha fazla esneklik ve kontrol sa\u011flar. \u00d6zellikle dok\u00fcmantasyonunuz bir FastAPI web uygulamas\u0131yla s\u0131k\u0131 entegrasyon gerektiriyorsa, API'lerden dinamik i\u00e7erik \u00e7ekmeniz gerekiyorsa, \u00f6zel kimlik do\u011frulama veya yetkilendirme mekanizmalar\u0131 uygulayacaksan\u0131z, veya sadece Python ekosistemi i\u00e7inde kalmay\u0131 tercih ediyorsan\u0131z, bu yakla\u015f\u0131m daha uygun olabilir.\n    <\/li>\n<li>\n        <strong>S: Sidebar'da \u00e7ok say\u0131da dok\u00fcman olursa performans sorunlar\u0131 ya\u015far m\u0131y\u0131m?<\/strong><br \/>\n        <strong>C:<\/strong> Mevcut haliyle, <code>sidebar.yaml<\/code> dosyas\u0131n\u0131n b\u00fcy\u00fck olmas\u0131 veya \u00e7ok say\u0131da Markdown dosyas\u0131n\u0131n her istekte okunup i\u015flenmesi potansiyel bir performans darbo\u011faz\u0131 yaratabilir. Bu nedenle, makalede bahsedilen <code>lru_cache<\/code> gibi \u00f6nbellekleme tekniklerini veya daha b\u00fcy\u00fck projeler i\u00e7in Redis gibi harici bir \u00f6nbellekleme \u00e7\u00f6z\u00fcm\u00fcn\u00fc kullanman\u0131z \u015fiddetle tavsiye edilir.\n    <\/li>\n<li>\n        <strong>S: Markdown dosyalar\u0131na ek olarak ba\u015fka formatlarda (\u00f6rn. reStructuredText, AsciiDoc) dok\u00fcman ekleyebilir miyim?<\/strong><br \/>\n        <strong>C:<\/strong> Evet, <code>convert_markdown_to_html<\/code> fonksiyonu gibi kendi \u00f6zel d\u00f6n\u00fc\u015ft\u00fcr\u00fcc\u00fc fonksiyonlar\u0131n\u0131z\u0131 yazarak ve FastAPI rotan\u0131zda bu fonksiyonlar\u0131 \u00e7a\u011f\u0131rarak farkl\u0131 dok\u00fcman formatlar\u0131n\u0131 destekleyebilirsiniz. \u00d6rne\u011fin, <code>python-docutils<\/code> k\u00fct\u00fcphanesini kullanarak reStructuredText dosyalar\u0131n\u0131 HTML'e \u00e7evirebilirsiniz. <code>sidebar.yaml<\/code>'deki <code>type<\/code> alan\u0131n\u0131 geni\u015fleterek farkl\u0131 formatlar\u0131 belirtebilirsiniz.\n    <\/li>\n<li>\n        <strong>S: Sidebar'a dinamik olarak kategori veya dok\u00fcman eklemenin bir yolu var m\u0131?<\/strong><br \/>\n        <strong>C:<\/strong> Evet. Mevcut kurulum, <code>sidebar.yaml<\/code> dosyas\u0131n\u0131 de\u011fi\u015ftirmenizi gerektirir. Ancak, ileri seviye bir yakla\u015f\u0131m olarak, bir y\u00f6netim paneli veya API endpoint'i arac\u0131l\u0131\u011f\u0131yla veritaban\u0131nda saklanan kategori\/dok\u00fcman bilgilerini g\u00fcncelleyebilir ve FastAPI uygulaman\u0131z\u0131n bu veritaban\u0131ndan sidebar'\u0131 olu\u015fturmas\u0131n\u0131 sa\u011flayabilirsiniz. Ayr\u0131ca, <code>watchdog<\/code> ile dosya de\u011fi\u015fikliklerini izleyerek otomatik g\u00fcncelleme de m\u00fcmk\u00fcnd\u00fcr.\n    <\/li>\n<li>\n        <strong>S: Dok\u00fcman sayfalar\u0131nda resimler veya di\u011fer statik varl\u0131klar nas\u0131l kullan\u0131l\u0131r?<\/strong><br \/>\n        <strong>C:<\/strong> Resimlerinizi ve di\u011fer statik varl\u0131klar\u0131n\u0131z\u0131 <code>static\/<\/code> klas\u00f6r\u00fcn\u00fcn uygun alt dizinlerine (\u00f6rn. <code>static\/images\/<\/code>) yerle\u015ftirebilirsiniz. Markdown dosyalar\u0131n\u0131zda bu varl\u0131klara referans verirken, FastAPI'nin statik dosya sunumu i\u00e7in ayarlad\u0131\u011f\u0131 <code>\/static\/<\/code> URL \u00f6n ekini kullanmal\u0131s\u0131n\u0131z. \u00d6rne\u011fin: <code>![Resim A\u00e7\u0131klamas\u0131](\/static\/images\/my-image.png)<\/code>. Bu, taray\u0131c\u0131n\u0131n do\u011fru dosyay\u0131 bulmas\u0131n\u0131 sa\u011flar.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"Docusaurus Benzeri FastAPI Sitesinde Dinamik Sidebar Olu\u015fturma Rehberi Modern dok\u00fcmantasyon siteleri, kullan\u0131c\u0131lar\u0131n arad\u0131klar\u0131 bilgiye h\u0131zl\u0131ca ula\u015fmalar\u0131n\u0131 sa\u011flayan, iyi&hellip;","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-34855","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Neden Dinamik Bir Sidebar&#039;a \u0130htiya\u00e7 Duyar\u0131z?<\/title>\n<meta name=\"description\" content=\"Modern dok\u00fcmantasyon siteleri, kullan\u0131c\u0131lar\u0131n arad\u0131klar\u0131 bilgiye h\u0131zl\u0131ca ula\u015fmalar\u0131n\u0131 sa\u011flayan, iyi d\u00fczenlenmi\u015f ve etkile\u015fimli sidebar (kenar \u00e7ubu\u011fu) navigasyonuna sahiptir. Docusaurus gibi pop\u00fcler statik site \u00fcreticileri bu konuda standartlar\u0131 belirlerken, FastAPI ile dinamik bir web sitesi geli\u015ftirirken benzer bir deneyimi nas\u0131l sunabiliriz? Bu makalede, FastAPI ve Jinja2 kullanarak, dosya sistemi tabanl\u0131 veya yap\u0131land\u0131rma dosyalar\u0131 \u00fczerinden dinamik olarak olu\u015fturulan, Docusaurus benzeri bir sidebar yap\u0131s\u0131n\u0131 ad\u0131m ad\u0131m in\u015fa edece\u011fiz. Bu sayede, projenizin dok\u00fcmantasyonunu y\u00f6netmek ve kullan\u0131c\u0131lar\u0131n\u0131za kesintisiz bir gezinme deneyimi sunmak art\u0131k \u00e7ok daha kolay olacak. Haz\u0131r m\u0131s\u0131n\u0131z?\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Neden Dinamik Bir Sidebar&#039;a \u0130htiya\u00e7 Duyar\u0131z?\" \/>\n<meta property=\"og:description\" content=\"Modern dok\u00fcmantasyon siteleri, kullan\u0131c\u0131lar\u0131n arad\u0131klar\u0131 bilgiye h\u0131zl\u0131ca ula\u015fmalar\u0131n\u0131 sa\u011flayan, iyi d\u00fczenlenmi\u015f ve etkile\u015fimli sidebar (kenar \u00e7ubu\u011fu) navigasyonuna sahiptir. Docusaurus gibi pop\u00fcler statik site \u00fcreticileri bu konuda standartlar\u0131 belirlerken, FastAPI ile dinamik bir web sitesi geli\u015ftirirken benzer bir deneyimi nas\u0131l sunabiliriz? Bu makalede, FastAPI ve Jinja2 kullanarak, dosya sistemi tabanl\u0131 veya yap\u0131land\u0131rma dosyalar\u0131 \u00fczerinden dinamik olarak olu\u015fturulan, Docusaurus benzeri bir sidebar yap\u0131s\u0131n\u0131 ad\u0131m ad\u0131m in\u015fa edece\u011fiz. Bu sayede, projenizin dok\u00fcmantasyonunu y\u00f6netmek ve kullan\u0131c\u0131lar\u0131n\u0131za kesintisiz bir gezinme deneyimi sunmak art\u0131k \u00e7ok daha kolay olacak. Haz\u0131r m\u0131s\u0131n\u0131z?\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-22T19:01:44+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"43 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Neden Dinamik Bir Sidebar&#8217;a \u0130htiya\u00e7 Duyar\u0131z?\",\"datePublished\":\"2025-11-22T19:01:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/\"},\"wordCount\":5511,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/\",\"name\":\"Neden Dinamik Bir Sidebar'a \u0130htiya\u00e7 Duyar\u0131z?\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-11-22T19:01:44+00:00\",\"description\":\"Modern dok\u00fcmantasyon siteleri, kullan\u0131c\u0131lar\u0131n arad\u0131klar\u0131 bilgiye h\u0131zl\u0131ca ula\u015fmalar\u0131n\u0131 sa\u011flayan, iyi d\u00fczenlenmi\u015f ve etkile\u015fimli sidebar (kenar \u00e7ubu\u011fu) navigasyonuna sahiptir. Docusaurus gibi pop\u00fcler statik site \u00fcreticileri bu konuda standartlar\u0131 belirlerken, FastAPI ile dinamik bir web sitesi geli\u015ftirirken benzer bir deneyimi nas\u0131l sunabiliriz? Bu makalede, FastAPI ve Jinja2 kullanarak, dosya sistemi tabanl\u0131 veya yap\u0131land\u0131rma dosyalar\u0131 \u00fczerinden dinamik olarak olu\u015fturulan, Docusaurus benzeri bir sidebar yap\u0131s\u0131n\u0131 ad\u0131m ad\u0131m in\u015fa edece\u011fiz. Bu sayede, projenizin dok\u00fcmantasyonunu y\u00f6netmek ve kullan\u0131c\u0131lar\u0131n\u0131za kesintisiz bir gezinme deneyimi sunmak art\u0131k \u00e7ok daha kolay olacak. Haz\u0131r m\u0131s\u0131n\u0131z?\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Neden Dinamik Bir Sidebar&#8217;a \u0130htiya\u00e7 Duyar\u0131z?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Neden Dinamik Bir Sidebar'a \u0130htiya\u00e7 Duyar\u0131z?","description":"Modern dok\u00fcmantasyon siteleri, kullan\u0131c\u0131lar\u0131n arad\u0131klar\u0131 bilgiye h\u0131zl\u0131ca ula\u015fmalar\u0131n\u0131 sa\u011flayan, iyi d\u00fczenlenmi\u015f ve etkile\u015fimli sidebar (kenar \u00e7ubu\u011fu) navigasyonuna sahiptir. Docusaurus gibi pop\u00fcler statik site \u00fcreticileri bu konuda standartlar\u0131 belirlerken, FastAPI ile dinamik bir web sitesi geli\u015ftirirken benzer bir deneyimi nas\u0131l sunabiliriz? Bu makalede, FastAPI ve Jinja2 kullanarak, dosya sistemi tabanl\u0131 veya yap\u0131land\u0131rma dosyalar\u0131 \u00fczerinden dinamik olarak olu\u015fturulan, Docusaurus benzeri bir sidebar yap\u0131s\u0131n\u0131 ad\u0131m ad\u0131m in\u015fa edece\u011fiz. Bu sayede, projenizin dok\u00fcmantasyonunu y\u00f6netmek ve kullan\u0131c\u0131lar\u0131n\u0131za kesintisiz bir gezinme deneyimi sunmak art\u0131k \u00e7ok daha kolay olacak. Haz\u0131r m\u0131s\u0131n\u0131z?","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/","og_locale":"tr_TR","og_type":"article","og_title":"Neden Dinamik Bir Sidebar'a \u0130htiya\u00e7 Duyar\u0131z?","og_description":"Modern dok\u00fcmantasyon siteleri, kullan\u0131c\u0131lar\u0131n arad\u0131klar\u0131 bilgiye h\u0131zl\u0131ca ula\u015fmalar\u0131n\u0131 sa\u011flayan, iyi d\u00fczenlenmi\u015f ve etkile\u015fimli sidebar (kenar \u00e7ubu\u011fu) navigasyonuna sahiptir. Docusaurus gibi pop\u00fcler statik site \u00fcreticileri bu konuda standartlar\u0131 belirlerken, FastAPI ile dinamik bir web sitesi geli\u015ftirirken benzer bir deneyimi nas\u0131l sunabiliriz? Bu makalede, FastAPI ve Jinja2 kullanarak, dosya sistemi tabanl\u0131 veya yap\u0131land\u0131rma dosyalar\u0131 \u00fczerinden dinamik olarak olu\u015fturulan, Docusaurus benzeri bir sidebar yap\u0131s\u0131n\u0131 ad\u0131m ad\u0131m in\u015fa edece\u011fiz. Bu sayede, projenizin dok\u00fcmantasyonunu y\u00f6netmek ve kullan\u0131c\u0131lar\u0131n\u0131za kesintisiz bir gezinme deneyimi sunmak art\u0131k \u00e7ok daha kolay olacak. Haz\u0131r m\u0131s\u0131n\u0131z?","og_url":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-11-22T19:01:44+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"43 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Neden Dinamik Bir Sidebar&#8217;a \u0130htiya\u00e7 Duyar\u0131z?","datePublished":"2025-11-22T19:01:44+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/"},"wordCount":5511,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/","url":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/","name":"Neden Dinamik Bir Sidebar'a \u0130htiya\u00e7 Duyar\u0131z?","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-11-22T19:01:44+00:00","description":"Modern dok\u00fcmantasyon siteleri, kullan\u0131c\u0131lar\u0131n arad\u0131klar\u0131 bilgiye h\u0131zl\u0131ca ula\u015fmalar\u0131n\u0131 sa\u011flayan, iyi d\u00fczenlenmi\u015f ve etkile\u015fimli sidebar (kenar \u00e7ubu\u011fu) navigasyonuna sahiptir. Docusaurus gibi pop\u00fcler statik site \u00fcreticileri bu konuda standartlar\u0131 belirlerken, FastAPI ile dinamik bir web sitesi geli\u015ftirirken benzer bir deneyimi nas\u0131l sunabiliriz? Bu makalede, FastAPI ve Jinja2 kullanarak, dosya sistemi tabanl\u0131 veya yap\u0131land\u0131rma dosyalar\u0131 \u00fczerinden dinamik olarak olu\u015fturulan, Docusaurus benzeri bir sidebar yap\u0131s\u0131n\u0131 ad\u0131m ad\u0131m in\u015fa edece\u011fiz. Bu sayede, projenizin dok\u00fcmantasyonunu y\u00f6netmek ve kullan\u0131c\u0131lar\u0131n\u0131za kesintisiz bir gezinme deneyimi sunmak art\u0131k \u00e7ok daha kolay olacak. Haz\u0131r m\u0131s\u0131n\u0131z?","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/neden-dinamik-bir-sidebara-ihtiyac-duyariz\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Neden Dinamik Bir Sidebar&#8217;a \u0130htiya\u00e7 Duyar\u0131z?"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34855","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=34855"}],"version-history":[{"count":0,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34855\/revisions"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=34855"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=34855"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=34855"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}