Eskiden her sabah görevler ve düşünceler içinde boğuluyordum: şimdi ne yapmalı, kime yanıt vermeli, işlerin önceliği ne ve birkaç gün önce ne düşünüyordum? Şimdi tek bir not açıyorum — ve tüm projelerimi, görevlerimi, alışkanlıklarımı ve düşüncelerimi hemen görüyorum. Bu makalede tüm günlük not sistemimi ayrıntılı, adım adım ve olabildiğince basit bir dille ele alacağım — böylece onu kendine kelimenin tam anlamıyla bir akşamda kurabilesin.


Obsidian’da neden günlük tutmalı

Kâğıt bir not defteri harikadır. Ama bir eksisi var: dün yazdığın “dünde” kalır.

Görevler kendiliğinden taşınmaz, alışkanlıklar bir grafikte toplanmaz ve düşünceler sayfalar arasında kaybolur.

Obsidian’da her şey farklı. Günlük not, gününün merkezi olur:

🔁
Görevler
kendiliğinden taşınır ve projelerden gelir
📅
Takvim
Google Calendar ile senkronizasyon
Alışkanlıklar
düğmeler ve ilerleme grafikleri
💭
Düşünceler
fikirler ve düşünceler için serbest bir alan

Sabah uyandığımda, dün neyle meşgul olduğumu hemen hatırlıyorum. Tamamlanmamış görevler otomatik olarak bugüne taşınıyor. Basit rutinleri — alışkanlıklar, meditasyon — tek bir düğmeyle işaretliyorum ve net bir dinamikte toplanıyorlar. Ve yeni görevleri doğrudan hedeflerimle bağlı projelerimden alıyorum.

Bu basit sistem beni odaklı tutuyor: ertelemek yerine gerçekten gerekeni yapıyorum. Onu birlikte kuralım.

Sistemimin ve PARA yapısının tam açıklaması — sitedeki önceki materyallerde.


Adım 1. Ne kurmalı

Obsidian’da görevleri, düşünceleri ve alışkanlıkları tutmak için birkaç eklentiye ve bir yerleşik ayara ihtiyacımız var.

Topluluk eklentileri

Ayarlar → Topluluk eklentileri → Gözat’ı açıyoruz ve sırayla kuruyoruz:

EklentiNe için
DataviewNotlardan veri toplar (örn. günlere göre düşünceler, grafikler)
Meta BindNot özelliklerini doğrudan metinde düğme ve alanlara çevirir
HomepageAçılışta açılan bir ana sayfa yapar
TemplaterBir not oluşturulduğunda betikler çalıştırır (görev taşıma)
ButtonsTek tıkla komut çalıştıran düğmeler oluşturur
QuickAddDüğmelerin “beyni”: makro ve betik çalıştırır

Dataview'i kurduktan sonra ayarlarına gir ve tüm kutucukları işaretle (özellikle Enable JavaScript Queries ve Enable Inline JavaScript Queries) — bunlar olmadan takvim widget'ı çalışmaz.

Yerleşik “Günlük Notlar”ı etkinleştirme

Obsidian “kutudan çıktığı gibi” günlük tutabilir. Ayarlar → Core plugins’e gidip Daily notes’u etkinleştiriyoruz. Sonra onları kendimize göre ayarlıyoruz.

Üç anahtar ayar:

  1. Not başlığı formatı. Benim için bu sadece gün, ay ve yıl:

    DD-MM-YYYY
    

    Bu önemli: tüm kodum (widget, görev taşıma) notları tam olarak DD-MM-YYYY formatında arar. Başlığa haftanın gününü eklemek istersen — harfleri ekle (örn. dddd), ama o zaman formatı kodda da düzelt. Hangi harfin neyden sorumlu olduğunu format.cm (Moment.js belgeleri) sitesinde bakmak kullanışlı.

  2. Yeni notlar klasörü. Benim için günlük notlar 2. Areas/Дневники/Ежедневные заметки içinde. Her şeyi PARA yapısına göre tutuyorum ve günlük tutmak bir “yaşam alanı” (Area), bu yüzden yeri Areas klasörü.

  1. Şablon. Bu, her yeni notun oluşturulacağı yapıdır. Şablonum 0. Files/4. Templates/Шаблон ежедневных заметок içinde. “Templates” şablonlar demek.

Günlük notumun yapısı şöyle görünür:

Özellikler → hafta/takvim widget’ı → gün için planlar → görev taşıma → alışkanlıklar → beslenme → düşünceler. Her şeyi doldurmak her zaman mümkün olmuyor. Ama çabanın kendisi beni daha disiplinli yapıyor.

Uzun uzun çözmek istemeyenler için

Hazır Obsidian şablonumu dene ve bilgini bugün sistematikleştirmeye başla

Şablon hakkında bilgi al

Adım 2. Notun özellikleri (YAML)

Şablonu açıp yukarıdan aşağıya inceleyelim. İlk gördüğümüz şey — notun özellikleri (onlara YAML ya da frontmatter da denir).

Anlamları ne? Özellikler, notun diğer eklentilerin kolayca okuduğu “resmî” verileridir. Örneğin, alışkanlık grafiği bilgiyi tam olarak özelliklerden alır, sıradan metinden değil. Bu kuralı hatırlamakta fayda var: grafikler ve otomasyon için önemli olanı — özelliklerde sakla.

Özellikler, notun en üstünde üç tireden oluşan iki satır arasına yazılır:

---
Спорт: false
Чтение: false
Прогулка: false
Завтрак:
Перекусы:
Обед:
Ужин:
Итого_ккал:
---

