tldraw-skill について
tldraw-skillは、エージェントが手描き風のホワイトボード図を編集可能な.tldr JSONで作成し、@kitschpatrol/tldraw-cliでPNGまたはSVGに出力する手順を案内します。アーキテクチャやプロセスの図に対応し、プレビューと修正の流れも扱います。
主な機能
- 01.tldr JSON形式で図を生成
- 02PNGとSVGへのエクスポート
- 03多様な図形と矢印の利用
- 04プレビュー、確認、修正の手順
活用シーン
- 01サービスやモジュールの構成図
- 02複数段階の処理やデータフローの表示
- 03決定木やシーケンス図の作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ agents365-ai/ 365-skills --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 を推奨)、またはユーザーが簡単な Q&A のやり取りをしている場合。
使用しない場合 — 別のツールに切り替える:
- ロゴ/単色のグラフィック/塗りつぶしアイコン:tldraw には不透明な塗りつぶしがありません(
solidは薄い色合いで、暗い背景上の白い図形は再現できません)→ drawio スキルまたは元のベクターファイルを使用します。 - 正確なベクター形状や厳密な(中抜き矢印の)UML → drawio(または UML には plantuml)。
- 多数のノードの自動レイアウト → mermaid(tldraw では座標を手動で指定する必要があります)。
- 既存の画像をピクセル単位で忠実に再現する場合 → diagram-skill の対象ではありません。
前提条件
# Install tldraw-cli
npm install -g @kitschpatrol/tldraw-cli
# Verify
tldraw --version
macOS、Windows、Linux で同じように動作します。
初回エクスポート時の注意: tldraw export は、puppeteer 経由で固定された Chrome ビルドを使ってレンダリングします。初回のエクスポートでは、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 回だけ必要です。)
ワークフロー
開始する前に、ユーザーの依頼が十分に具体的か確認します。重要な詳細が不足している場合は、焦点を絞った質問を 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 を更新します |
| レイアウトの向きを変更 | 全体を再生成 — グリッドを再計画して作り直します |
ルール:
- 要素 1 つだけを変更する場合:既存の 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が発生します。上記の"a*"の 1 文字キーを使用してください。
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 | アクセント(技術図ではほとんど必要ありません) |
geo の値は 20 種類すべて有効です。上記は技術図で役立つものです。
カラーパレット
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 = デフォルトのホワイトボードスタイル |
Arrow レコード
{
"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"
}
}
Arrow の接続ルール
- Arrow レコードの
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}= 中央
- ラベル付きの接続には、arrow 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本 →
- まっすぐな矢印と1本の曲線矢印(
bend: 0とbend: 40)の組み合わせは、リクエスト/レスポンスのペアをすっきりと表現できます。
コンテナーと注釈の図形
geo と arrow に加えて、技術図ではさらに2種類の図形が便利です。
Frame(ラベル付きコンテナー — 階層、サブシステム、スイムレーン)
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(付箋注釈/吹き出し)
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" }
}
- Note に
w/hはありません。固定サイズの正方形(約200px)で、テキストが長い場合は自動で大きくなります。w/hは追加しないでください。 yellowは定番の付箋の色です。パレットの色はどれでも使用できます。- Note は控えめに使用し、図の説明用の注釈に限定してください。主要なノードには使用せず、
geoを使用します。
インデックスの順序ルール
インデックスで z-order(重なり順)を制御します。以下の順序を使用してください。
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"
- Geo 図形を先に配置します:
a1からaFまで(必要に応じてさらに追加します)。 - Arrow 図形はその後に配置します:
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 | 出ていく矢印には必ずラベルを付ける(はい/いいえ) |
| 入出力 | 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 | スタックの最上部と最下部 |
| Conv/Pooling | rectangle | blue | 標準のレイヤーブロック |
| Attention/Transformer | rectangle | violet | Self-attentionブロックを区別する色 |
| RNN/LSTM/GRU | rectangle | yellow | 再帰レイヤー |
| FC/Linear | rectangle | orange | 全結合の射影レイヤー |
| Loss/Activation | 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つの複数行テキストラベルとして表示 |
| 列リスト | 行の間に \n を入れて props.text に埋め込む | — | 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 で開くよう提案します |