Введение
Около двух лет я использую Obsidian как основное приложение для ведения заметок, планирования и написания статей. В этой статье я хочу поделиться своим полным workflow: от распределения заметок по папкам и горячих клавиш до детального Cheatsheet по хранилищу и организации метода Zettelkasten.
Сразу уточню: Obsidian становится действительно удобным только тогда, когда человек сам собирает под себя хранилище и находит подходящий ему метод. Ниже я разбираю реализацию по частям, чтобы каждый мог изучить интересующий блок, взять полезные идеи или настроить всё аналогично у себя.
Ниже — краткий план того, о чём будет статья:
Архитектура папок (где и что хранится, а также подробный
Cheatsheet.md, который я составлял для себя).Плагины, которые я использую.
Настройка Homepage и каталога книг.
Синхронизация ПК + телефон (плагин Git + Termux на телефоне, у меня репозиторий в Gitea).
Архитектура
Это исчерпывающее руководство по моей системе заметок и записей (Obsidian и Habitica). Если я что-то забуду — вся информация здесь.
Obsidian
Термины и правила
Файлы-якоря (taglinks) — замена тегов в их привычном понимании. Смысл в том, что это те же теги, но в виде отдельных файлов. Их преимущество — явная наглядность и возможность добавить внутреннюю логику (например, указать прямые ссылки на другие файлы для быстрого поиска или расписать описание самого тега). Имеют вид
[[Мой якорь]], где скобки обозначают ссылку на файл.Индекс (index) — taglink с расширенной внутренней логикой. Как правило, у такого index-файла много связей с другими «полноценными» заметами. В начале имени любого индекса ставится
00, а название пишется с большой буквы. Например, taglink[[физика]]превращается в[[00 Физика]]. Это нужно для того, чтобы с первого взгляда отделить индекс от обычного taglink.-
Теги (tags) — классические теги с решёткой (например:
#тег). Используются для неявного указания свойств файла. Я указываю тип файла (#plan,#note,#zettel,#book,#index) для быстрого поиска. Если это#zettel-файл, я добавляю теги прогресса#baby,#teen,#adult:#baby— заметка только на стадии зарождения;#teen— заметка в процессе написания;#adult— заметка самодостаточна и всегда полезна (вечнозелёная).
Важно помнить: даже если заметка уже «выросла», её всё равно можно дополнять. Для этого создаётся новый файл со ссылкой на старый, который раскрывает тему дальше или с другого ракурса.
Типы файлов
note— для простых и оперативных записей (которые со временем могут потерять актуальность);plan— для планов, программ и проектов;zettel— для постоянных знаний в Zettelkasten (статусы:#baby,#teen,#adult);book— для конспектов и карточек книг;index— для индексов.
Файловая структура
_files
Здесь хранятся все медиафайлы, используемые в заметках (фотографии, схемы, рисунки и т.д.).
_templates
Здесь хранятся шаблоны для разных типов файлов.
-
[[Book temp]]— шаблон для книг в папкеBooks. Состоит из:title(название книги),cover(ссылка на обложку),author(автор),genre(жанр),tags(#book),taglinks(ссылки на файлы-якоря),status(статус: прочитана / читаю / в планах),current_page(текущая страница),total_pages(всего страниц),date_started(дата начала чтения),date_ended(дата окончания чтения),other_internal_links(дополнительные ссылки на связанные файлы; по умолчанию стоит ссылка на каталог книг),other_external_links(дополнительные ссылки на внешние ресурсы).
-
[[Index temp]]— шаблон для индексов в папкеIndexes. Состоит из:created_at(дата и время создания),tags(#index),other_internal_links(дополнительные внутренние ссылки),other_external_links(дополнительные внешние ссылки).
-
[[Note temp]]— шаблон для заметок в папкеPlans & Notes. Состоит из:created_at(дата и время создания),tags(#note),taglinks(ссылки на файлы-якоря),other_internal_links(дополнительные внутренние ссылки),other_external_links(дополнительные внешние ссылки).
-
[[Plan temp]]— шаблон для планов и программ в папкеPlans & Notes. Состоит из:created_at(дата и время создания),tags(#plan),taglinks(ссылки на файлы-якоря),other_internal_links(дополнительные внутренние ссылки),other_external_links(дополнительные внешние ссылки).
-
[[Zettel temp]]— шаблон для записей в папкеZettelkasten. Состоит из:created_at(дата и время создания),tags(#zettelи#baby, который затем меняется на#teenи#adultпо мере готовности),taglinks(ссылки на файлы-якоря),other_internal_links(дополнительные внутренние ссылки),other_external_links(дополнительные внешние ссылки).
Taglinks
Папка для хранения всех файлов-якорей.
Indexes
Хранилище всех индексов (файлов с внутренней логикой). Позволяет быстро находить нужные темы через систему связей.
Plans & Notes
Здесь хранятся все планы, программы (
plans) и обычные заметки (notes). Отдельная папка нужна, чтобы не засорять основную базу, так как эти записи не имеют бесконечной ценности.
Zettelkasten
Главная база знаний. Сюда попадают идеи и материалы, содержащие ценные умозаключения, которые пригодятся в будущем.
Главный критерий: «Хотел бы я, чтобы эта информация осталась со мной надолго?». Если ответ «да» — материал ценен и его нужно зафиксировать.
-
Rough Notes (Черновики):
Что это: Папка для «сырых» и только зарождающихся заметок. Все записи в Zettelkasten начинаются отсюда.
Что внутри: Заметки с потенциалом, еще не получившие законченную форму. Это «рассада» моей базы знаний.
Критерий: Если заметка неполная или требует доработки — она остаётся здесь.
-
Grown Notes (Выросшие заметки):
Что это: Основное хранилище ценных и сформированных заметок.
Что внутри: Доработанные записи с законченной мыслью, понятные без стороннего контекста.
Критерий: Как только заметка становится самодостаточной, я перемещаю её из
Rough NotesвGrown Notes.
Books
Папка для прочитанных книг. Главный файл — Каталог, в котором наглядно отображаются все книги.
Создаётся файл с названием книги, применяется и заполняется шаблон. Ниже заголовка можно писать краткие мысли. Если требуется полноценный разбор книги, создаётся отдельный файл, который отправляется в
Zettelkasten.
Остальные файлы
[[Cheatsheet.md]]— исчерпывающая шпаргалка по системе (этот файл);[[Homepage.md]]— домашняя страница с ключевыми ссылками;[[Inbox.md]]— файл для быстрых заметок и невыполненных за день дел;Bookmarks — встроенные закладки Obsidian для мгновенного доступа к частым файлам.
Основные горячие клавиши
Alt + S— вставка шаблонаAlt + Q— вставка CalloutCtrl + O— открыть Quick SwitcherCtrl + P— открыть Command PaletteCtrl + E— переключить режим просмотра (Current View)Ctrl + ЛКМ— открыть ссылку в новой вкладкеCtrl + Shift + F— поиск по всем файламCtrl + ↑— переместить строку вверхCtrl + ↓— переместить строку внизAlt + 1— замена сниппета (Snippet Replacement)Alt + A— свернуть все списки и заголовкиAlt + D— развернуть все списки и заголовки
Как правильно записывать информацию?
Найти интересный материал.
Прочитать и разбирать его до полного понимания.
Закрыть источник и записать суть в Obsidian в удобном формате (рисунок, таблица, список, текст).
Задать себе вопросы: «Будет ли польза от этой заметки в будущем?» и «В каком конкретном сценарии я это применю?». Если ответы положительные — оставляем.
Проставить ссылки (
taglinks,other_internal_links), теги и проверить связность с другими файлами (если это не#index).Открыть первоисточник и сверить точность записей, при необходимости скорректировать.
Перечитать заметку и проверить, понятен ли материал. Если есть пробелы — повторить шаг 6, пока заметка не станет на 100% понятной и автономной.
При возникновении сопутствующих вопросов создать новую связанную заметку и пройти алгоритм с 1-го пункта.
Habitica
Привычки (habits)
Регулярные или пассивные действия, которые выполняются в течение дня.
Дела (tasks)
Быстрые разовые задачи с коротким сроком жизни (1–2 дня): загрузить посудомойку, помыть пол и т.д.
Ежедневные дела (recurring tasks)
Обязательные регулярные задачи, формирующие распорядок дня.
Отложенные (deferred)
Задачи на перспективу («когда-нибудь»). Находятся в мобильном приложении (HabitNow / Habitica) для оперативного доступа с телефона. Задачи из Obsidian
Inboxкасаются именно рабочих процессов за ПК, поэтому их удобнее вести за компьютером.
Плагины, которые я использую
Better Word Count — подсчёт слов и символов.
Commander — кастомизация интерфейса и добавление быстрых команд.
Dataview — агрегация и отображение сложных данных через запросы.
Excalidraw — рукописные схемы и подготовка к экзаменам на графическом планшете.
Git — автоматическая синхронизация с репозиторием.
Homepage — настройка стартовой домашней страницы.
Ink — быстрое создание рукописных заметок.
List Callouts — стильное оформление списков и акцентов.
Templater — расширенная работа с шаблонами и скриптами.
Text Snippets — автозамена текста на заранее заготовленные шаблоны.
Настройка Homepage
Файл домашней страницы (Homepage.md):
--- cssclasses: dashboard --- <div class="fade-banner"> <img src="_files/sandpile.jpg" alt="Banner"> <div class="banner-gradient"></div> </div> # ?️ My Dashboard - ## ? [[3 - Plans & Notes/NetDevSecOps.canvas|NetDevSecOps]] - ## ? [[5 - Books/00 Каталог.md|Каталог книг]] - ## ? [[Inbox]] --- - ### ?️ Тренировки - [[Тренировки зал full-body]] - [[3 - Plans & Notes/Тренировки лето новые.md|Тренировки лето]] - [[Доп. Тренировки (3 в неделю)]] - ### ? Цели и Планы - [[3 - Plans & Notes/Цели на 2026.md|Цели на 2026]] - [[3 - Plans & Notes/Еженедельный план 2026.md|Еженедельный план 2026]] - [[2 - Indexes/00 Хочу.md|Все что я хочу]] - ### ? Полезные материалы - [[Interview Questions|Вопросы DevOps Advanced]] - [[DevOps Questions Basic Level|Вопросы DevOps Basic]] - [[Механизм минимальных затрат]]
CSS-сниппет для оформления панели (простой стиль без лишних элементов):
.fade-banner { position: relative; width: 100%; height: 200px; overflow: hidden; margin-bottom: 25px; border-radius: 8px; } .fade-banner img { width: 100%; height: 100%; object-fit: cover; } .banner-gradient { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to bottom, transparent 50%, var(--background-primary) 100%); } .dashboard { font-family: inherit; padding-left: 25px !important; padding-right: 25px !important; padding-top: 20px !important; } .dashboard .markdown-preview-section { max-width: 100%; } .dashboard h1 { font-size: 2em; font-weight: 600; margin-bottom: 20px; } .dashboard div>ul>li>b, .dashboard div>ul>li>strong { display: block; font-size: 1.2em; font-weight: 600; margin-bottom: 12px; color: var(--text-normal); } .dashboard div>ul>li { background-color: transparent !important; border: none !important; box-shadow: none !important; padding: 10px !important; } .dashboard div>ul { list-style: none; display: flex; column-gap: 40px; row-gap: 25px; flex-flow: row wrap; padding-left: 0px !important; } .dashboard div>ul>li { min-width: 260px; flex: 1; } .dashboard div.markdown-preview-section>div>ul>li>.list-bullet { display: none !important; } .dashboard.markdown-rendered.show-indentation-guide li>ul::before, .dashboard.markdown-rendered.show-indentation-guide li>ol::before { display: none; } div.markdown-preview-section>div>ul.has-list-bullet>li { padding-left: 0px !important; } .dashboard ul.dataview { row-gap: 0px !important; list-style-type: disc !important; } .dashboard-welcome { font-size: 1.25em; font-weight: 800; letter-spacing: 7px; text-transform: uppercase; color: #FFFFFF !important; text-shadow: 0px 2px 4px rgba(255, 255, 255, 0.6), 0px 4px 10px rgba(0, 0, 0, 0.4); margin-bottom: -15px; opacity: 1; text-align: center; display: block; }
Настройка каталога книг
Основной файл каталога (работает на dataviewjs):
const bookPages = dv.pages('"5 - Books"').where(p => p.title); const container = this.container; const style = document.createElement("style"); style.textContent = ` .book-table { width: 100%; border-collapse: collapse; font-family: Cascadia Mono, monospace; margin-top: 1rem; font-size: 15px; } .book-table th { background: rgba(138, 43, 226, 0.15); color: #d6bcfa; padding: 12px 14px; border-bottom: 2px solid rgba(214, 188, 250, 0.3); font-weight: 600; text-align: left; } .book-table td { padding: 12px 14px; border-bottom: 1px solid rgba(214, 188, 250, 0.15); color: #e9d8fd; vertical-align: middle; } .book-table tr { transition: all 0.2s ease; } .book-table tr:hover { background: rgba(138, 43, 226, 0.12) !important; } .filter-container { background: rgba(138, 43, 226, 0.1); backdrop-filter: blur(10px); border-radius: 12px; padding: 1.2rem; margin-bottom: 2rem; border: 1px solid rgba(214, 188, 250, 0.2); display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; } .filter-select, .filter-search { padding: 10px 14px; border-radius: 10px; border: 1px solid rgba(214, 188, 250, 0.3); background: rgba(26, 26, 32, 0.8); color: #e9d8fd; font-size: 14px; outline: none; transition: all 0.2s ease; height: 40px; box-sizing: border-box; font-family: Cascadia Mono, monospace; } .filter-select:hover, .filter-search:focus { border-color: rgba(214, 188, 250, 0.6); box-shadow: 0 0 0 4px rgba(138, 43, 226, 0.15); } .filter-search { flex: 1; min-width: 250px; } .book-title-link { color: #d6bcfa; text-decoration: none; font-weight: 600; font-size: 16px; transition: color 0.2s; line-height: 1.3; } .book-title-link:hover { color: #e9d8fd; } .book-meta-text { font-size: 12px; color: rgba(214, 188, 250, 0.7); margin-top: 3px; } .status-dropdown { padding: 4px 10px; border-radius: 14px; font-size: 13px; font-weight: 600; border: 1px solid transparent; outline: none; cursor: pointer; transition: all 0.2s; width: 130px; text-align: center; height: 36px; box-sizing: border-box; font-family: Cascadia Mono, monospace; } .page-num-input { width: 55px; background: rgba(138, 43, 226, 0.15); border: 1px solid rgba(214, 188, 250, 0.3); color: #e9d8fd; border-radius: 6px; padding: 4px 6px; text-align: center; font-size: 13px; font-family: Cascadia Mono, monospace; outline: none; transition: all 0.2s; box-sizing: border-box; } .page-num-input:focus { border-color: rgba(214, 188, 250, 0.6); background: rgba(26, 26, 32, 0.9); box-shadow: 0 0 0 3px rgba(138, 43, 226, 0.2); } .page-num-input::-webkit-outer-spin-button, .page-num-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } .page-num-input { -moz-appearance: textfield; } .progress-bar-container { background: rgba(214, 188, 250, 0.15); border-radius: 12px; height: 6px; width: 100%; overflow: hidden; } .progress-bar-fill { background: linear-gradient(90deg, #8A2BE2, #9370DB); height: 100%; transition: width 0.3s ease; } .book-cover-img { width: 75px; height: 108px; border-radius: 8px; object-fit: cover; box-shadow: 0 6px 14px rgba(0,0,0,0.4); border: 1px solid rgba(214, 188, 250, 0.2); transition: transform 0.2s; cursor: pointer; } .book-cover-img:hover { transform: scale(1.05); } .total-page-label { font-size: 12px; color: rgba(214, 188, 250, 0.8); white-space: nowrap; } /* Мобильная оптимизация */ @media (max-width: 600px) { .book-table th, .book-table td { padding: 8px 6px; font-size: 13px; } .book-cover-img { width: 50px; height: 72px; } .book-title-link { font-size: 14px; } .book-meta-text { font-size: 11px; } .status-dropdown { width: 105px; font-size: 12px; height: 32px; padding: 2px 4px; } .page-num-input { width: 45px; font-size: 12px; padding: 3px 2px; } .total-page-label { font-size: 11px; } .filter-container { padding: 0.8rem; flex-direction: column; align-items: stretch; gap: 0.6rem; } .filter-select, .filter-search { width: 100%; } } `; document.head.appendChild(style); const filterContainer = document.createElement("div"); filterContainer.className = "filter-container"; const genreSelect = document.createElement("select"); genreSelect.className = "filter-select"; const allOption = document.createElement("option"); allOption.textContent = "Все жанры"; allOption.value = ""; genreSelect.appendChild(allOption); const allGenres = new Set(); for (let p of bookPages) { if (p.genre) { const genres = Array.isArray(p.genre) ? p.genre : [p.genre]; genres.forEach(g => g && allGenres.add(g)); } } for (let genre of Array.from(allGenres).sort()) { const opt = document.createElement("option"); opt.textContent = genre; opt.value = genre; opt.style.background = "#1a1a20"; genreSelect.appendChild(opt); } filterContainer.appendChild(genreSelect); const statusSelect = document.createElement("select"); statusSelect.className = "filter-select"; const statusOptions = [ { value: "", text: "Все статусы" }, { value: "reading", text: "Читаю" }, { value: "completed", text: "Прочитано" }, { value: "planned", text: "В планах" } ]; statusOptions.forEach(o => { const opt = document.createElement("option"); opt.textContent = o.text; opt.value = o.value; opt.style.background = "#1a1a20"; statusSelect.appendChild(opt); }); filterContainer.appendChild(statusSelect); const searchInput = document.createElement("input"); searchInput.type = "text"; searchInput.className = "filter-search"; searchInput.placeholder = "? Поиск по названию или автору..."; filterContainer.appendChild(searchInput); container.appendChild(filterContainer); function determineBookStatus(page) { if (page.status) return page.status; const today = new Date().toISOString().split('T')[0]; if (page.date_ended && page.date_ended <= today) return "completed"; if (page.date_started) return "reading"; const total = page.total_pages || 100; const current = page.current_page || 0; if (total > 0 && current >= total) return "completed"; if (page.current_page && page.current_page > 0) return "reading"; return "planned"; } function applyStatusStyle(selectElement, status) { if (status === "completed") { selectElement.style.background = "rgba(102, 221, 170, 0.15)"; selectElement.style.color = "#66ddaa"; selectElement.style.borderColor = "rgba(102, 221, 170, 0.25)"; } else if (status === "reading") { selectElement.style.background = "rgba(147, 112, 219, 0.15)"; selectElement.style.color = "#9370db"; selectElement.style.borderColor = "rgba(147, 112, 219, 0.25)"; } else { selectElement.style.background = "rgba(214, 188, 250, 0.15)"; selectElement.style.color = "#d6bcfa"; selectElement.style.borderColor = "rgba(214, 188, 250, 0.25)"; } } async function updatePageProperty(page, property, value) { try { const file = app.vault.getAbstractFileByPath(page.file.path); if (!file) return false; await app.fileManager.processFrontMatter(file, (fm) => { if (value === undefined || value === "") { delete fm[property]; } else { fm[property] = value; } }); page[property] = value; return true; } catch (e) { console.error(e); return false; } } async function removePageProperty(page, property) { try { const file = app.vault.getAbstractFileByPath(page.file.path); if (!file) return false; await app.fileManager.processFrontMatter(file, (fm) => { delete fm[property]; }); delete page[property]; return true; } catch (e) { console.error(e); return false; } } function renderTable(selectedGenre = "", selectedStatus = "", searchTerm = "") { const oldTable = container.querySelector(".book-table"); if (oldTable) oldTable.remove(); const table = document.createElement("table"); table.className = "book-table"; const header = table.insertRow(); ["Обложка", "Книга", "Статус", "Прогресс"].forEach(t => { const th = document.createElement("th"); th.textContent = t; header.appendChild(th); }); for (let p of bookPages) { const genreMatch = !selectedGenre || (p.genre && ((Array.isArray(p.genre) && p.genre.includes(selectedGenre)) || p.genre === selectedGenre)); const actualStatus = determineBookStatus(p); const statusMatch = !selectedStatus || actualStatus === selectedStatus; const searchMatch = !searchTerm || (p.title && p.title.toLowerCase().includes(searchTerm.toLowerCase())) || (p.author && p.author.toLowerCase().includes(searchTerm.toLowerCase())); if (!(genreMatch && statusMatch && searchMatch)) continue; let total = p.total_pages || 100; let current = p.current_page || 0; let percent = total > 0 ? Math.round((current / total) * 100) : 0; const row = table.insertRow(); row.onclick = (e) => { if (!e.target.closest('a') && !e.target.closest('select') && !e.target.closest('input') && !e.target.closest('img')) { window.location.href = p.file.path; } }; const cellCover = row.insertCell(); if (p.cover) { const img = document.createElement("img"); img.src = p.cover; img.className = "book-cover-img"; img.onclick = () => window.location.href = p.file.path; cellCover.appendChild(img); } else { const placeholder = document.createElement("div"); placeholder.className = "book-cover-img"; placeholder.style.background = "rgba(138, 43, 226, 0.12)"; placeholder.style.display = "flex"; placeholder.style.alignItems = "center"; placeholder.style.justifyContent = "center"; placeholder.style.fontSize = "22px"; placeholder.style.border = "1px dashed rgba(214, 188, 250, 0.2)"; placeholder.innerHTML = "?"; placeholder.onclick = () => window.location.href = p.file.path; cellCover.appendChild(placeholder); } const cellInfo = row.insertCell(); const infoWrapper = document.createElement("div"); infoWrapper.style.display = "flex"; infoWrapper.style.flexDirection = "column"; const link = document.createElement("a"); link.href = p.file.path; link.textContent = p.title || p.file.name; link.className = "internal-link book-title-link"; const metaText = document.createElement("div"); metaText.className = "book-meta-text"; const author = p.author || "Автор не указан"; const genre = Array.isArray(p.genre) ? p.genre.join(", ") : (p.genre || ""); metaText.textContent = author + (genre ? ` • ${genre}` : ""); infoWrapper.appendChild(link); infoWrapper.appendChild(metaText); cellInfo.appendChild(infoWrapper); const cellStatus = row.insertCell(); const sel = document.createElement("select"); sel.className = "status-dropdown"; const opts = [ { value: "planned", text: "? В планах" }, { value: "reading", text: "? Читаю" }, { value: "completed", text: "✓ Готово" } ]; opts.forEach(o => { const opt = document.createElement("option"); opt.value = o.value; opt.textContent = o.text; opt.style.background = "#1a1a20"; if (o.value === actualStatus) opt.selected = true; sel.appendChild(opt); }); applyStatusStyle(sel, actualStatus); cellStatus.appendChild(sel); sel.onchange = async () => { const newStatus = sel.value; applyStatusStyle(sel, newStatus); if (newStatus !== actualStatus) { let success = await updatePageProperty(p, "status", newStatus); if (success) { if (actualStatus === "completed" && newStatus !== "completed") { const newCurrent = Math.max(0, Math.floor(total * 0.9)); await updatePageProperty(p, "current_page", newCurrent); await removePageProperty(p, "date_ended"); } else if (newStatus === "completed") { await updatePageProperty(p, "current_page", total); await updatePageProperty(p, "date_ended", new Date().toISOString().split('T')[0]); } renderTable(genreSelect.value, statusSelect.value, searchInput.value); } } }; const cellProgress = row.insertCell(); const progressWrapper = document.createElement("div"); progressWrapper.style.display = "flex"; progressWrapper.style.flexDirection = "column"; progressWrapper.style.gap = "6px"; progressWrapper.style.minWidth = "120px"; const barContainer = document.createElement("div"); barContainer.className = "progress-bar-container"; const barFill = document.createElement("div"); barFill.className = "progress-bar-fill"; barFill.style.width = `${percent}%`; barContainer.appendChild(barFill); progressWrapper.appendChild(barContainer); const inputRow = document.createElement("div"); inputRow.style.display = "flex"; inputRow.style.alignItems = "center"; inputRow.style.gap = "4px"; inputRow.style.justifyContent = "flex-end"; const numInput = document.createElement("input"); numInput.type = "number"; numInput.className = "page-num-input"; numInput.value = current; numInput.min = 0; numInput.max = total; const label = document.createElement("span"); label.className = "total-page-label"; label.textContent = `/${total} (${percent}%)`; inputRow.appendChild(numInput); inputRow.appendChild(label); progressWrapper.appendChild(inputRow); cellProgress.appendChild(progressWrapper); const saveProgressValue = async () => { let val = parseInt(numInput.value); if (isNaN(val)) val = current; val = Math.max(0, Math.min(val, total)); if (val !== current) { let success = await updatePageProperty(p, "current_page", val); if (success) { if (val >= total) { await updatePageProperty(p, "status", "completed"); await updatePageProperty(p, "date_ended", new Date().toISOString().split('T')[0]); } else if (actualStatus === "completed" && val < total) { await updatePageProperty(p, "status", "reading"); await removePageProperty(p, "date_ended"); } else if (actualStatus === "planned" && val > 0) { await updatePageProperty(p, "status", "reading"); await updatePageProperty(p, "date_started", new Date().toISOString().split('T')[0]); } renderTable(genreSelect.value, statusSelect.value, searchInput.value); } } else { numInput.value = current; } }; numInput.onblur = saveProgressValue; numInput.onkeydown = (ev) => { if (ev.key === "Enter") numInput.blur(); if (ev.key === "Escape") { numInput.value = current; numInput.blur(); } }; } container.appendChild(table); } genreSelect.onchange = () => renderTable(genreSelect.value, statusSelect.value, searchInput.value); statusSelect.onchange = () => renderTable(genreSelect.value, statusSelect.value, searchInput.value); searchInput.oninput = () => renderTable(genreSelect.value, statusSelect.value, searchInput.value); renderTable();
Синхронизация ПК и смартфона (Git + Termux + Gitea)
Для независимой синхронизации без сторонних платных сервисов я использую связку Git, собственный инстанс Gitea и Termux на Android:
На ПК: В самом Obsidian настроен плагин
Obsidian Git. Он автоматически коммитит и отправляет (push) изменения в мой закрытый репозиторий на Gitea при закрытии программы или каждые 10–15 минут.-
На телефоне:
Настроен Termux с установленным пакетом
gitи SSH-ключами для доступа к Gitea.Синхронизацию я запускаю через комманду (alias)
gsyncв ~/.zshrc (или ~/.bashrc), которая делает сначала pull, потом push репозитория. Да, приходится заходить в терминал и писать gsync, но меня пока что устраивает (alias gsync="cd ~/storage/shared/Obsidian/Vault && git pull origin main && git add . && git commit -m 'mobile auto-sync' && git push origin main")Также уточню, что git-crypt я не использую, так как репозиторий находится в моем self-hosted Gitea, данные никуда не утекают.
Почему именно Gitea: Полный контроль над данными, отсутствие ограничений на размер файлов и бесплатный приватный сервер.
Обязательно стоит добавить .gitignore: (чтобы не было конфликтов веток)
.obsidian/workspace.json .obsidian/workspace-mobile.json .obsidian/cache .trash/
Также вот неплохая статья с гайдом по настройке (подход немного отличается от моего)
Заключение
Эта система складывалась постепенно и продолжает эволюционировать. Главный вывод за два года использования — хранилище не должно быть идеальным с первого дня. Оно должно помогать думать и работать, а не забирать всё время на свою настройку.
Надеюсь, мой workflow подаст вам пару интересных идей для организации собственного цифрового сада в Obsidian. Если у вас есть вопросы по работе со скриптами или структурой — пишите в комментариях!
Постараюсь ответить на все вопросы. Со мной также можно связаться в телеграм (в хабр профиле), там я точно вам отвечу.
Комментарии (33)

CEOCTO
26.07.2026 14:27Всегда интересно смотреть такие статьи через пару лет использования. Но почти у всех замечаю одну закономерность: чем больше появляется собственных правил, шаблонов и соглашений, тем выше порог входа для самого себя через год. Иногда проще написать обычную markdown-заметку, чем решить, это note, zettel или уже index.

ITsuperiorRF Автор
26.07.2026 14:27Я отчасти согласен, так как 90% времени я пишу в основном планы и заметки, zettelkasten заметки добавляются редко, когда я хочу изучить определенную тему.
Тут важно понимать, что для человека, который видит конкретный подход в первый раз, система может показаться замудренной, однако на самом деле все сводится к простой вставке шаблона в заметку и заполнением properties за 2 минуты, не более. Остальное либо делается автоматически, либо делается очень редко.
Главный смысл в том - что это система, которую проектировал я сам, поэтому она мне интуитивно понятна, и мне не нужно ничего запоминать ради ее реализации. И я лично настаиваю на том, чтобы каждый человек делал систему такой, какой ему нужно, не придумывая лишнего без смысла.
Я лишь хотел привести свой подход, чтобы кто-то мог взять из этого какую-то малую часть, и добавить в свой процесс, если ему это нужно.

DrewUnknown
26.07.2026 14:27данный аргумент не совсем валидный.
Человек сам под себя проектирует систему, он в ней проводит много времени, поэтому это всё уже запоминается на мышечной памяти. То что человек забудет свою систему справедливо, когда он обсидианом пользуется раз в 100500 лет.
+ чтобы не забыть свою систему, все правила так же пишутся\описываются в соответствующей заметки.

bashka-pro
26.07.2026 14:27Какой то рерайт, у вас уважаемый. syncthing вот это мошь, синхронизирует компы, мобилы почти без инета. И это я еще не пишу про слак

ITsuperiorRF Автор
26.07.2026 14:27Я раньше пользовался syncthing, однако мне было важно версионирование, поэтому git меня больше всего привлекает

mih-kopylov
26.07.2026 14:27А как насчёт приложения GitSync? Делает то же самое, по расписанию, без консоли на телефоне.

RulenBagdasis
26.07.2026 14:27А у меня просто иерархия папок по теме и обычные md файлы безо всяяких шаблонов. Из плагинов только HTML Reader, который показывает в обсидиане веб-страницы, сохранённые через SingleFile. Картинки всегда в папке с заметкой хранятся. Это меня полностью устраивает, доволен, как слон.
Зачем вся эта машинерия? Пост начинается сразу с технических подробностей без объяснения, а какую, собственно, проблему решали.

ITsuperiorRF Автор
26.07.2026 14:27Здесь не решается какая-то проблема, я просто рассказывал свой подход которым я пользуюсь. Главный смысл статьи был в том, чтобы каждый мог для себя взять какую-то часть, а не копировать все полностью. Даже больше скажу - конкретно мой подход один в один подойдет только мне и никому более.

RulenBagdasis
26.07.2026 14:27Так зачем вы используете именно такой подход? Это же самое интересное.

ITsuperiorRF Автор
26.07.2026 14:27Я могу частично согласиться с претензией, так как я действительно не писал что и зачем конкретно вводилось, но тут скорее дело в том, что если человеку не понятно зачем вводилось то или иное, значит, вероятно, оно ему не нужно.
Здесь дело не в решении, а в удобстве, так как в действительности информацию можно держать просто в txt в папке, а сам obsidian и надстройки поверх него - лишь "сахар".
Если есть какие-то конкретные моменты, которые нужно объяснить, то спрашивайте, я отвечу.

alexanderniki
26.07.2026 14:27Надеюсь, мой workflow подаст вам пару интересных идей
Я пролистал статью несколько раз и у меня вопрос: так а workflow-то, собссно, где? Структура папок и ваш custom css - это не workflow :)

ITsuperiorRF Автор
26.07.2026 14:27Workflow переводится как рабочий процесс.
В статье я писал про структуру своего Obsidian с описаниями как и что я делаю, данные действия как раз и составляют workflow, т.е как выглядит мой рабочий процесс в obsidian.
Также я затрагивал не только css и структуру папок, как вы пишете, а и то, как я создаю заметки и ими управляю, что и является самой главной частью.

Deric
26.07.2026 14:27Единственная проблема Обсидиана - это отсутствие возможности быстро делать заметки. Давно использую его для хранения информации - но из-за того что на Андроидет Обсидиан открывается ооочень долго рабочий процесс чаще всего выглядит как: добавить быструю заметку в Google Keep - вспомнить что добавил заметку - добавить заметку в Obsidian. Само собой второй этап частенько продалбыввается из-за чего воскресное ретро частенько затягивается потому что надо перенести заметки из Keep в Обсидиан. Очень не хватает виджета быстрых заметок или быстрого доступа к ежеденевной заметке.

ITsuperiorRF Автор
26.07.2026 14:27Тут я согласен, на телефоне obsidian загружается довольно долго. Я частично решил это с помощью добавления отдельной папки с плагинами и настройками для андроид (вместо .obsidian использую .obsidian-mobile). В нем убраны почти все плагины, кроме самых нужных. Это немного ускоряет загрузку.
opium
В этом плане полностью перешёл на ИИ агента и ношн с обсидианом сейчас кажется каменным веком как когда то был евернот
ITsuperiorRF Автор
Честно говоря, я не очень понимаю как ИИ агент может заменить полноценные заметки. Главный смысл заметок в том, что ты их пишешь сам, тем самы закрепляя материал, а не просто складываешь, добавляя ссылки. (иначе проще просто загуглить).
Если я что-то и добавляю в заметки, то это не какие-то сухие факты по типу набора терминов и подобное, а какой-то мыслительный/творческий процесс написания, который невозможно воссоздать иначе, кроме как самостоятельно.
opium
Вообще никто мне кажется так ну пишет, все пишут просто заметки и забывают про них, я очень много видел заметок у знакомых и работников своих это всегда ад и Израиль, я вел заметки очень структурировано, но это требует так много усилий и времени. Сейчас я веду их как попало без напряга и на выходе получаю результат в разы лучше на выходе
ibr06
Можно подробнее?
opium
ну просто ведешь в агенте , он просто ведет все красиво и правильно и с нужными контекстами в гите , если прямо очень много всего можно векторный поиск прикрутить но с миллионым контекстом я везде убрал векторный поиск и раг за ненадобностью
Mixael_sas
А как агент сращивается с Obsidian?
opium
никак обсидиан ношн и все подобные софты не нужны как прослойки , они не добавляют никакого профита в этой схеме , агент сам все прекрасно ведет
Mixael_sas
Т.е. просто ведешь заметки в нужном тебе агенте и он всё помнит? А как же переполнение контекста и галлюцинации? Нужны же точные данные, которые записал сам
opium
Контекст уже очень давно миллион, его можно переполнить ну и компакт или клевер поможет
Галлюцинации на простых задачах вроде заметок ну наверно не совру 0. Так как пользуюсь уже давно и ни разу не встретил как было раньше
Proidoha
Это ортогональные вещи. Можно агента использовать вместе с obsidian, и он же может делать и заметки в том числе, создавая свою базу знаний.
opium
а зачем лишняя тяжелая прослойка в виде обсидиана , какую она несет функциональность то ? обсидиан и ношн и прочие такие системы в такой реализации не нужны
Starmaster1
Не очень то тяжёлая прослойка, всего лишь текстовые файлы. Сам обсидиан агенту не нужен. Обсидиан нужен человеку, чтобы читать заметки самостоятельно
opium
не понял зачем мне для чтения заметок нужен обсидиан, это просто мд файлы , я могу их читать супер быстро и удобно и с компа и с мобилы без всяких лишних софтов , удобно навигировать по ним сам и искать иишкой то что нужно
Starmaster1
Без софтов никак не получится в любом случае. Хоть блокнот, хоть vim, хоть nano, хоть что. Но чтобы было удобно, функционально и красиво, нужен Obsidian. А так, да - есть масса вариантов для любого стиля работы. Как хорошо, что можно выбрать то, что по душе.
opium
ничего не понял , это же просто гит и мд , в браузере просто смотрю, оно супер функционально и красиво всегда , с офигенной навигацией , отсылками и пасхалками
levkib
А если надо посмотреть заметки где-то за пределами стационарных сетей, а мобильный интернет ограничен? Как вы выходите из ситуации?
opium
Пока не было таких проблем ну а так гит что на телефоне что на компе у меня есть, ну и если надо могу копию заметок держать
Starmaster1
Лично я совмещаю оба подхода. У меня Openclaw с wiki-memory в Obsidian и loseless-claw долговременной памятью. В Obsidian же что-то типа PARA workflow настроено со связями. Могу и сам писать/читать заметки и задачи, и агенты в ходе работы разные артефакты туда пишут в свои разделы и пользуются общей базой знаний.