Zettelkasten Inbox / ブロック詳細
「このノートはどの観点の話か」を決める場所。おすすめは語句の重なりの点数計算で、通信ゼロ・AIなし。無ければその場でTagを作れるが、作る前に必ず同名を照合する。
抽象度 Lv.4(技術用語+システム上のやりとりまで/製品名・ライブラリ名は書かない)「このノートは、どの観点の話か」を決める場所。Tagはこのアプリの分類の背骨で、 Tagを選ばないとABC Noteの候補が1つも出ない作りになっている。
おすすめは、ノートの文とTag名の語句の重なりで点数を付けて上位3件を出す。 ここもAIは使っていない。全部ブラウザの中の計算で、通信は発生しない。
探しても無ければ、その場で新しいTagを作れる。ここだけがNotionへの書き込みで、 作る前に必ず「同じ名前が既にないか」を照合する。
3. 本文の取り出しと自動要約 → 5. Tagの推薦と新規作成 → 6. ABC Note候補の絞り込み
POST /api/tags を呼ぶ502ABC Noteより先にTagを決めさせるのが、このアプリの中心の思想。 ABC Noteは数が多く、名前だけでは似たものが並ぶ。 先に「どの観点か」を1段挟むことで、候補が数十件から数件まで一気に減る。 Tagは分類のためというより、選択肢を減らすための道具として置かれている。
推薦をサーバーに置かなかった理由。3番で作った特徴量がすでにブラウザにある。 同じものをサーバーへ送り直せば通信が要る。ブラウザで完結させたことで、 コメントを書き足して「候補を更新」を押すとその場で順位が変わる。
整理用Tagを減点する理由。「あとで読む」「本」のようなTagは、 仕組み上はよく使われるので使用回数が高く、放っておくと常に上位に出る。 だが観点としては何も言っていない。45点という重い減点で、意図的に沈めている。
新規作成を保存(8番)とは別のAPIにした理由。Tagを作った時点で 画面のTag一覧に即座に加わり、選択済みになる。保存まで待たせない。 「無いなら作って、そのまま続ける」という流れを止めないための分離。
| 工程 | 主体 | やりとりの内容 | 方向 |
|---|---|---|---|
| 5-1 | ブラウザ(内部) | ノートの文を正規化し、2文字の並びの集合に変換 | ↻ |
| 5-2 | ブラウザ(内部) | Tagごとの点数計算と上位3件の選出 | ↻ |
| 5-3 | ブラウザ(内部) | 検索入力があれば推薦を止め、絞り込みに切替 | ↻ |
| 5-4 | ブラウザ → Tag作成API | 新しいTagの名前(新規作成のときだけ) | → |
| 5-5 | Tag作成API → Notion | Tag DBの全件取得と同名の照合 | → |
| 5-6 | Tag作成API → Notion | (同名が無ければ)ページの作成 | → |
| 5-7 | Tag作成API(内部) | 作成結果の検証 | ↻ |
| 5-8 | Tag作成API → ブラウザ | Tagの情報と、作ったか見つけたかの区別 | ← |
5-1 まず、このノートに関する文字を全部つなげて1本の文章にし、 比べやすい形に整える。整えるというのは、大文字小文字・全角半角・記号・空白のばらつきを消すこと。
技術的には つなぐのは 元の題名・編集中の新タイトル・編集中のコメント・Notion本文の4つ。 正規化は3手順:全角と半角を統一する形に変換(NFKC)、日本語向けの小文字化、 そして空白・約物・記号をすべて削除。 残った文字列を先頭から2文字ずつ重ねて切り出し、重複を消した集合にする (「知識管理」なら「知識」「識管」「管理」の3つ)。 2文字にするのは、日本語には英語のような単語の区切りが無いから。 単語に分けようとすると辞書が要るが、2文字ずつなら辞書なしで語句の重なりが測れる。
5-2 Tag1つずつに点数を付けて、高い順に3つを「おすすめ」に出す。
技術的には 重なりの測り方が2種類あり、混ぜて使う。 包含率=Tag側の並びのうち何割が本文にもあるか。 ダイス係数=共通部分の2倍を、両方の合計で割った値。 この2つを 0.72 : 0.28 で混ぜる。 包含率を重く見ているのは、短いTag名が長い本文に埋もれないようにするため―― ダイス係数だけだと、本文が長いほど分母が膨らんですべてのTagの点が下がってしまう。 そのうえで、点数は次の足し算になる。 そのまま含まれていれば140点(「知識管理」というTagが本文に丸ごと出てくる場合)、 題名の重なり×85、親Tag名と説明文の重なり×65、配下にABC Noteがあれば8点、 使用回数の常用対数×5(10件で5点、100件で10点。対数にしているのは、 よく使うTagが強くなりすぎないように差を圧縮するため)、 整理用Tagなら45点減点。上位3件が「おすすめ」、残りは使用回数順で下に並ぶ。 この計算は通信ゼロで、Tagが200件あっても一瞬で終わる。
5-3 検索窓に何か打つと、おすすめは消えて、素直な絞り込みに切り替わる。
技術的には 入力を同じ手順で正規化し、 Tag名・親Tag名・説明文をつないだ文字列に含まれるかで絞る。 並び順は使用回数の降順、同数なら日本語順。 推薦と検索を同時に見せず、はっきり切り替えるのは、 「探しに来た人」に対して機械の推測を混ぜない、という判断。
5-4 探しても無ければ、入力した名前でそのまま新しいTagを作れる。 同じ名前のTagが既にあるときは、作成ボタンが押せなくなる。
技術的には POST /api/tags に
application/json で {"title": "…"}。
ボタンを押せなくする判定はブラウザ側でも行うが、
サーバー側でも同じ照合をやり直す(画面の状態が古い可能性があるため)。
名前の上限は100文字で、これも両側で見る。
5-5 サーバーはNotionのTagを全部取ってきて、同じ名前が無いかを確かめる。
技術的には 同名かどうかの判定は、 全角半角をそろえ、小文字にし、前後の空白を落とし、連続空白を1つにまとめた形で比べる。 ここは 5-1 の正規化とは別で、記号は消さないし、空白も残す―― Tag名は表記そのものが意味を持つので、消しすぎると別のTagが同じものと判定されてしまう。 2つの正規化を使い分けているのがこのアプリの細かい所。
5-6 無ければ作る。ラベルの絵文字が自動で付く。
技術的には POST /v1/pages に、
親としてTag DBを指定し、絵文字🏷️をアイコンに、名前だけを設定して作る。
親Tagや配下のABC Noteは設定しない。階層への組み込みは、あとからNotion側で人がやる前提。
5-7 作ったあとで、本当に狙いどおりに出来ているかを確かめる。
技術的には 返ってきたページに対して2つ検証する。
(1) 親が本当にTag DBか――親の種類が「データソース指定」で、
そのIDが設定と一致するか。
(2) 付いた名前が、頼んだ名前と正規化後に一致するか。
どちらか外れたら 502 +「NotionへのTag作成結果を確認できませんでした。」。
ただし、このとき作られたページは削除されない。
照合は「出来たつもりで出来ていない」を検知するためのもので、元に戻す仕組みではない。
5-8 結果を返す。「新しく作った」のか「同名が見つかった」のかを 区別して伝えるので、画面のお知らせも変わる。
技術的には {"ok": true, "tag": {…}, "created": true|false}。
created が偽なら「同名のTagが見つかったため、既存のTagを選択しました。」と出る。
どちらの場合もTagは選択済みになり、作業は止まらない。
作成に成功したときだけ、受信箱と全体マップの控えを捨てる関数が呼ばれる。
502。
元に戻す処理はどこにも無い。Notionが正本なので、
直すのはNotion側で人がやる、という割り切り。400。Notionへは行かない。404 がそのまま返り、
画面のTag作成欄の下に赤い文字で出る。推薦や他の操作は止まらない。502。
Notion側にはTagが作られたまま残る可能性がある。
画面には「Notion側を確認してください。」と出るだけで、自動では消さない。※ 2026年8月14〜15日時点の zettelkasten-inbox のプログラムを読んで作成しました。過去の設計資料は参照していません。
※ 番号は全体図・この解説・シーケンス図で共通です。工程番号は「ブロック番号-連番」で書いています。