「自分でアウトライナーを作れるのか」

今回は、アウトライナーのアプリ製作に関する内容です。

2024年後半にLogseq DB版が話題になり、アウトライナーの自作に興味を持ち、昨年はGoogle AI StudioFirebase Studioを活用し20以上の試作を重ね徐々に知見が溜まってきました。一区切りをつけて記録を残します。


理想のアウトライナーを求めて、約50のアプリを試行錯誤した末、自分の中では、データベース構造が必須だと結論づけましたブロック単位の緻密な管理 (しくみ) を実現するには、データベース化が不可欠だからです。(当時)

- Markdownファイルベース更新
- ブロックIDを持つアウトライナー
- データベース併用
この三つを“同時に”高い整合性で成立させるのは構造的にほぼ不可能に近い

ファイルベースのアウトライナーについて

従来のLogseqもこれを実現していたけど、パフォーマンス低下などの副作用が課題でした。長期的な蓄積でも破綻しない運用を求めると、次の3つが有力な候補となります。

データベース方式の最新ツール

1.Workflowy: プロセス型 アウトライナー
https://workflowy.com/
究極にシンプルな操作感。動作は非常に軽快ですが、無料版は項目数に制限があるため、長期的には有料プランが必須となります。

画像
WorkFlowly

2.Tana: ネットワーク型 アウトライナー
https://tana.inc/
Logseqに近いデイリーノート中心の設計で、Logseq派にも馴染みやすいアプリです。

画像
Tana

3.Capacities: ブロック単位 PKMツール
https://capacities.io/
もっともユーザーフレンドリー。
データベースを活用した、「オブジェクト整理」方式。
日付でリファレンスを集めてくれるので、デイリーノートとして最適。

画像
Capacities

Capacitiesは、データベースの表示方法(ビュー)に開発の重点がある。

過去記事 ↓


それぞれのアプリの核心を、一言で表すと以下のようになります。

  • Workflowy:階層(上下構造で深掘りする)

  • Tana:役割(スーパータグで属性を定義する)

  • Capacities:型(オブジェクトとして構造化する)


  • 補足:

    • Workflowy は、どこまでも続く「階層」の中に情報を配置する。

    • Tana は、ノードに「#task」や「#meeting」といったタグ(役割)を与えることで、情報を動的に扱う。

    • Capacities は、情報を「本」や「人」といった特定の「型」として扱い、厳密に管理する方式。

クラウドであることが欠点

これら3つのクラウド依存アプリ(SaaSと呼ばれる)は、利便性と引き換えにデータの永続性やプライバシーをサービス側に委ねる「ベンダーロックイン」のリスクを抱えています。オフライン制限や拡張性の低さなど、Logseqのような自由度や安心感がない点は共通の課題です。


自分でアウトライナーを作るとすると

LogseqユーザーとしてTanaの完成度には惹かれますが、Tana級の利便性を備えた「デスクトップ特化」のアプリを自作したいと考えています。


求めるアプリの要件

  • なぜ作るのか

    • ローカル保存と永続性

      • SQLiteデータベースで10年先も閲覧・処理可能

    • 情報のブロック化

      • タグで意味を付与し、柔軟に構造化する。

  • どう使うのか

    • 日々の記録と抽出、ネットワーク化

      • デイリーノートに集約しつつ、文脈に応じて必要な情報を呼び出す。書くときは一箇所だけど、提示するのは各々の場所で(Tanaのコンセプト)

      • リンクとリファレンスにより、関連情報を提示する

  • どんなツールか

    • アウトライナー

      • 操作性の高いブロック単位の編集構造

    • PC環境への最適化

      • デスクトップでの操作性とレスポンスを優先


採用ライブラリ

(ソースコードが公開されていて) 特定の機能を呼び出して再利用できるようにまとめられたものを『ライブラリ』と言います。


アウトライナー

lexical: ブロック単位 高機能エディターコア (Facebook製)
https://playground.lexical.dev/ デモ
https://lexical.dev/ サイト

画像
一般的なアウトライナーを手軽に構築できる

デスクトップアプリ

Tauri: Web技術で、軽量動作のデスクトップアプリを構築できる
https://v2.tauri.app/ja/

SQLite: ローカル駆動のクエリーデータベース
https://sqlite.org/

データベース式でアプリを構築します。アウトライナーおよびネットワーク型ナレッジベースはデータベースと相性がよいためです。
基本的に、ブロックノードには固有IDを付与するのですが、それをマークダウンファイルに記載するのは困難で、それなら共存させたらいいのではという意見もあるのですが、競合してしまうので現実的には厳しいです。
ただし、階層内にある複数のノートを、純粋なマークダウンファイルとして一括して出力するだけなら可能です。

ユーティリティ

date-fns: 日付関連の処理
https://date-fns.org/

date-holidays: 世界各国の祝日に対応
https://www.npmjs.com/package/date-holidays

画像
date-holidaysは、
Logseq用 「Show weekday and week-number」
プラグインで利用しているライブラリの一つ。

Yjs: CRDT技術による差分更新
https://github.com/yjs/yjs

CRDT: Conflict-free Replicated Data Type)
正しく設計すればパフォーマンス・データ安全性の向上にも応用できる。
将来的には、共同編集、別デバイス間のローカルファースト同期が可能。


スコープ外(実装しないこと)

  • APIやプラグインの仕組みは設けない

  • Web版・モバイル版は用意しない

  • Markdownファイルベースの運用はしない

  • サーバーを介する機能 (同期、リアルタイム共同編集など) は対象外


課題

  • データベースの不透明さ、他アプリへの移行性の考慮

    • → Markdownファイルで全体をエクスポート可能にする

      • 定期的な書き出しも検討

  • 将来的に拡張性が必要になるかもしれない

  • 個人開発のスコープでどこまで作り込めるか



(後日記載)
個人的には、今回の内容のとおり、データベース式のブロック単位アウトライナーを必要としていますが、そうではなくファイルベース・アウトライナーのニーズがあるため、そちらも実現可能かどうか検討してみました

新しい記事 ↓


ピックアップされています

ノートアプリ研究 (PKM)

  • 19本

コメント

2
コメントするには、 ログイン または 会員登録 をお願いします。
TOのプロフィールへのリンク
TO

いつも参考にさせて頂いています。 私事ですが、NotionやCapacitiesには馴染めず、コロナ禍の円安でRoam Researchを離れて以来、しばらくLogseqを使っておりましたが、DB版の安定リリースがなかなか来ないのにしびれを切らして、この冬休みにTanaを試しています。 Logseqを使っていた時は、テキ…

1
YU いいね
YUのプロフィールへのリンク
YU

Logseqの件もTanaの件も、よく分かります。 Tanaに関しては、コンセプト/基軸は「アウトライナー式デイリーノートで、タグをつけながら書いていくスタイル」なので、Logseqの進化系と捉えることもできるのではないかと考えていますが、それと馴染めるかどうかは別かもしれませんね。

1
買うたび 抽選 ※条件・上限あり \note クリエイター感謝祭ポイントバックキャンペーン/最大全額もどってくる! 12.1 月〜1.14 水 まで
「自分でアウトライナーを作れるのか」|YU
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1