📝

Markdownを単一ソースにしたタスク管理ツールをVite + React + Monacoで作ってみた

に公開

はじめに

最近、個人開発や調べ物などを進める中で
「もう少し雑に扱えて、あとから AI に投げやすいタスク管理が欲しい」
と思うことが増えてきました。

多くのタスク管理ツールは高機能で完成度も高いのですが

  • 入力がフォーム前提になっている
  • 内部データ構造がツール固有で外に出しづらい
  • LLM にそのまま渡せる形では保存されていない

といった点が、少しだけ引っかかっていました。

そこで今回
「人間が書きやすく、LLMが読みやすい」 タスク管理の形を試してみようと思い
Flowmark という小さなアプリを作りました。

Flowmark の基本方針はとてもシンプルです。

  • タスクは Markdown でそのまま書く
  • Markdown が唯一の正
  • UI やビューはすべてそこから自動生成する

Markdown なら人間にとっては雑に書けて
LLM にとってはそのまま文脈付きデータとして扱えます。

この記事では Flowmark を どんな設計で、どのように実装したかを整理していきます。

作ったもの

画面スクショ

  • 画像の左側がマークダウン入力画面で、右側がマークダウンを元にタスクを表示
  • 「#」で入力したものでタスク分類
  • 画面右側のチェックボックスをクリックすると [x]にもできる

Github

(starいただけると嬉しいです…)
https://github.com/KASAHARA-Kyohei/flowmark

Flowmarkは「タスク管理ツール」ではない

Flowmark は、一般的な意味での「タスク管理ツール」ではありません。

Todo アプリやプロジェクト管理ツールというよりも
「思考を止めずに、やることを書き続けるための道具」を意識しました。

多くのタスク管理ツールでは、タスクを追加するだけでも次のような操作が必要になります。

  • 入力フォームを開く
  • タイトルを入れる
  • 期限や優先度を選ぶ
  • 保存ボタンを押す

この一連の操作は、一見すると整理されているようで
実際には 「考える流れ」を何度も分断します。

Flowmark が解決したかったのは
「タスクを管理すること」ではなく「タスクを書くこと」です。

発想の転換:まず Markdown を書く

Flowmark の出発点はとても単純です。

人間は、構造化されたフォームより
箇条書きの文章のほうが速く書ける

実際、やることを考えるときはこんな書き方をします。

- バグ直す
- 明日ミーティング
- 記事書く

Flowmark では、この 雑な書き出しを否定しません。
むしろ、それをそのまま「正」として扱います。

  • Markdown は人間が書く
  • 構造化はツールがやる
  • UI は Markdown から常に再生成する

これが Flowmark の思想です。

Flowmark の全体像

UI は非常にシンプルです。

  • 画面左:Monaco Editor で Markdown を直接編集
  • 画面右:Markdown をパースした Task AST から導出したビュー
    (Inbox / Today / All / セクション別)
  • 保存:IndexedDB

画面右側は常に派生ビューであり、真実は左側の Markdown だけ
という点です。

図解:Flowmark のデータフロー

  • 編集は常に Markdown
  • UI 操作も最終的には Markdown を書き換える
  • 状態は一切分岐しない

技術スタックと構成

  • Vite + React + TypeScript(strict)
  • Monaco Editor
    • monaco-editor
    • @monaco-editor/react
  • Tailwind CSS
  • 永続化:IndexedDB → localStorage fallback

ディレクトリ構成(monorepo-ready、webのみ実装)

flowmark/
  docs/     # Codex先生用
  packages/ 
    web/
      src/
        parser/
        storage/
        ui/
        utils/

コア設計

Flowmark の設計原則はこれだけです。

  • UI の状態は 常に Markdown から導出
  • 右側 UI の操作も 最終的には Markdown を書き換える

これにより

  • データモデルの二重管理を回避
  • 状態不整合の温床を排除
  • デバッグ対象を Markdown のみに限定

できます。

タスク記法

タスクは 1 行 = 1 タスクの Markdown リスト項目です。

- [ ] write blog @2026-01-10 #oss !high ~30m
- [x] fix parser bug @2026-01-07 @15:00 #wbs !!
- buy milk

MVP ルール

  • 行頭が - ならタスク候補
  • [ ] / [x] があれば完了状態に反映
  • 未知トークンがあっても 絶対に落とさない
  • raw(元行)は必ず保持

トークン一覧(順不同)

以下を入力するとタスクの下側に付属情報が表示されるようなイメージです。

  • due:@YYYY-MM-DD / @today / @tomorrow
  • time:@HH:MM
  • tag:#word
  • priority:!low / !high / !! / !!! → 0..3
  • effort:~<number>(m|h) → minutes

1パスでの Markdown パース(セクション導出)

見出しは MVP なので # (level 1)のみ扱います。
セクションは 直前の見出しです。

for (let index = 0; index < lines.length; index++) {
  const line = lines[index];

  if (line.startsWith('# ')) {
    currentSection = line.slice(2).trim() || 'Inbox';
    continue;
  }

  if (!line.startsWith('- ')) continue;
  const parsed = parseTaskLine(line, { now });
  if (!parsed) continue;

  tasks.push({
    id: fnv1a32(`${currentSection}\n${normalizeTaskLineForId(line)}`),
    raw: line,
    section: currentSection,
    ...parsed,
    lineNumber: index + 1
  });
}

Monaco Editor を使った理由

Flowmark において Monaco は
単なるエディタ部品ではなく、UX そのものです。

なぜ Monaco か

  • VS Code と同じ編集体験
  • Undo / Redo / 行操作 / マルチカーソルが最初から揃っている
  • コマンド登録とキー割当が強力
  • テキストモデルを直接操作できる

なので
「UI 操作」ではなく「テキスト編集」としてタスク管理ができます。

公式リソース

図解:Monaco を中心にした編集ループ

おわりに

Flowmark は
タスクを「管理」するためのツールではなく、
タスクを「書き続ける」ための道具
です。

Markdown を書く行為そのものを中心に据え、
UI は常にそれに従う。

この思想が刺さる人には、かなり快適な体験になるかと思い作ってみました。
本当にこれが良いのか自分でもわからないのでしばらく自分で使ってみようと思います。

Discussion