Burada iki grup var:

  • Alışkanlıklar (Спорт, Чтение, Прогулка) — “onay kutusu” tipi. false “henüz yapılmadı” demek.
  • Beslenme (Завтрак, Обед, Ужин, Перекусы, Итого_ккал) — “metin” tipi, buraya ne yediğini ve bir kalori sayacı yazarız.

Kendi özelliğini eklemek basit: özellikler modunda **"+ Özellik ekle"**ye bas, adı yaz ve tipi seç (metin, sayı, onay kutusu, tarih). Birkaç gün doldurmadan sonra bir grafikte dinamiği zaten görürsün.


Adım 3. Google Calendar ve görevlerle senkronizasyon

Şablonda özelliklerin hemen altında büyük bir kod bloğu gelir. Korkma — onu bir AI yazdı, ben sadece yapıştırdım. Bu kod güzel bir widget çizer: haftanın gününü, hafta ilerlemesini gösterir ve “Görevler” modunda — Google Calendar ve Google Tasks’ınla senkronize olur. Doğrudan Obsidian’dan günün etkinliklerini ve görevlerini görür, onları tamamlanmış işaretleyebilir ve yenilerini ekleyebilirsin.

Bunun çalışması için şablondaki kod tek başına yetmez. Obsidian’a Google hesabına erişim vermen gerekir. Bu, ücretsiz Google Apps Script servisi üzerinden yapılır. Adım adım ele alalım — yavaş ve ayrıntılı.

3.1. scripts.google.com’da sunucuyu hazırlama

1
script.google.com'u aç ve "Yeni proje"ye bas.
2
Editördeki tüm metni sil ve aşağıda verdiğim kodu yapıştır.
3
Google Tasks API servisini bağla: solda "Hizmetler" menüsünde ("+" simgesi) Tasks API'yi bul ve "Ekle"ye bas. Bu adım olmadan kod görevlerini görmez.

Adım 3 en sık atlanan. Kod Tasks.Tasklists.list() kullanır ve bu bir "gelişmiş hizmet"tir. Tasks API'yi eklemezsen, betik bir hatayla çöker.

İşte editöre yapıştırman gereken kod (etkinlik/görevleri okumaktan ve görev oluşturmaktan/kapatmaktan sorumlu):

// ======================================
// GOOGLE APPS SCRIPT — TASKS + CALENDAR
// ======================================
 
// Yetkilendirme kontrolü (bir kez elle çalıştır)
function testAuth() {
  const taskLists = Tasks.Tasklists.list();
  Logger.log(taskLists);
  const events = CalendarApp.getDefaultCalendar().getEvents(new Date(), new Date());
  Logger.log(events.length + " bugün etkinlik");
}
 
