tldraw-skill について
tldraw-skillは、ホワイトボード風の図を.tldr JSONファイルとして作成し、@kitschpatrol/tldraw-cliでPNGまたはSVGに書き出すスキルです。手動配置した図形と接続を使い、システムやプロセスを可視化します。
主な機能
- 01.tldr JSON形式の図の生成
- 02PNG・SVGファイルへの書き出し
- 03図形と矢印による図の作成
- 04書き出し画像のレイアウト確認
- 05個別編集による図の修正
活用シーン
- 01複数段階のプロセスやデータフローの可視化
- 02サービスやモジュール間の関係の表示
- 03アーキテクチャ図や決定木の作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ agents365-ai/ tldraw-skill --skill tldraw-skillインストール後、Claude Code で/tldraw-skillを入力して読み込まれたか確認します。
詳細
tldraw ホワイトボード図
概要
モダンなホワイトボードスタイルの図を .tldr JSON ファイルとして生成し、@kitschpatrol/tldraw-cli を使って PNG/SVG にエクスポートします。tldraw は、豊富な図形ライブラリと滑らかな矢印のルーティングを備えた、すっきりとした手描き風の図を作成します。カジュアルなビジュアライゼーションやホワイトボードスタイルのビジュアライゼーションに適しています。
形式: .tldr JSON
エクスポート: PNG、SVG(@kitschpatrol/tldraw-cli を使用)
見た目: デフォルトは手描き風のホワイトボードスタイルです。font プロパティで、すっきりしたフォントに切り替えられます。
使用する場面
明示的なトリガー: ユーザーが「図」「フローチャート」「描く」「可視化する」「ホワイトボード図」「tldraw 図」「アーキテクチャ図」「これをスケッチして」などと言った場合。
積極的に使用する場面:
- 3 つ以上のコンポーネントが連携するシステムを説明する場合
- 複数段階のプロセス、データフロー、パイプラインを説明する場合
- サービスやモジュール間の関係を示す場合
- アーキテクチャの概要、シーケンスフロー、決定木、ML モデルのレイヤーを示す場合
使用しない場合: 簡単なリストや表で十分な場合、ユーザーが洗練されたビジネスプレゼンテーション用の図を求めている場合(drawio-skill を優先)、またはユーザーが簡単な質疑応答の最中である場合。
使用せず、別の手段を使う場合:
- ロゴ/単色グラフィック/塗りつぶしアイコン:tldraw には不透明な塗りつぶしがありません(
solidは淡い色合いになり、暗い背景に白で描いたものは再現できません)→ drawio スキルまたは元のベクターファイルを使用してください。 - 正確なベクター形状や厳密な(中抜き矢印の)UML → drawio(または UML には plantuml)を使用してください。
- 多数のノードの自動レイアウト → mermaid を使用してください(tldraw では座標を手動で指定する必要があります)。
- 既存の画像をピクセル単位で忠実に再現する場合 → 図作成スキルの対象ではありません。
前提条件
# Install tldraw-cli
npm install -g @kitschpatrol/tldraw-cli
# Verify
tldraw --version
macOS、Windows、Linux で同じように動作します。
初回エクスポート時の注意: tldraw export は、固定バージョンの Chrome ビルドを puppeteer 経由で使ってレンダリングします。初回のエクスポートでは Could not find Chrome (ver. <x>) というエラーが発生することがあります。エラーに必要な正確なバージョンが表示されるので、一度インストールすれば、その後はエクスポートできます。
# The error message names the version; substitute it here
npx puppeteer browsers install chrome@<version-from-error>
(~/.cache/puppeteer にインストールされます。必要なのは CLI のバージョンごとに一度だけです。)
ワークフロー
作業を始める前に、ユーザーのリクエストに十分な具体性があるかを確認します。重要な情報が不足している場合は、要点を絞った質問を 1~3 件します。
- 図の種類 — どのプリセットを使いますか?(Architecture、Flowchart、Sequence、ML/DL、ERD、UML、または一般)
- 出力形式 — PNG(デフォルト)、SVG のどちらですか?
- 出力先 — デフォルトはユーザーの作業ディレクトリです。ユーザーが明示したパス(例:「
./artifacts/に保存して」)があれば、それに従います。指定がない場合は質問しないでください。 - 範囲/忠実度 — コンポーネントはいくつですか?特定の技術やラベルはありますか?
リクエストに必要な詳細がすでに含まれている場合や、明らかに簡単な内容(例:「X のフローチャートを描いて」)の場合は、確認を省略します。
- 依存関係を確認 —
tldraw --versionが成功することを確認します。インストールされていない場合は、npm install -g @kitschpatrol/tldraw-cliを実行します。 - 計画 — 図形(ノードごとの geo タイプ)、接続(始点/終点を指定した矢印)、レイアウト(TB または LR、階層/役割ごとのグループ化)を特定します。JSON を書く前に座標グリッドをスケッチします。
- 生成 —
.tldrJSON ファイルを書きます。デフォルトの出力先はユーザーの作業ディレクトリです。ユーザーがパスやディレクトリ(例:./artifacts/)を指定した場合は、先にmkdir -pでディレクトリを作成し、そこに書き込みます。手順 4 と 7 で PNG/SVG をエクスポートするときも同じ出力先を使います。 - ドラフトをエクスポート — CLI を実行して、プレビュー用の PNG を生成します。
- 自己チェック — エージェントに組み込まれたビジョン機能を使ってエクスポートした PNG を読み取り、明らかな問題を見つけて、ユーザーに見せる前に自動修正します(Claude Sonnet/Opus など、ビジョン対応モデルが必要です)。ビジョン機能を利用できない場合は、この手順を省略します。
- レビューの反復 — 画像をユーザーに見せてフィードバックを受け取り、JSON を必要な箇所だけ修正して再エクスポートします。承認されるまで繰り返します。
- 最終エクスポート — 承認されたバージョンを、リクエストされたすべての形式でエクスポートします。
.tldrソースファイルとエクスポートした画像のファイルパスを報告します。
ステップ 5:セルフチェック
下書きの PNG をエクスポートしたら、ユーザーに表示する前に、エージェントの画像認識機能(例:Claude の画像入力)を使って画像を読み取り、以下の問題がないか確認します。エージェントが画像認識に対応していない場合は、セルフチェックを省略して PNG をそのまま表示します。
tldraw 独自の AI エージェントが検出する構造上の欠陥は、テキストのはみ出し(ラベルに対してボックスが小さすぎる)、テキストの重なり、接続先のない矢印(片方の端が未接続の矢印)のちょうど 3 つです。以下の最初の 3 行はそれらを対象としています。あらかじめボックスを適切なサイズに設定しておけば(「ラベルに合わせたボックスのサイズ設定」を参照)、これらの問題はほとんど発生しません。
| チェック項目 | 確認する内容 | 自動修正の方法 |
|---|---|---|
| テキストのはみ出し | ラベルが図形の枠からはみ出している、またはボックスが指定した高さより大きく見える(tldraw は小さすぎるボックスを自動で拡大します) | ラベルに収まるよう w/h を大きくします — 以下のサイズ設定の計算式を参照 |
| テキストの重なり | テキストを含む 2 つの図形のラベルが接触または重なり、読みやすさが損なわれている | 図形を 200px 以上離します |
| 接続先のない矢印 | 片方の端が図形に接続されていない矢印(宙に浮いている) | 両端を接続します。すべての矢印の start と end に、既存の図形と一致する boundShapeId が必要です |
| キャンバス外の図形 | 負の座標にある図形、または主要なグループから遠く離れた図形 | クラスター付近の正の座標に移動します |
| 矢印と図形の重なり | 矢印が無関係な図形を視覚的に貫通している | bend の値を調整するか、端点を別の normalizedAnchor 側に移動します |
| 矢印の重なり | 複数の矢印が同じ経路で互いに重なっている | 図形の周囲に normalizedAnchor を分散させます(異なる x/y 値を使用します) |
- セルフチェックは最大 2 ラウンドです — 2 回修正した後も問題が残る場合は、そのままユーザーに表示します。
- 修正のたびに再エクスポートし、新しい PNG を読み直します。
ステップ 6:レビューの反復
セルフチェックの後、エクスポートした画像を表示し、ユーザーにフィードバックを求めます。
フィードバック別の編集ルール — 各種フィードバックに対して、必要最小限の JSON 変更を適用します。
| ユーザーのリクエスト | JSON の編集方法 |
|---|---|
| X の色を変更 | props.text が X と一致する図形を見つけ、props.color を更新します |
| 新しいノードを追加 | 次に使用可能なインデックスを使って新しい図形レコードを追加し、関連ノードの近くに配置します |
| ノードを削除 | 図形レコードと、それにバインドされている矢印レコードを削除します |
| 図形 X を移動 | 図形の x/y フィールドを更新します |
| 図形 X のサイズを変更 | props.w/props.h を更新します |
| A から B への矢印を追加 | A と B の図形 ID にバインドする新しい矢印レコードを追加します |
| ラベルのテキストを変更 | 一致する図形または矢印の props.text を更新します |
| レイアウトの方向を変更 | 全面的に再生成 — グリッドを再計画し、作り直します |
ルール:
- 単一要素の変更の場合:既存の JSON をその場で編集します — これにより、前回までの反復で調整したレイアウトを維持できます。
- レイアウト全体に関わる変更(例:LR↔TB の入れ替え、「最初からやり直す」)の場合:JSON 全体を再生成します。
- 各反復で同じ
{name}.pngを上書きします —v1、v2、v3などのファイルは作成しません。 - 編集後に再エクスポートし、更新した画像を表示します。
- ユーザーが承認済み/完了/LGTM と言うまで、反復を続けます。
- 安全策: 5 回の反復後、細かな調整を行うにはユーザーが
.tldrファイルを tldraw.com またはデスクトップアプリで開くよう提案します。
ファイル形式
.tldr の完全なスケルトン
{
"tldrawFileFormatVersion": 1,
"schema": {
"schemaVersion": 1,
"storeVersion": 4,
"recordVersions": {
"asset": {"version": 1, "subTypeKey": "type", "subTypeVersions": {"image": 2, "video": 2, "bookmark": 0}},
"camera": {"version": 1},
"document": {"version": 2},
"instance": {"version": 17},
"instance_page_state": {"version": 3},
"page": {"version": 1},
"shape": {"version": 3, "subTypeKey": "type", "subTypeVersions": {"group": 0, "embed": 4, "bookmark": 1, "image": 2, "text": 1, "draw": 1, "geo": 7, "line": 0, "note": 4, "frame": 0, "arrow": 1, "highlight": 0, "video": 1}},
"instance_presence": {"version": 4},
"pointer": {"version": 1}
}
},
"records": [
{"id": "document:document", "typeName": "document", "gridSize": 10, "name": "", "meta": {}},
{"id": "page:page1", "typeName": "page", "name": "Page 1", "index": "a1", "meta": {}}
/* shapes and arrows go here */
]
}
重要なルール:
document:documentとpage:page1のレコードは常に必須です。- すべての図形は、ページレコードの後にある
records配列に入れます。 - すべての図形の
"parentId": "page:page1"とします。 - 図形 ID の形式は
"shape:xxx"とし、末尾には一意の文字列を使用します(例:"shape:s1"、"shape:a1")。 indexの値は分数インデックスキーです。"a"に 62 進数の文字を1 文字付け、"a0"~"a9"、次に"aA"~"aZ"、次に"aa"~"az"の順に使用します(順序付きのキーは 62 個あり、通常の図なら十分です)。- 2 文字目を追加しないでください。
"a10"は無効です。 また、先頭に"b"/"c"を使うことは絶対に避けてください("b1"、"c1"、"b0")。これらはより大きな整数部を表すため、不正な分数キーとなり、invalidRecordsが発生します。上記の 1 文字の"a*"キーのみを使用してください。
Geo 図形レコード
{
"id": "shape:s1",
"typeName": "shape",
"type": "geo",
"parentId": "page:page1",
"index": "a1",
"x": 100,
"y": 100,
"rotation": 0,
"isLocked": false,
"opacity": 1,
"meta": {},
"props": {
"w": 180,
"h": 60,
"geo": "rectangle",
"color": "blue",
"labelColor": "black",
"fill": "semi",
"dash": "draw",
"size": "m",
"font": "draw",
"text": "API Gateway",
"align": "middle",
"verticalAlign": "middle",
"growY": 0,
"url": ""
}
}
Geo の種類
geo の値 | 用途 |
|---|---|
rectangle | サービス、モジュール、コンポーネント |
ellipse | データベース、開始/終了ノード |
oval | カプセル形の開始/終了記号(フローチャート) |
diamond | 判断ポイント |
cloud | 外部サービス、インフラストラクチャ |
hexagon | イベントハブ、メッセージバス |
triangle | ゲートウェイ、ロードバランサー |
star | 強調表示、主要機能 |
pentagon | 段階、マイルストーン |
octagon | 停止/終端/ブロック状態 |
trapezoid | 手動操作、変換 |
rhombus / rhombus-2 | 平行四辺形 — I/O の手順(左右の傾斜) |
arrow-right / arrow-left / arrow-up / arrow-down | 方向を示すフローブロック、データの移動 |
x-box | 失敗/無効/却下状態(✕ の付いたボックス) |
check-box | 合格/検証済み/完了状態(✓ の付いたボックス) |
heart | アクセント(技術図ではほとんど必要ありません) |
20 種類の geo 値はすべて有効です。上記は技術図で役立つものを抜粋しています。
カラーパレット
color | 用途 |
|---|---|
blue | クライアント、コアサービス |
green | 成功、データベース、ストレージ |
orange | キュー、イベントバス、警告 |
red | 外部 API、エラー、アラート |
light-red | 控えめなアラート、二次的な警告 |
violet | ゲートウェイ、セキュリティ、認証 |
yellow | 判断、キャッシュ |
grey | 中立、背景、レガシー |
light-blue | 二次サービス、メタデータ |
light-violet | 控えめな認証/セキュリティ、二次ゲートウェイ |
light-green | 控えめな成功、二次ストレージ |
white | 空白/空のノード、プレースホルダー(fill: solid と組み合わせます) |
black | タイトル、強調 |
全パレット(13 色):black、grey、light-violet、violet、blue、light-blue、yellow、orange、green、light-green、light-red、red、white。
スタイルオプション
| プロパティ | 値 | 備考 |
|---|---|---|
fill | semi、solid、none、pattern | semi = 色付きの塗りつぶし(推奨) |
dash | draw、solid、dashed、dotted | draw = 手描きのデフォルト |
size | s、m、l、xl | m = デフォルト |
font | draw、sans、serif、mono | draw = デフォルトのホワイトボードスタイル |
矢印レコード
{
"id": "shape:a1",
"typeName": "shape",
"type": "arrow",
"parentId": "page:page1",
"index": "aG",
"x": 0,
"y": 0,
"rotation": 0,
"isLocked": false,
"opacity": 1,
"meta": {},
"props": {
"dash": "draw",
"size": "m",
"fill": "none",
"color": "black",
"labelColor": "black",
"bend": 0,
"start": {
"type": "binding",
"boundShapeId": "shape:s1",
"normalizedAnchor": {"x": 0.5, "y": 1},
"isExact": false
},
"end": {
"type": "binding",
"boundShapeId": "shape:s2",
"normalizedAnchor": {"x": 0.5, "y": 0},
"isExact": false
},
"arrowheadStart": "none",
"arrowheadEnd": "arrow",
"text": "",
"font": "draw"
}
}
矢印の接続ルール
- 矢印レコードの
xとyは常に0, 0です。 "type": "binding"とboundShapeIdを使って、特定の図形に接続します。normalizedAnchorは、矢印が接続する対象図形上の位置を指定します(範囲は 0~1)。{x: 0.5, y: 0}= 上部中央{x: 0.5, y: 1}= 下部中央{x: 0, y: 0.5}= 左中央{x: 1, y: 0.5}= 右中央{x: 0.5, y: 0.5}= 中央
- ラベル付きの接続には、矢印の props に
"text": "label"を追加します。 - 他の矢印との重なりを避けるため、少しカーブさせる場合は
"bend": 20(または-20)を指定します。 - 破線/点線の矢印(例:非同期フロー、任意のリンク)では、
"dash": "dashed"または"dotted"を設定します。 - 滑らかな曲線の矢印には
"spline": "cubic"を設定します(デフォルトの"line"は直線/直角線です)。スキップ接続や逆方向の接続に便利です。
矢印の先端
arrowheadStart と arrowheadEnd は、それぞれ以下の9つの値を受け付けます(すべて @kitschpatrol/tldraw-cli で描画されます)。
| 値 | 見た目 | 用途 |
|---|---|---|
none | (先端なし) | 一方向矢印の始点 |
arrow | 開いたV字 | デフォルトの流れの方向 |
triangle | 塗りつぶされた▶ | UMLの継承/「is-a」 |
diamond | 塗りつぶされた◆ | UMLのコンポジション/集約(所有者側の端) |
dot | ● | シーケンス図のメッセージの端点 |
square | ■ | 終端/固定された端点 |
bar | | | 「停止」/境界マーカー |
pipe | || | 代替の境界マーカー |
inverted | 中が空のV字 | 目立たせない方向 |
デフォルトの矢印では "arrowheadStart": "none"、"arrowheadEnd": "arrow" を使用します。双方向リンクにするには、両端を "arrow" に設定します。
図形上で矢印を分散する
複数の矢印が同じ図形に接続する場合は、重なりを防ぐために異なる normalizedAnchor 点を割り当てます。
| 位置 | x | y | 使用する場面 |
|---|---|---|---|
| 上中央 | 0.5 | 0 | 上のノードに接続する場合 |
| 左上 | 0.25 | 0 | 上から2番目の接続 |
| 右上 | 0.75 | 0 | 上から3番目の接続 |
| 右中央 | 1 | 0.5 | 右側のノードに接続する場合 |
| 下中央 | 0.5 | 1 | 下のノードに接続する場合 |
| 左中央 | 0 | 0.5 | 左側のノードに接続する場合 |
ルール: 図形の一辺に N 本の接続がある場合は、等間隔に配置します(例:下側に3本の接続がある場合 → x = 0.25, 0.5, 0.75)。
同じ2つのノード間に複数の矢印を配置する
上記のアンカー分散ルールは、異なるノードに向かう矢印を分散させます。N本の矢印が同じペア(例:双方向のリクエスト/レスポンス、または A↔B 間の複数の関係)に接続する場合、アンカーでは分離できません。その代わりに、bend の値を対称に分散させて、矢印が異なる弧を描くように広げます。
- 最大の曲がり量
amountを決めます(約30~60。ノード間の距離が大きい場合は大きめにします)。 - N本の矢印に、
−amountから+amountまで等間隔で曲がり量を割り当てます。- 2本の矢印 →
bend: -amount、bend: +amount - 3本の矢印 →
bend: -amount、0、+amount - 一般式:
bend[i] = -amount + i * (2*amount / (N-1))(i = 0..N-1)
- 2本の矢印 →
- 直線の矢印と、曲線の矢印(
bend: 0とbend: 40)を1本ずつ組み合わせると、リクエスト/レスポンスのペアをすっきり表現できます。
コンテナーと注釈の図形
技術図では、geo と arrow に加えて、さらに2種類の図形が便利です。
フレーム(ラベル付きコンテナー — 階層、サブシステム、スイムレーン)
frame は、タイトル付きのネイティブな長方形コンテナーです。階層やサブシステムを見える境界線でグループ化する場合に使用します。複数のフレームを重ねることで、スイムレーンを表現できます。
{
"id": "shape:frame1", "typeName": "shape", "type": "frame",
"parentId": "page:page1", "index": "a1",
"x": 60, "y": 60, "rotation": 0, "isLocked": false, "opacity": 1, "meta": {},
"props": { "w": 360, "h": 220, "name": "Backend Tier", "color": "black" }
}
props.nameは、フレームの左上に表示されるタイトルです。- 子図形の
"parentId"は"shape:frame1"に設定します(page:page1ではありません)。また、子図形のx/yはページではなく、フレームの左上隅を基準とした相対位置です。x: 40, y: 60の子図形は、フレームの原点から右に40px、下に60pxの位置に配置されます。 - フレームは、手描き風ではないすっきりした長方形として描画されるため、構造のグループ化に適しています。矢印は通常どおり、フレームをまたいで接続できます。
ノート(付箋の注釈/吹き出し)
note は付箋です。TODO、吹き出し、図に重ねるコメントに最適です。
{
"id": "shape:n1", "typeName": "shape", "type": "note",
"parentId": "page:page1", "index": "a4",
"x": 480, "y": 80, "rotation": 0, "isLocked": false, "opacity": 1, "meta": {},
"props": { "color": "yellow", "size": "m", "text": "TODO: add retry\nlogic here",
"font": "draw", "align": "middle", "verticalAlign": "middle",
"growY": 0, "fontSizeAdjustment": 0, "url": "", "scale": 1, "labelColor": "black" }
}
- ノートに
w/hはありません。固定サイズの正方形(約200px)で、テキストが長い場合は自動的に大きくなります。w/hは追加しないでください。 yellowは標準的な付箋の色です。パレットのどの色でも使用できます。- ノートは控えめに使い、図の主要なノードではなく、図に対する注釈に使用してください(主要なノードには
geoを使用します)。
インデックスの順序ルール
インデックスは z 順(重なり順)を制御します。次の順序を使用してください。
a1, a2, a3, a4, a5, a6, a7, a8, a9,
aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, aM,
aN, aO, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ,
aa, ab, ac, ... az ← continue here past aZ; never "a10"
- ジオメトリ図形を先に配置します:
a1からaFまで(必要な数だけ)。 - 矢印図形はその後に配置します:
aG、aHなど。 - すべての図形に一意のインデックスを付ける必要があります。
レイアウトのヒント
間隔 — 複雑さに応じて調整します:
| 図の複雑さ | ノード数 | 水平方向の間隔 | 垂直方向の間隔 |
|---|---|---|---|
| シンプル | ≤5 | 200px | 150px |
| 中程度 | 6–10 | 280px | 200px |
| 複雑 | >10 | 350px | 250px |
ラベルに合わせたボックスのサイズ設定(セルフチェックではなく、最初に行います): draw フォントは幅が広いため、テキストが切れないよう、ラベルから w/h を計算します。デフォルトの draw フォントにおける、おおよその文字幅と行の高さは次のとおりです:
size | 文字幅(px) | 行の高さ(px) |
|---|---|---|
s | 11 | 18 |
m(デフォルト) | 15 | 28 |
l | 22 | 40 |
xl | 32 | 56 |
各辺の padding = 16 とします:
w = ceil(最長行の文字数 * 文字幅 + 2*padding)とし、次の10の倍数に切り上げます。h = ceil(行数 * 行の高さ + 2*padding)とし、10の倍数に切り上げます。
例:サイズがmで、ラベルが"API Gateway"のボックス(11文字、1行)の場合 → w ≈ 11*15 + 32 = 197 → 200、h ≈ 28 + 32 = 60。複数行のラベル(\nを含む)の場合、wには最長の行を、hには行数を使います。少し大きめにする分には問題ありません。余白が増えるだけですが、ボックスの幅が狭すぎると単語が文字の途中で折り返されます。
これが重要な理由:ボックスの高さがテキストに対して足りない場合、tldraw はレンダリング時に黙ってボックスを縦に拡張します(図形の growY が設定されます)。そのため、ボックスは指定した h より大きくなり、下に配置した要素と重なってしまいます。最初に適切なサイズを設定すれば、growY を0に保ち、レイアウトを維持できます。これは、エクスポート後に「図が窮屈に見える/ボックスが重なる」最もよくある原因です。
**ルーティング用の通路:**図形の行や列の間には、矢印がほかの図形を横切らずに通れるよう、約80pxの空き通路を追加で確保します。矢印が通る必要のある隙間には、図形を配置しないでください。
グリッドへの整列:すべての x、y、w、h の値を10の倍数に合わせます。これは tldraw のデフォルトの gridSize: 10 と一致し、手動編集がしやすくなります。
一般的なルール:
x/y座標を割り当てる前にグリッドを計画し、まずノードの位置を頭の中でスケッチします。- 関連するノードは、同じ水平または垂直の帯にまとめます。
- 接続が多い「ハブ」ノードは中央に配置し、矢印が交差せずに外側へ放射状に伸びるようにします。
- API Gateway など、下流の複数のサービスにまたがる幅広の図形は、全体を覆うように
wを設定します。 - 子ノードは親ノードの真下に中央揃えで配置し(中心のx座標を同じにし)、斜めのルーティングを避けます。
- イベントバスのパターン:バス(六角形)はサービスの行の下ではなく、中央に配置します。左右のサービスから短い水平矢印で接続でき(左側は
normalizedAnchor.x = 1、右側は0)、交差をなくせます。 - 同じ行にある垂直ノードと交差しない水平接続は、ピアツーピア接続やパブリッシュ接続に使用します。
矢印と図形の重なりを避ける:
- 座標を確定する前に、矢印の経路を頭の中でたどります。無関係な図形を横切る必要がある場合は、図形を移動するか、
bendを使って迂回させます。 - ツリー型/階層型のレイアウトでは、ノードをレイヤー(行)に分け、交差を最小限にするため、隣接するレイヤー間だけを接続します。
- スター型/ハブ型のレイアウトでは、ハブを中央に、サテライトをその周囲に配置し、矢印が短く放射状に伸びるようにします。
図の種類別プリセット
ユーザーが特定の図の種類を指定した場合は、図形、色、レイアウトの規則について、以下の該当するプリセットを適用します。
アーキテクチャ図
| 要素 | geo | color | 備考 |
|---|---|---|---|
| クライアント(Web/モバイル) | rectangle | blue | 最上段に配置し、クライアントの種類をラベルで示します |
| サービス/モジュール | rectangle | blue | 中段に配置し、階層ごとにグループ化します |
| データベース | ellipse | green | 最下段に配置し、サービスごとに1つ設けます |
| キャッシュ | ellipse | yellow | 対応するサービスの隣に配置します |
| キュー/イベントバス | hexagon | orange | ハブパターンでは、サービス段の中央に配置します |
| ゲートウェイ/ロードバランサー | triangle | violet | サービスの上に配置します |
| 外部 API | cloud | red | キャンバスの端に配置し、破線の矢印を向けます |
| 認証/セキュリティ | rectangle | violet | 多くの場合、ゲートウェイの近くに配置します |
レイアウト: 階層の数に応じて TB または LR を使います。階層が4つ以上の場合は TB にします。ハブノードは中央に配置します。間隔は複雑さに応じて調整します(上の表を参照)。
フローチャート
| 要素 | geo | color | 備考 |
|---|---|---|---|
| 開始/終了 | ellipse | green | 常に最上部と最下部に配置します |
| 処理ステップ | rectangle | blue | デフォルトのアクションボックスです |
| 判断 | diamond | yellow | 出ていく矢印には必ずラベル(Yes/No)を付けます |
| 入出力 | rectangle(dash: dashed を指定) | orange | 破線の枠で処理ステップと区別します |
| サブプロセス | rectangle | violet | 呼び出し可能なサブフローを示します |
レイアウト: TB、垂直方向の間隔は約200pxです。判断から左右に分岐し、その後、中央に合流させます。判断分岐には、矢印の props.text で必ずラベルを付けます。
シーケンス図
tldraw にはライフラインのネイティブ図形がありません。次のように近似します。
| 要素 | geo | color | 備考 |
|---|---|---|---|
| アクター/オブジェクトのヘッダー | rectangle | blue | 列の最上部に配置します |
| ライフライン | rectangle(w: 2、fill: solid、color: grey) | grey | 各アクターヘッダーの下に引く細い垂直線です |
| 同期メッセージ | arrowheadEnd: arrow を指定した矢印 | black | 実線の水平矢印です |
| 非同期メッセージ | dash: dashed を指定した矢印 | black | 破線の水平矢印です |
| 戻りメッセージ | dash: dashed、color: grey を指定した矢印 | grey | 灰色の破線です |
レイアウト: アクターは LR(間隔は200~280px)、時間は TB にします。各メッセージは、y を大きくしながら、2本のライフライン間に水平矢印として配置します。
ML/ディープラーニングモデル図
ニューラルネットワークのアーキテクチャ図に使用します。論文の図や解説に便利です。
| 要素 | geo | color | 備考 |
|---|---|---|---|
| 入力/出力 | rectangle | green | スタックの上端と下端に配置します |
| 畳み込み/プーリング | rectangle | blue | 標準的なレイヤーブロックです |
| アテンション/Transformer | rectangle | violet | Self-Attention ブロックを区別する色です |
| RNN/LSTM/GRU | rectangle | yellow | 再帰レイヤーです |
| FC/線形 | rectangle | orange | 全結合の射影レイヤーです |
| 損失/活性化 | rectangle | red | 最終的な損失/softmax/活性化です |
| スキップ接続 | bend: 30、dash: dashed を指定した矢印 | grey | 曲線の破線で迂回します |
テンソル形状の注釈: 2行目に次元を含め、props.text に記述します。tldraw は JSON 文字列内の \n をそのまま表示するため、実際の改行を使います(JSON エンコーダーが \n を出力します)。
"text": "Conv2D\n(B, 64, 32, 32)"
レイアウト: TB(データは上から下へ流れます)、レイヤー間隔は約150pxです。スキップ接続はメインスタックを迂回するように曲げます。
ER 図(ERD)
tldraw にはテーブル/行のネイティブシェイプがありません。各エンティティを、複数行テキストを含む縦長の長方形で近似します。
| 要素 | geo | color | 備考 |
|---|---|---|---|
| エンティティ | rectangle(fill: solid、color: light-blue) | light-blue | タイトルと列を、1つの複数行テキストラベルとして配置 |
| 列リスト | props.text に埋め込み、行の間に \n を挿入 | — | PK は接頭辞 *、FK は接頭辞 > で示します |
| リレーションシップ | arrowheadStart: arrow、arrowheadEnd: arrow を指定した矢印 | black | 多対多の場合は両端に矢印を付けます |
| オプション/弱いリレーションシップ | dash: dashed を指定した矢印 | grey | オプションの FK は破線で示します |
矢印に、props.text で多重度(例:1..*、0..1)のラベルを付けます。
レイアウト: TB またはグリッド。列リストを配置するスペースを確保するため、エンティティ間は 300px 以上離します。
UML クラス図
| 要素 | geo | color | 備考 |
|---|---|---|---|
| クラス | rectangle(fill: solid、color: light-blue) | light-blue | タイトル、属性、メソッドを1つの複数行 text として配置 |
| 継承 | arrowheadEnd: triangle を指定した矢印 | black | tldraw では塗りつぶされた triangle の矢印ヘッドが描画されます。親クラスに向けます |
| コンポジション | arrowheadStart: diamond、arrowheadEnd: none を指定した矢印 | black | tldraw では塗りつぶされた diamond の矢印ヘッドが描画されます。所有者(全体)側に配置します |
| 集約 | arrowheadStart: diamond を指定した矢印 | black | 同じダイヤモンド型の矢印ヘッドを使います。ラベルまたは注記でコンポジションと区別します |
| 関連 | arrowheadEnd: arrow を指定した矢印 | black | 標準の矢印 |
注: tldraw の triangle/diamond の矢印ヘッドは塗りつぶしですが、厳密な UML では中抜きの三角形(継承)と、塗りつぶしまたは中抜きのダイヤモンド(コンポジション/集約)が使われます。スケッチや解説では問題なく読み取れますが、中抜きの矢印ヘッドを使った公開品質の UML を作成する場合は、drawio-skill(別スキル)のほうが適しています。
レイアウト: TB。クラス間は約 250px 離し、インターフェースは実装クラスの上に配置します。
エクスポートコマンド
# Check CLI version
tldraw --version
# PNG at 2x scale (recommended) — outputs diagram.png in ./
tldraw export diagram.tldr -f png --scale 2 -o ./
# SVG — outputs diagram.svg in ./
tldraw export diagram.tldr -f svg -o ./
# Transparent background
tldraw export diagram.tldr -f png --scale 2 --transparent -o ./
# Dark theme
tldraw export diagram.tldr -f png --scale 2 --dark -o ./
# Custom output directory (e.g. CI artifacts dir) — create if missing, then export there
mkdir -p ./artifacts && tldraw export diagram.tldr -f png --scale 2 -o ./artifacts/
注: -o は出力先のディレクトリであり、ファイルパスではありません。出力ファイル名は入力ファイル名に基づきます(diagram.tldr → diagram.png)。
エクスポート後に自動で起動
ユーザーのデフォルトの tldraw ビューアー/エディターで .tldr ファイルを開くよう提案します。
| OS | コマンド |
|---|---|
| macOS | open diagram.tldr |
| Linux | xdg-open diagram.tldr |
| Windows | start diagram.tldr |
または、https://tldraw.com にアップロードし(.tldr ファイルをドラッグ&ドロップ)、ブラウザーで編集します。
よくあるミス
| ミス | 対処方法 |
|---|---|
tldraw コマンドが見つからない | npm install -g @kitschpatrol/tldraw-cli を実行します |
エクスポート時に Could not find Chrome (ver. X) が表示される | 固定されたビルドをインストールします:npx puppeteer browsers install chrome@X(エラーに表示された正確なバージョンを使用します) |
エクスポート時に invalidRecords が表示される | 1 文字の a キー(a1…a9、aA…aZ、aa…az)を使用します。a10、b1、c1 は不正な小数インデックスキーです |
| エクスポート結果が空白/空になる | document:document と page:page1 のレコードがあることを確認します |
| 出力ファイルが見つからない | -o はディレクトリです。ファイル名は入力と一致します:tldraw export foo.tldr -o ./ → ./foo.png |
| 矢印が表示されない | "type": "binding" と boundShapeId を使用します。矢印の x/y を 0,0 に設定します |
| 図形が重なっている | x/y を割り当てる前に、200px 以上のグリッドを計画します。複雑さに応じて間隔を広げます |
| ボックスが想定より高い/下の図形と衝突する | ラベルが小さすぎるボックスからはみ出したため、tldraw が自動的にサイズを拡大しました(growY)。サイズ計算式を使って、あらかじめラベルに合わせて w/h を設定します |
| テキストが表示されない | props.text が設定されていることを確認します。fill: "none" の場合は、テキストの色に十分なコントラストがあることを確認します |
| インデックスが衝突している | すべての図形で、一意の index 値を使用する必要があります |
| 図形 ID が重複している | 一意の ID を使用します:"shape:s1"、"shape:s2"、"shape:a1" など |
| エクスポートに失敗する | .tldr ファイルが有効な JSON であることを確認します:python3 -m json.tool file.tldr > /dev/null |
| 複数行のラベル | JSON 文字列内で実際の改行文字を使用します("text": "Line1\nLine2")。tldraw は \n を認識します |
| 矢印が図形を横切る | bend を使って曲線を描くか、別の normalizedAnchor に終点を移動します |
| 反復ループが終わらない | 5 ラウンド後、微調整のために .tldr を tldraw.com で開くようユーザーに提案します |
フォールバック手順
ツールを利用できない場合は、段階的に機能を縮小します:
| シナリオ | 動作 |
|---|---|
tldraw-cli がない | .tldr JSON のみを生成し、https://tldraw.com にドラッグ&ドロップするか、CLI をインストールするようユーザーに案内します |
| セルフチェックにビジョンを利用できない | セルフチェック(ステップ 5)を省略し、エクスポートした PNG をすぐにユーザーに表示します |
| エクスポートに失敗する | python3 -m json.tool で JSON を検証し、.tldr ファイルを渡して tldraw.com で開くよう提案します |