// ====== OKUMA: takvim etkinlikleri + gün için görevler ======
function doGet(e) {
  try {
    const tz = Session.getScriptTimeZone();
 
    // DEBUG modu: tarayıcıda GAS_URL?debug=1 aç — TÜM görevleri gösterir
    if (e && e.parameter && e.parameter.debug) {
      const debugLists = (Tasks.Tasklists.list().items) || [];
      const all = [];
      debugLists.forEach(list => {
        const items = (Tasks.Tasks.list(list.id, {
          showCompleted: true, showHidden: true, maxResults: 100
        }).items) || [];
        items.forEach(t => {
          all.push({ list: list.title, listId: list.id, title: t.title, due: t.due || null, status: t.status });
        });
      });
      return ContentService
        .createTextOutput(JSON.stringify({
          success: true, scriptTimeZone: tz,
          listsFound: debugLists.map(l => l.title),
          totalTasks: all.length, all: all
        }))
        .setMimeType(ContentService.MimeType.JSON);
    }
 
    const param = (e && e.parameter && e.parameter.date) ? e.parameter.date : null;
    const base = param
      ? new Date(+param.split("-")[0], +param.split("-")[1] - 1, +param.split("-")[2])
      : new Date();
 
    const start = new Date(base.getFullYear(), base.getMonth(), base.getDate(), 0, 0, 0);
    const end   = new Date(base.getFullYear(), base.getMonth(), base.getDate(), 23, 59, 59);
    const dayStr = Utilities.formatDate(base, tz, "yyyy-MM-dd");
 
    const events = CalendarApp.getDefaultCalendar().getEvents(start, end).map(ev => ({
      title: ev.getTitle(),
      allDay: ev.isAllDayEvent(),
      time: ev.isAllDayEvent() ? null : Utilities.formatDate(ev.getStartTime(), tz, "HH:mm")
    }));
 
    const tasks = [];
    const lists = (Tasks.Tasklists.list().items) || [];
    const today = new Date();
    const todayStr = Utilities.formatDate(today, tz, "yyyy-MM-dd");
    const isToday = dayStr === todayStr;
 
    lists.forEach(list => {
      const items = (Tasks.Tasks.list(list.id, { showCompleted: true, showHidden: true }).items) || [];
      items.forEach(t => {
        if (!t.due) return;
        const taskDay = t.due.substring(0, 10);
        const isExactDay = taskDay === dayStr;
        const isOverdue = isToday && taskDay < dayStr && t.status === "needsAction";
        if (isExactDay || isOverdue) {
          tasks.push({
            id: t.id, listId: list.id, title: t.title,
            status: t.status, completed: t.completed || null, overdue: isOverdue
          });
        }
      });
    });
 
    tasks.sort((a, b) => (a.overdue === b.overdue) ? 0 : (a.overdue ? -1 : 1));
 
    return ContentService
      .createTextOutput(JSON.stringify({ success: true, date: dayStr, events, tasks }))
      .setMimeType(ContentService.MimeType.JSON);
 
  } catch (error) {
    return ContentService
      .createTextOutput(JSON.stringify({ success: false, error: error.toString() }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}
 
// ====== YAZMA: bir görev oluştur YA DA kapat ======
function doPost(e) {
  try {
    const data = JSON.parse(e.postData.contents);
 
    if (data.action === "complete") {
      const listId = data.listId || Tasks.Tasklists.list().items[0].id;
      Tasks.Tasks.patch({ status: "completed" }, listId, data.taskId);
      return ContentService
        .createTextOutput(JSON.stringify({ success: true, message: 'Görev tamamlandı!' }))
        .setMimeType(ContentService.MimeType.JSON);
    }
 
    const title = data.title;
    const dueDate = data.dueDate;
    const taskLists = Tasks.Tasklists.list();
    const defaultTaskList = taskLists.items[0].id;
 
    const task = Tasks.Tasks.insert({ title: title, due: dueDate, status: 'needsAction' }, defaultTaskList);
 
    return ContentService
      .createTextOutput(JSON.stringify({ success: true, taskId: task.id, message: 'Görev eklendi!' }))
      .setMimeType(ContentService.MimeType.JSON);
 
  } catch (error) {
    return ContentService
      .createTextOutput(JSON.stringify({ success: false, error: error.toString() }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

3.2. İlk kez izin verme

Google, sen kişisel olarak izin vermeden kodun takvimine dokunmasına izin vermez. Bunu bir kez elle yapalım:

1
Üstteki fonksiyon açılır listesinde testAuth'u seç ve "Çalıştır"a (▶) bas.
2
"Yetkilendirme gerekli" penceresi belirir → "İzinleri incele"ye bas ve Google hesabını seç.
3
Korkutucu bir "Google bu uygulamayı doğrulamadı" ekranı belirir. Bu normal — uygulama senin kendine ait. Altta "Gelişmiş" → "… sayfasına git (güvenli değil)"ye bas.
4
"İzin ver"e bas. Hazır — erişim verildi. Günlükte (Logs) görev listelerini görürsün.

"Google uygulamayı doğrulamadı" ekranı herkesin kişisel betiklerinde belirir. Veriyi dışarıdan kimseye aktarmıyorsun — kod yalnızca senin hesabında çalışır.

3.3. Dağıtım ve hangi bağlantıyı kopyalamalı

Şimdi koddan, Obsidian’ın erişeceği gerçek bir web adresi yapalım:

1
Sağ üstte "Dağıtımı başlat" → "Yeni dağıtım"a bas.
2
Tip seçim dişlisine tıkla ve "Web uygulaması" (Web app) seç.
3
Doldur:
Şu kişi olarak çalıştır: "Ben" (hesabın)
Erişimi olan: "Herkes" (Anyone)
4
"Dağıt"a bas. "Web uygulaması URL'si"ni kopyala — bu, /exec ile biten o bağlantı.

Tam olarak /exec ile biten bağlantıyı kopyala. /dev ile biten bir bağlantı Obsidian'da çalışmaz.

https://script.google.com/macros/s/AKfycbx…………/exec

3.4. Widget kodunu şablona yapıştırma

Şimdi günlük not şablonuna widget kodunu yapıştırıyoruz. Bu, hafta ve takvimle bir kart çizen bir ```dataviewjs bloğudur. En önemlisi — ilk satırda tırnak içindeki bağlantıyı 3.3 adımındaki kendi bağlantınla değiştir:

const GAS_URL = "exec_İLE_BİTEN_KENDİ_BAĞLANTINI_BURAYA_YAPIŞTIR";

Widget kodunun başında şöyle görünür (yalnızca GAS_URL satırını değiştirirsin, gerisine dokunmazsın):

```dataviewjs
const GAS_URL = "https://script.google.com/macros/s/AKfyc…………/exec";

const obsidian = require("obsidian");

const fileName = dv.current().file.name;
const m = fileName.match(/^(\d{2})-(\d{2})-(\d{4})$/);

if (!m) {
  dv.paragraph("⚠️ Not başlığı DD-MM-YYYY formatında olmalı");
} else {
  // … sonra uzun widget kodu gelir: hafta, ilerleme,
  //   "Görevler" düğmesi, takvimden etkinlik ve görev yükleme …
}
```

Hazır! Artık notta bugünkü görevleri görürsün, gecikmiş görevler kırmızıyla vurgulanır, görevler tamamlanmış işaretlenebilir ve yenileri eklenebilir. Bu özellikle telefonda kullanışlı: widget’ı açtın — ve hızlıca işleri ekledin.

Çalışmayı kontrol etme. Bağlantını tarayıcıda, sonuna ?debug=1 ekleyerek aç. Görevlerinin bir listesiyle JSON görürsen — sunucu doğru çalışıyor.

Uzun uzun çözmek istemeyenler için

Hazır Obsidian şablonumu dene ve bilgini bugün sistematikleştirmeye başla

Şablon hakkında bilgi al

Adım 4. Gün için planlar ve düğmeler

Şablonun bir sonraki bölümü — gün için planlar. Burada Buttons eklentisinden düğme etiketlerim var:

`button-spaced-repetition` `button-sport` `button-morning-routine` `button-work-on-project` `button-litso`

Böyle her etiket, gün içinde bastığım bir düğmedir:

DüğmeNe başlatır
🃏 Aralıklı tekrarÖğrendiğim materyali hatırlama
💪 AntrenmanlarBugünkü egzersizler (kas gruplarına göre otomatik değişir)
🙏 SabahSabah ritüelim — meditasyon ve konsantrasyon
📋 GörevProjeleri aç ve oradan bir görev al (ana düğme!)
😌 YüzKişisel bakım rutini

Bu işlevler kademeli eklendi. Önce notta yalnızca sabah ritüeli vardı. Sonra aralıklı tekrar, antrenmanlar ve geri kalanını ekledim — beyni aşırı yüklememek için gerektikçe. Sana da bir-iki düğmeyle başlamanı öneririm.


Adım 5. Düğmeler (Buttons) nasıl çalışır — basit sözlerle

Yeni başlayanların en sık yanlış anlaması: “neden notta `button-sport` yazılı ama güzel bir düğme beliriyor?” Anlayalım.

Mantık iki parçaya ayrılır: düğmenin tanımlandığı yer ve gösterildiği yer.

1. "MOC - Buttons" notu
Burada tüm düğmelerin tam açıklamaları var (kod + ^button-… etiketi). Bu düğmelerin "deposu".
2. Günlük not
Burada yalnızca kısa `button-sport` etiketi var — ve eklenti düğmeyi "depodan" koyar.

Neden bu kadar karmaşık? Uzun düğme kodunu her nota kopyalamamak için. Bir kez tanımladın — kısa bir etiketle istediğin kadar eklersin.

Bir düğme açıklaması nasıl görünür

Tüm düğmelerim tek bir MOC - Buttons (ya da sadece “Buttons”) notunda saklanır. İşte bir düğmenin açıklama örneği:

```button
name 💪 Antrenmanlar
type command
action QuickAdd: Antrenmanları aç
color black
class btn-inline
```
^button-sport

Satır satır inceleyelim:

nameDüğmede ne yazıyor (emojili olabilir).
type command"command" tipi — düğme bir Obsidian komutu başlatır.
actionTam olarak hangi komutun başlatılacağı (burada — QuickAdd'den bir seçim).
color / classGörünüm. btn-inline — kompakt satır içi düğme.
^button-sport⭐ En önemlisi: etiket (block id). Bu düğmenin "adresi".

^button-... ve metindeki etiket nedir

Kod bloğunun hemen altındaki ^button-sport satırı, Obsidian’da bir block id’dir (blok bağlantısı). Düğmeye benzersiz bir adres verir.

Bundan sonra, herhangi bir notta etiketi satır içi kod olarak (tek backtick içinde) yazmak yeterli:

`button-sport`

Buttons eklentisi bu etiketi görür, ^button-sport adresine göre gereken açıklamayı bulur ve yerine çalışan bir düğme çizer. Bir satıra arka arkaya birkaç etiket koyabilirsin — bir düğme sırası olur.

Kural basit:

^button-adı (“şapkalı”) — düğmenin tanımlandığı yer. `button-adı` (tırnak içinde) — düğmenin gösterildiği yer. button-’dan sonraki ad eşleşmeli.

Sıfırdan kendi düğmeni nasıl oluşturursun

1
"MOC - Buttons" notunda herhangi bir hazır ```button … ``` bloğunu kopyala.
2
name (etiket) ve action (hangi komutu başlatacağını) değiştir.
3
Altta benzersiz bir etiket belirle, örneğin ^button-water.
4
Gereken notta `button-water` yaz — ve düğme belirir.

Adım 6. Ana “Görev” düğmesi: günlük ve projelerin bağlantısı

”📋 Görev” düğmesi ana düğmelerden biri. Etiketi button-work-on-project ve QuickAdd üzerinden project-to-daily betiğini başlatır.

Önce görevlerin nereden geldiği hakkında. Tüm projelerim MOC - Projects notunda (PARA yapısına göre 1. Projects klasörü). Bu, Kanban eklentisinde bir kanban panosudur: sadece durumdan duruma sürüklenen görev kartları.

💡 Fikirler
🔄 Devam ediyor
Bitti

“Görev” düğmesi iki akıllı şey yapar:

  1. Projelerden görevleri günlüğe çeker. Kanban panonla bir pencere açılır, gereken kartları işaretlersin ve “Ekle”ye basarsın — “Gün için planlarım” bölümünde belirirler.
  2. Tamamlandığında görevleri pano boyunca taşır. Bir görevi günlükte doğrudan tamamlanmış (- [x]) işaretlediğinde, otomatik olarak kanbanın bir sonraki sütununa geçer (örn. “Devam ediyor”dan “Bitti”ye) ve nottan kaldırılır.

Bir "turbo modu" da var: "🏁 Sona" düğmesini açarsan (ya da göreve 🏁 simgesini eklersen), tamamlanınca doğrudan panonun en son sütununa gider.

Betikte kendine göre neyi değiştirmeli

Betik bende 0. Files/4. Templates/Scripts/project-to-daily_01.js’te. Onu kendine alırsan, en üstte sistemine göre ayarlaman gereken iki satır var:

const MOC_PATH = "1. Projects/MOC - Projects.md"; // ← SENİN kanban panonun yolu
const LAST_COLUMN_MARKER = "🏁";                   // ← "doğrudan son sütuna" simgesi
  • MOC_PATH — projelerinle ana kanban panonun yolunu belirt (nasıl adlandırıldığı ve hangi klasörde olduğu).
  • LAST_COLUMN_MARKER — “turbo modu” için işaret simgesi. 🏁 bırakabilir ya da kendi simgeni koyabilirsin.

Bir önemli nokta daha: betik görevleri nereye ekleyeceğini # Мои планы на день (Gün için planlarım) başlığına göre arar. Bu başlık günlük notunda olmalı — yoksa görevler sona eklenir.

Uzun uzun çözmek istemeyenler için

Hazır Obsidian şablonumu dene ve bilgini bugün sistematikleştirmeye başla

Şablon hakkında bilgi al

Adım 7. Tamamlanmamış görevleri otomatik taşıma

Şablonda, düğmelerin yanı sıra bir kod daha var — önceki günün tamamlanmamış görevlerini bugüne taşır. Templater eklentisiyle çalışır: yeni bir not oluşturulduğunda kod bir kez çalışır ve sıradan bir görev listesine dönüşür.

Mantık basit ve çok kullanışlı:

📄 Dünkü not
mevcut günden önceki son notu buluruz
🔍 "- [ ]" ararız
tüm kapatılmamış görevleri toplarız
📥 Bugün
onları yeni nota ekleriz

İşte şablondan bu kod (olduğu gibi yapıştırılır, bir şey değiştirmeye gerek yok — istersen günlük notlar klasörünün yolu hariç):

<%*
const moment = tp.obsidian.moment;
const fn = tp.file.title;
const date = moment(fn, 'DD-MM-YYYY');
 
// Pazar günleri bir yedekleme düğmesi ekleriz
if (date.isValid() && date.day() === 0) {
  tR += '- [ ] `button-local-backup`\n';
}
 
const pathToDailyNotes = "2. Areas/Дневники/Ежедневные заметки"; // ← senin yolun
const currentDate = moment(tp.file.title, 'DD-MM-YYYY');
const today = moment().startOf('day');
const referenceDate = currentDate.isAfter(today) ? today.clone().add(1, 'day') : currentDate;
 
function findLatestDailyNoteBeforeDate(beforeDate) {
  const folder = app.vault.getAbstractFileByPath(pathToDailyNotes);
  if (!folder || !folder.children) return null;
  const dailyFiles = folder.children
    .filter(file => {
      if (file.extension !== "md") return false;
      if (!file.name.match(/^\d{2}-\d{2}-\d{4}\.md$/)) return false;
      const fileDate = moment(file.name.replace('.md', ''), 'DD-MM-YYYY');
      return fileDate.isBefore(beforeDate) && fileDate.isSameOrBefore(today);
    })
    .sort((a, b) => {
      const dateA = moment(a.name.replace('.md', ''), 'DD-MM-YYYY');
      const dateB = moment(b.name.replace('.md', ''), 'DD-MM-YYYY');
      return dateB.valueOf() - dateA.valueOf();
    });
  return dailyFiles.length > 0 ? dailyFiles[0] : null;
}
 
if (!currentDate.isValid()) {
  tR += `❌ Dosya adından tarih belirlenemedi. Format: DD-MM-YYYY.`;
} else {
  const yesterday = referenceDate.clone().subtract(1, 'day').format('DD-MM-YYYY');
  let targetFile = app.vault.getAbstractFileByPath(`${pathToDailyNotes}/${yesterday}.md`);
  let targetDate = yesterday;
  if (!targetFile) {
    targetFile = findLatestDailyNoteBeforeDate(referenceDate);
    if (targetFile) targetDate = targetFile.name.replace('.md', '');
  }
  if (!targetFile) {
    tR += `❌ ${referenceDate.format('DD-MM-YYYY')} tarihinden önce günlük not yok.`;
  } else {
    const fileContent = await app.vault.read(targetFile);
    const tasks = fileContent.split("\n").filter(line => line.trim().startsWith("- [ ]"));
    if (tasks.length === 0) {
      tR += `✅ ${targetDate} için tamamlanmamış görev yok.`;
    } else {
      tR += `## 🔁 ${targetDate} tarihinden tamamlanmamış görevler (son not)\n\n`;
      tR += tasks.join("\n");
    }
  }
}
%>

Günlüğünde birkaç günlük bir ara olduysa, betik yine de mevcut günden önceki son notu bulur ve görevleri ondan çeker — hiçbir şey kaybolmaz. Yalnızca farklı bir klasörün varsa pathToDailyNotes'u değiştirmen gerekir.


Adım 8. Alışkanlık ve beslenme düğmeleri (Meta Bind)

Şablonda sonra alışkanlıklar gelir. Onlar, notun özelliklerini doğrudan metinden düzenlemeni sağlayan Meta Bind eklentisiyle çalışır — yukarı kaydırıp özellikler panelini açmaya gerek yok.

`INPUT[toggle:Спорт]` 🏃‍♂️ Spor
`INPUT[toggle:Чтение]` 📖 Okuma
`INPUT[toggle:Прогулка]` 🚶‍♂️ Yürüyüş

Burada INPUT[toggle:Спорт], Спорт özelliğine bağlı bir anahtardır. Notun gövdesinde anahtarı çevirdin — onay kutusu özelliklerde otomatik işaretlenir. Ve grafikler veriyi tam olarak özelliklerden aldığı için, alışkanlığın hemen istatistiğe girer.

Beslenme de aynı şekilde, yalnızca metin alanlarıyla kurulur:

🥚 **Kahvaltı:** `INPUT[text:Завтрак]`
🍕 **Öğle:** `INPUT[text:Обед]`
🥧 **Akşam:** `INPUT[text:Ужин]`
🥨 **Ara öğün:** `INPUT[text:Перекусы]`
 **Toplam:** `INPUT[text:Итого_ккал]`

`button-calories`

Sonda button-calories düğmesi var — ”🌮 Kalori hesapla”. Bu, beslenme alanlarına yazdıklarımdan AI ile kalori miktarını tahmin eden kişisel düğmem.

Her gün kusursuz doldurmak mümkün olmuyor — ve bu normal. Ama haftada birkaç dolu gün bile alışkanlık ve kalori grafiklerinde net bir dinamik verir.


Adım 9. Düşünceler — en önemli bölüm

Ve en önemlisi — şablonun en altında “Düşünceler” bölümü. Burada kod ya da şablon yok. Düşünmek için tamamen boş bir alan.

Buraya gün içinde yazarım:

  • gelecek için görevler ve fikirler;
  • beni endişelendiren sorunlar;
  • düşünceler ve gözlemler.

Bir görevi şu anda çözemiyorsam, kendime baskı yapmam. "Düşünceler"e onu neden üstlenemediğimi yazarım. Çoğu zaman beynin başka, dışsal bir göreve takılı olduğu ortaya çıkar — ve bunun farkına varmak donukluğu kendiliğinden kaldırır.

Bu düşünceler benim için sonrasında da çalışır:

  1. Ana sayfada. Yarın dünkü düşünceleri ana sayfadaki (Homepage) özel bir blokta görürüm.
  2. MOC - Дневники notunda. Orada tüm günlük notlardan düşünceleri toplayan ve onları aylara göre — gün gün — gösteren bir kod var. Onlardan yeni görevler ve atomik notlar doğar.
  3. Telefondan. Bir düşünceyi doğrudan bugünkü notun gereken bölümüne yazan bir widget ayarladım. Bir fikir sokakta geldiğinde vazgeçilmez.

Kod: tüm günlük notlardan tüm düşünceler aylara göre

Bu bloğu ayrı bir MOC - Дневники notuna yapıştırırım (bende 2. Areas/Дневники’de). Ayın tüm günlük notlarını gezer, her birinden “Düşünceler” bölümünü (ve varsa Мысль_дня ve Инсайт_дня özelliklerini) çıkarır ve onları liste olarak gösterir. ”← Önceki / Sonraki →” düğmeleri ayları gezer, ”🔽 Yeniler önce” sıralamayı değiştirir.

Kendine göre neyi değiştirmeli

Kodda günlük notlar klasörünün yoluyla bir satır var — kendi yolunu koy:

dv.pages('"2. Areas/Дневники/Ежедневные заметки"')

Ayrıca blok notlarda ## Мысли (Düşünceler) başlığını ve Дата (Tarih) özelliğini arar. Bölümün farklı adlandırılmışsa (örn. # Мысли) — yine de çalışır (1 ila 3 kare arar). Дата özelliği günlük notun özelliklerinde tarih formatında olmalı.

Bloğu bütün olarak kopyala — dataviewjs kelimesiyle başlayan satırdan kapatan backtick’lere kadar:

```dataviewjs
let currentDate = new Date();
let sortOrder = "desc";

const container = dv.el("div", "");

// Kontrol paneli
const controls = dv.el("div", "");
controls.style.cssText = `display: flex; align-items: center; gap: 8px; margin: 12px 0 20px 0; flex-wrap: wrap;`;

// Düğmeler için stil
function styleBtn(btn) {
  Object.assign(btn.style, {
    display: "inline-flex", "align-items": "center", "justify-content": "center",
    gap: "6px", padding: "8px 16px", "border-radius": "8px",
    border: "1px solid var(--background-modifier-border)",
    background: "var(--background-secondary)", color: "var(--text-normal)",
    cursor: "pointer", "font-size": "13px", "font-family": "inherit", "line-height": "1",
    transition: "background 0.15s, transform 0.1s, box-shadow 0.15s"
  });
  btn.onmouseenter = () => { btn.style.background = "var(--background-modifier-hover)"; btn.style.transform = "translateY(-1px)"; };
  btn.onmouseleave = () => { btn.style.background = "var(--background-secondary)"; btn.style.transform = "translateY(0)"; };
}

const spacer = dv.el("div", "");
spacer.style.cssText = "flex: 1;";

const prevBtn = dv.el("button", "⬅️ Önceki");
const nextBtn = dv.el("button", "Sonraki ➡️");
const sortBtn = dv.el("button", "🔽 Yeniler önce");
styleBtn(prevBtn); styleBtn(nextBtn); styleBtn(sortBtn);

controls.appendChild(prevBtn);
controls.appendChild(nextBtn);
controls.appendChild(spacer);
controls.appendChild(sortBtn);
container.appendChild(controls);

const contentDiv = dv.el("div", "");
container.appendChild(contentDiv);

async function renderMonth(date) {
  contentDiv.innerHTML = "";
  const start = new Date(date.getFullYear(), date.getMonth(), 1);
  const end = new Date(date.getFullYear(), date.getMonth() + 1, 0);

  const title = dv.el("h2", `${start.toLocaleDateString("tr", { month: "long", year: "numeric" })}`);
  title.style.cssText = "margin: 0 0 12px 0; font-size: 1.1em;";
  contentDiv.appendChild(title);

  // ↓↓↓ Yolu kendi günlük notlar klasörünle DEĞİŞTİR ↓↓↓
  const dailyNotes = dv.pages('"2. Areas/Дневники/Ежедневные заметки"')
    .where(p => {
      if (!p.Дата) return false;
      const d = new Date(p.Дата);
      return d >= start && d <= end;
    })
    .sort(p => p.Дата, sortOrder);

  for (const note of dailyNotes) {
    const content = await dv.io.load(note.file.path);
    const match = content.match(/#{1,3}\s*Мысли\s*\n([\s\S]*?)(?=\n#{1,3}\s|$)/i);
    const thoughtOfDay = note["Мысль_дня"];
    const insightOfDay = note["Инсайт_дня"];

    if (!match && !thoughtOfDay && !insightOfDay) continue;

    const block = dv.el("div", "");
    block.style.cssText = "border-bottom: 1px solid var(--background-modifier-border); padding: 8px 0;";

    block.appendChild(dv.el("h4", note.file.name));
    if (thoughtOfDay) block.appendChild(dv.el("p", `💭 Günün düşüncesi: ${thoughtOfDay}`));
    if (insightOfDay) block.appendChild(dv.el("p", `💡 İçgörü: ${insightOfDay}`));
    if (match) block.appendChild(dv.el("p", `📝 Düşünceler:\n${match[1].trim()}`));

    contentDiv.appendChild(block);
  }
}

prevBtn.onclick = () => { currentDate.setMonth(currentDate.getMonth() - 1); renderMonth(currentDate); };
nextBtn.onclick = () => { currentDate.setMonth(currentDate.getMonth() + 1); renderMonth(currentDate); };
sortBtn.onclick = () => {
  if (sortOrder === "desc") { sortOrder = "asc"; sortBtn.textContent = "🔼 Eskiler önce"; }
  else { sortOrder = "desc"; sortBtn.textContent = "🔽 Yeniler önce"; }
  renderMonth(currentDate);
};

await renderMonth(currentDate);
```
📷 Ekran görüntüsü: aylara göre düşünce listesi ve anahtar düğmeleriyle MOC - Дневники notu
(buraya bir görsel ekle)

Ana sayfa: alışkanlıklar ve düşünceler

Her sabah Obsidian benim için boş bir yerde değil, bir ana sayfada açılır (MOC - HOME notu, Homepage eklentisi). Onda en önemli iki şeyi hemen görürüm: bu ayın alışkanlık grafiği ve dünkü düşünceler. Böylece gün kısa bir “kendine bakışla” başlar.

Bu blok iki sekmeden oluşur — “Alışkanlıklar” ve “Düşünceler”. “Alışkanlıklar” sekmesi ay için bir tamamlama grafiği kurar (veriyi günlük notların özelliklerinden alır). “Düşünceler” sekmesi dünkü nottan “Düşünceler” bölümünü gösterir.

Kendine göre neyi değiştirmeli

Kodun başında günlük notlar klasörünün yoluyla bir satır var — kendi yolunu belirt:

const HABITS_FOLDER = "2. Areas/Дневники/Ежедневные заметки";

Ve habits dizisinde alışkanlıklarını listele — adlar şablondaki özellik adlarıyla tam eşleşmeli (Спорт, Чтение, Прогулка vb.).

Alışkanlık grafiği için Obsidian Charts eklentisi gerekir (window.renderChart fonksiyonunu sağlar). Onu diğerleri gibi kur: Gözat → "Charts" → Kur ve etkinleştir.

Bloğu bütün olarak kopyala — dataviewjs kelimesiyle başlayan satırdan kapatan backtick’lere kadar:

```dataviewjs
// ⚙️ AYARLAR — yolları ve alışkanlık listesini kendine göre değiştir
const { MarkdownRenderer } = require('obsidian');
const HABITS_FOLDER = "2. Areas/Дневники/Ежедневные заметки"; // ← senin günlük notlar klasörün
const habits = [
  { name: "Spor",    key: "Спорт" },
  { name: "Okuma",   key: "Чтение" },
  { name: "Yürüyüş", key: "Прогулка" }
];

// 📅 Mevcut ay
const now       = new Date();
const year      = now.getFullYear();
const month     = now.getMonth() + 1;
const pad       = n => String(n).padStart(2, "0");
const monthStr  = pad(month);
const totalDays = new Date(year, month, 0).getDate();
const MONTH_NAMES = ["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"];
const monthName = MONTH_NAMES[month - 1];

// 📅 Dünkü tarih ("Düşünceler" bölümü için)
const yesterday = new Date(now);
yesterday.setDate(yesterday.getDate() - 1);
const yFileName = `${pad(yesterday.getDate())}-${pad(yesterday.getMonth() + 1)}-${yesterday.getFullYear()}`;
const yFilePath = `${HABITS_FOLDER}/${yFileName}.md`;

// 🛠️ Yardımcılar
const asBool = v => v === true || v === "true" || v === 1;
function gradientColor(pct) {
  let r, g, b = 0;
  if (pct < 50) { r = 255; g = Math.round(255 * pct / 50); }
  else          { g = 255; r = Math.round(255 - 255 * (pct - 50) / 50); }
  return `rgb(${r},${g},${b})`;
}

// 🚀 Render
let viewMode = "habits";

async function render() {
  this.container.innerHTML = "";

  const tabs = this.container.createEl("div");
  tabs.style.cssText = "display:flex; gap:8px; margin-bottom:14px; flex-wrap:wrap;";
  const makeTab = (label, mode) => {
    const active = viewMode === mode;
    const btn = tabs.createEl("button", { text: label });
    btn.style.cssText = "padding:6px 16px; border-radius:6px; cursor:pointer; border:1px solid var(--interactive-accent); " +
      (active ? "background:var(--interactive-accent); color:var(--text-on-accent); font-weight:600;"
              : "background:transparent; color:var(--text-normal);");
    btn.addEventListener("click", () => { if (viewMode !== mode) { viewMode = mode; render.call(this); } });
  };
  makeTab("Alışkanlıklar", "habits");
  makeTab("Düşünceler",    "thoughts");

  const box = this.container.createEl("div");

  // ── Alışkanlıklar ──────────────────────────────────────────────
  if (viewMode === "habits") {
    let pages = dv.pages(`"${HABITS_FOLDER}"`).where(p => {
      if (p.date) { const d = dv.date(p.date); return d && d.year === year && d.month === month; }
      const n = p.file.name;
      return n.includes(`-${monthStr}-${year}`) || n.includes(`${year}-${monthStr}-`);
    });
    if (pages.length === 0) { box.createEl("p", { text: `${monthStr}.${year} için veri yok.` }); return; }

    const counts   = habits.map(h => pages.filter(p => asBool(p[h.key])).length);
    const percents = counts.map(c => Math.round((c / totalDays) * 100));
    window.renderChart({
      type: "bar",
      data: {
        labels: habits.map(h => h.name),
        datasets: [{
          label: `${monthStr}.${year} tamamlama (${totalDays} günden)`,
          data: percents,
          backgroundColor: percents.map(p => gradientColor(p)),
          borderRadius: 4,
        }]
      },
      options: {
        indexAxis: "y",
        scales: {
          x: { min: 0, max: 100, ticks: { callback: v => v + "%" }, title: { display: true, text: "Yüzde" } },
          y: { title: { display: true, text: "Alışkanlıklar" } }
        },
        plugins: {
          legend: { display: false },
          tooltip: { callbacks: { label: ctx => `${ctx.raw}% (${totalDays} günden ${counts[ctx.dataIndex]})` } },
          title: { display: true, text: `Alışkanlıklar — ${monthName} ${year}` }
        }
      }
    }, box);

  // ── Düşünceler (dünkü nottan) ─────────────────────────
  } else if (viewMode === "thoughts") {
    const tfile = app.vault.getAbstractFileByPath(yFilePath);
    box.createEl("div", { attr: { style: "font-weight:600; margin-bottom:10px; color:var(--text-muted);" } })
       .setText(`Düşünceler — dün (${yFileName})`);
    if (!tfile) { box.createEl("p", { text: `Not bulunamadı: ${yFileName}`, attr: { style: "color:var(--text-muted);" } }); return; }

    const content = await app.vault.read(tfile);
    const match = content.match(/^#{1,6}\s*Мысли\s*$/m);
    if (!match) {
      box.createEl("p", { text: "Notta 'Düşünceler' bölümü bulunamadı.", attr: { style: "color:var(--text-muted);" } });
    } else {
      const startIdx    = content.indexOf(match[0]) + match[0].length;
      const afterText   = content.slice(startIdx);
      const nextHeading = afterText.match(/\n#{1,6}\s/);
      const thoughtsRaw = nextHeading ? afterText.slice(0, nextHeading.index).trim() : afterText.trim();
      if (thoughtsRaw) {
        const card = box.createEl("div", { attr: { style: "background:var(--background-secondary); border-left:3px solid var(--interactive-accent); border-radius:6px; padding:12px 14px; line-height:1.75; max-height:320px; overflow-y:auto;" } });
        await MarkdownRenderer.render(app, thoughtsRaw, card, yFilePath, this.component);
      } else {
        box.createEl("p", { text: "'Düşünceler' bölümü boş.", attr: { style: "color:var(--text-muted);" } });
      }
    }
    const linkWrap = box.createEl("div", { attr: { style: "margin-top:10px;" } });
    linkWrap.createEl("a", {
      text: `${yFileName} — Düşünceler aç`, cls: "internal-link",
      attr: { href: `${yFileName}#Мысли`, "data-href": `${yFileName}#Мысли`, style: "font-size:0.85em; color:var(--interactive-accent); text-decoration:none;" }
    });
  }
}
render.call(this);
```
📷 Ekran görüntüsü: "Alışkanlıklar" ve "Düşünceler" sekmeleriyle ana sayfa
(buraya bir görsel ekle)

Uzun uzun çözmek istemeyenler için

Hazır Obsidian şablonumu dene ve bilgini bugün sistematikleştirmeye başla

Şablon hakkında bilgi al

Kâğıt günlükler de sistemde

Kâğıttan tamamen vazgeçmedim — bazen elle yazmak hoş. Sistemimde bunun için bir düğme var — ”📸 Fotoğraftan metne” (etiket button-image-2-text, betik image-to-text).

Mantık basit: kâğıt defterin bir sayfasını fotoğraflarım → düğme el yazısı metni AI ile tanır → onu günlük nota kopyalayabilir ya da ondan yeni bir not oluşturabilirim.

📓 Kâğıt sayfa
📸 Fotoğraftan metne (AI)
📝 Notta metin

Ayrıca elle şema çizmeyi de severim — ve böyle herhangi bir çizim doğrudan nota kolayca eklenir (Excalidraw eklentisiyle ya da aynı çizim düğmesiyle). Yani Obsidian’da günlük tutmak işlevsellikle sınırlı değil: kâğıt, çizimler, ses, fotoğraf — her şey tek bir yerde toplanır.


Sonuç

İşte tüm sistem. Büyük ölçekli görünüyor ama basit yapı taşlarından kuruluyor:

1.Eklentiler: Dataview, Meta Bind, Homepage, Templater, Buttons, QuickAdd.
2.Yerleşik "Günlük Notlar" + Areas (PARA) klasöründe bir şablon.
3.Alışkanlıklar ve beslenme için özellikler (YAML).
4.scripts.google.com üzerinden Google Calendar widget'ı.
5.Günlüğü projelerle bağlayan düğmeler ve betik.
6.Görevlerin otomatik taşınması, alışkanlıklar, beslenme ve düşünceler bölümü.

Ana tavsiye: her şeyi bir anda uygulama. Etkinleştirilmiş günlük notlar ve bir sabah ritüeli düğmesiyle başla. Bu bir alışkanlık olunca — görev taşımayı, sonra takvimi, sonra projeleri ekle. Sistem beyni yüklememeli, boşaltmalı.

Sonraki materyallerde, kendime kitap okumak için nasıl bir eklenti yaptığımı (parçaları seçip onlardan notlar oluşturuyorum) ve okuma sürecinde doğrudan AI’dan bilgiyi nasıl netleştirdiğimi göstereceğim.

Uzun uzun çözmek istemeyenler için

Hazır Obsidian şablonumu dene ve bilgini bugün sistematikleştirmeye başla

Şablon hakkında bilgi al

© 2026 Elton Labs. Tüm hakları saklıdır.