From logseq
Create and edit LogSeq Whiteboard files (.edn) with shapes, connectors, portals, and embeds on an infinite canvas. Use when working with whiteboard .edn files in a LogSeq graph, creating visual diagrams, mind maps, or spatial canvases, or when the user mentions LogSeq whiteboards.
How this skill is triggered — by the user, by Claude, or both
Slash command
/logseq:logseq-whiteboardsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
LogSeq Whiteboards are infinite spatial canvases stored as `.edn` (Extensible Data Notation) files. Built on a custom fork of tldraw, they combine freeform drawing with LogSeq's knowledge graph — allowing you to place pages, blocks, shapes, connectors, images, and web embeds together on a visual canvas.
LogSeq Whiteboards are infinite spatial canvases stored as .edn (Extensible Data Notation) files. Built on a custom fork of tldraw, they combine freeform drawing with LogSeq's knowledge graph — allowing you to place pages, blocks, shapes, connectors, images, and web embeds together on a visual canvas.
Whiteboard files are stored in the whiteboards/ directory of a LogSeq graph:
my-graph/
├── journals/
├── pages/
├── whiteboards/ ← Whiteboard .edn files here
│ ├── My Diagram.edn
│ └── Project Board.edn
├── assets/ ← Images referenced by whiteboards
└── logseq/
└── config.edn ← Can customize :whiteboards-directory
The directory name can be changed in config.edn via :whiteboards-directory.
Every whiteboard .edn file has two top-level sections: :blocks (shapes) and :pages (canvas metadata).
{:blocks (
;; Each shape is a block with :logseq.tldraw.shape properties
{:block/created-at 1728698317371
:block/properties
{:ls-type :whiteboard-shape
:logseq.tldraw.shape
{:type "text"
:id "unique-uuid"
:point [100 200]
:size [300 50]
;; ... shape-specific properties
}}
:block/updated-at 1728698317371}
;; More shape blocks...
)
:pages (
;; One page entry per whiteboard
{:block/uuid #uuid "page-uuid-here"
:block/properties
{:ls-type :whiteboard-page
:logseq.tldraw.page
{:id "page-uuid-here"
:name "whiteboard-name"
:bindings {}
:nonce 1
:assets []
:shapes-index ("shape-id-1" "shape-id-2" "shape-id-3")}}
:block/type "whiteboard"
:block/name "whiteboard-name"
:block/original-name "Whiteboard Name"
:block/created-at 1728698317371
:block/updated-at 1728698317371}
)}
LogSeq whiteboards support 8 shape types:
| Type | Description |
|---|---|
"text" | Text labels and paragraphs |
"box" | Rectangles with optional labels |
"line" | Lines and arrows (connectors) |
"pencil" | Freehand drawings |
"image" | Images (references assets) |
"logseq-portal" | Embedded LogSeq pages or blocks |
"youtube" | Embedded YouTube videos |
"iframe" | Embedded web pages |
All shapes share these properties within :logseq.tldraw.shape:
| Property | Type | Description |
|---|---|---|
:type | String | Shape type (see table above) |
:id | String | Unique UUID for this shape |
:point | [x y] | Position (top-left corner) on canvas |
:size | [width height] | Dimensions in pixels |
:index | Integer | Z-order (rendering layer, higher = on top) |
:scale | [sx sy] | Scale factors (usually [1 1]) |
:opacity | Number | Opacity 0.0 to 1.0 |
:rotation | Number | Rotation in radians (0 = no rotation) |
:parentId | String | Parent shape ID (page ID for top-level shapes) |
:nonce | Integer | Timestamp for change tracking |
Text labels and headings on the canvas.
{:logseq.tldraw.shape
{:type "text"
:id "uuid-here"
:point [100 200]
:size [300 50]
:text "Hello World"
:fontSize 32 ;; Font size in pixels
:fontFamily "'Inter'" ;; Font family (CSS)
:fontWeight 700 ;; 400 = normal, 700 = bold
:italic false ;; Italic text
:lineHeight 1.2 ;; Line height multiplier
:isSizeLocked true ;; Size auto-adjusts to text
:scaleLevel "lg" ;; "xs", "sm", "md", "lg", "xl"
:padding 4 ;; Internal padding
:stroke "var(--tl-foreground, #000)"
:fill "#ffffff"
:noFill true ;; true = transparent background
:strokeType "line"
:strokeWidth 2
:borderRadius 0
:index 0
:scale [1 1]
:opacity 1
:parentId "page-uuid"
:nonce 1664366266517}}
Scale levels control default font sizes:
| Level | Typical fontSize |
|---|---|
"xs" | 12 |
"sm" | 16 |
"md" | 20 |
"lg" | 32 |
"xl" | 48 |
Rectangles for containers, cards, and labeled shapes.
{:logseq.tldraw.shape
{:type "box"
:id "uuid-here"
:point [0 0]
:size [1071 578]
:label "" ;; Text label inside box (can be empty)
:stroke "#ababab" ;; Border color
:fill "var(--ls-secondary-background-color)" ;; Fill color
:noFill false ;; false = filled, true = transparent
:strokeType "line" ;; "line" or "dashed"
:strokeWidth 2
:borderRadius 2 ;; Corner rounding in pixels
:fontSize 20 ;; Label font size
:fontWeight 400
:italic false
:rotation 0
:index 1
:scale [1 1]
:opacity 1
:parentId "page-uuid"
:nonce 1664366266231}}
Lines connect shapes with optional arrowheads and labels.
{:logseq.tldraw.shape
{:type "line"
:id "uuid-here"
:point [2824 284] ;; Base point (origin for handles)
:stroke "var(--ls-primary-text-color, #000)"
:fill "var(--ls-secondary-background-color)"
:noFill true
:strokeType "line" ;; "line" or "dashed"
:strokeWidth 1
:label "" ;; Text label on the line
:fontSize 20
:fontWeight 400
:italic false
:handles ;; Start and end points (relative to :point)
{:start
{:id "start"
:canBind true ;; Can snap to other shapes
:point [0 0] ;; Relative position [x y]
:bindingId nil} ;; UUID of bound shape (nil = unbound)
:end
{:id "end"
:canBind true
:point [52 0] ;; End point relative to base
:bindingId nil}}
:decorations ;; Arrowheads
{:start nil ;; nil or "arrow"
:end "arrow"} ;; nil or "arrow"
:index 28
:scale [1 1]
:opacity 1
:parentId "page-uuid"
:nonce 1664464964296}}
Decorations: Set :start and/or :end to "arrow" for arrowheads. Use nil for no arrowhead.
Bindings: When a line connects to a shape, :bindingId references the bound shape's ID. The :bindings map in the page metadata tracks these connections.
Freehand strokes from the pencil tool.
{:logseq.tldraw.shape
{:type "pencil"
:id "uuid-here"
:point [212 160] ;; Base position
:points [[0 0 0.5]] ;; Array of [x y pressure] points (relative)
:stroke "" ;; Stroke color (empty = theme default)
:fill ""
:noFill true
:strokeType "line"
:strokeWidth 2
:scaleLevel "md"
:isComplete true ;; true when stroke is finished
:index 0
:scale [1 1]
:opacity 1
:parentId "page-uuid"
:nonce 1730788259525}}
Each point in :points is [x y pressure] where:
x, y are relative to the shape's :pointpressure is pen pressure (0.0 to 1.0, typically 0.5 for mouse)Images reference assets stored in the graph's assets/ directory.
{:logseq.tldraw.shape
{:type "image"
:id "uuid-here"
:point [136 200]
:size [260 105]
:assetId "asset-uuid" ;; References asset in page's :assets array
:isAspectRatioLocked true ;; Preserve aspect ratio on resize
:isLocked false ;; Prevent accidental moves
:objectFit "fill" ;; "fill", "contain", "cover"
:clipping 0 ;; Clipping amount
:index 0
:scale [1 1]
:opacity 1
:parentId "page-uuid"
:nonce 1770432010158}}
Assets are defined in the page's :assets array:
:assets [
{:id "asset-uuid"
:type "image"
:src "../assets/image_1770432010069_0.png" ;; Relative path
:size [520 210]}] ;; Original dimensions
The unique LogSeq feature — embed pages or blocks from your graph directly onto the whiteboard.
{:logseq.tldraw.shape
{:type "logseq-portal"
:id "uuid-here"
:point [256 168]
:size [400 141]
:blockType "P" ;; "P" = page portal, "B" = block portal
:pageId "PageName" ;; Page name (for page portals)
;; :blockId "block-uuid" ;; Block UUID (for block portals)
:collapsed false ;; true = show only title
:collapsedHeight 0 ;; Height when collapsed
:compact false ;; Compact display mode
:isAutoResizing true ;; Auto-resize to fit content
:stroke ""
:fill ""
:noFill false
:strokeType "line"
:strokeWidth 2
:borderRadius 8
:scaleLevel "md"
:index 2
:scale [1 1]
:opacity 1
:parentId "page-uuid"
:nonce 1731296148685}}
Portal types:
blockType: "P"): Uses :pageId — embeds an entire pageblockType: "B"): Uses :blockId — embeds a single block and its childrenPortals render live LogSeq content. Editing the portal edits the actual page/block.
Embed YouTube videos on the canvas.
{:logseq.tldraw.shape
{:type "youtube"
:id "uuid-here"
:point [7383 321]
:size [283 159]
:url "https://www.youtube.com/watch?v=VIDEO_ID"
:rotation 0
:index 49
:scale [1 1]
:parentId "page-uuid"
:nonce 1664531347941}}
Embed any web page on the canvas.
{:logseq.tldraw.shape
{:type "iframe"
:id "uuid-here"
:point [7730 321]
:size [282 158]
:url "https://logseq.com/"
:rotation 0
:index 50
:scale [1 1]
:parentId "page-uuid"
:nonce 1664531425980}}
The :pages section contains canvas-level metadata:
{:block/uuid #uuid "page-uuid"
:block/properties
{:ls-type :whiteboard-page
:logseq.tldraw.page
{:id "page-uuid"
:name "whiteboard-name" ;; Lowercase page name
:bindings {} ;; Shape-to-shape binding map
:nonce 1 ;; Change counter
:assets [ ;; Image assets used by shapes
{:id "asset-uuid"
:type "image"
:src "../assets/filename.png"
:size [width height]}]
:shapes-index ("id1" "id2")}} ;; Ordered list of shape IDs
:block/type "whiteboard"
:block/name "whiteboard-name" ;; Lowercase
:block/original-name "Whiteboard Name" ;; Original case
:block/created-at 1728698317371
:block/updated-at 1728698317371}
:shapes-index controls the order shapes are listed. This is a list of shape IDs.
:bindings tracks connections between lines and shapes when :bindingId is set on line handles.
:assets stores metadata for images used by image shapes. The :src path is relative to the graph root.
Shapes support these color formats:
| Format | Example |
|---|---|
| Hex color | "#ababab", "#ffffff" |
| CSS variable | "var(--ls-primary-text-color, #000)" |
| Named color | "gray" |
| Empty (theme default) | "" |
Common CSS variables:
var(--ls-primary-text-color, #000) — primary textvar(--ls-secondary-background-color) — secondary backgroundvar(--tl-foreground, #000) — tldraw foreground:point is the top-left corner of each shape:size is [width height] in pixels:handles on lines are relative to the line's :pointA minimal whiteboard with a box, text label, and an arrow:
{:blocks (
{:block/created-at 1700000000000
:block/properties
{:ls-type :whiteboard-shape
:logseq.tldraw.shape
{:type "box"
:id "box-1"
:point [100 100]
:size [200 100]
:stroke "#ababab"
:fill "var(--ls-secondary-background-color)"
:noFill false
:strokeType "line"
:strokeWidth 2
:borderRadius 8
:label "My Box"
:fontSize 20
:fontWeight 400
:italic false
:rotation 0
:index 0
:scale [1 1]
:opacity 1
:parentId "page-1"
:nonce 1700000000000}}
:block/updated-at 1700000000000}
{:block/created-at 1700000000001
:block/properties
{:ls-type :whiteboard-shape
:logseq.tldraw.shape
{:type "text"
:id "text-1"
:point [100 50]
:size [200 30]
:text "Hello Canvas"
:fontSize 24
:fontFamily "'Inter'"
:fontWeight 700
:italic false
:lineHeight 1.2
:isSizeLocked true
:scaleLevel "lg"
:padding 4
:stroke ""
:fill ""
:noFill true
:strokeType "line"
:strokeWidth 2
:borderRadius 0
:index 1
:scale [1 1]
:opacity 1
:parentId "page-1"
:nonce 1700000000001}}
:block/updated-at 1700000000001}
{:block/created-at 1700000000002
:block/properties
{:ls-type :whiteboard-shape
:logseq.tldraw.shape
{:type "line"
:id "arrow-1"
:point [350 150]
:stroke ""
:fill ""
:noFill true
:strokeType "line"
:strokeWidth 1
:label ""
:fontSize 20
:fontWeight 400
:italic false
:handles
{:start
{:id "start"
:canBind true
:point [0 0]
:bindingId nil}
:end
{:id "end"
:canBind true
:point [100 0]
:bindingId nil}}
:decorations
{:end "arrow"}
:index 2
:scale [1 1]
:opacity 1
:parentId "page-1"
:nonce 1700000000002}}
:block/updated-at 1700000000002})
:pages (
{:block/uuid #uuid "00000000-0000-0000-0000-000000000001"
:block/properties
{:ls-type :whiteboard-page
:logseq.tldraw.page
{:id "page-1"
:name "my-diagram"
:bindings {}
:nonce 1
:assets []
:shapes-index ("box-1" "text-1" "arrow-1")}}
:block/type "whiteboard"
:block/name "my-diagram"
:block/original-name "My Diagram"
:block/created-at 1700000000000
:block/updated-at 1700000000002})}
{} for maps, () for lists, [] for vectors, :keyword for keys#uuid "..." reader literal:parentId to the page's UUID string:assets (page level) and a shape with matching :assetId:block/type "whiteboard"npx claudepluginhub jluo41/logseq-skills --plugin logseqCreate and edit Obsidian JSON Canvas (.canvas) files with nodes, edges, groups for mind maps, flowcharts, project boards, and visual note organization.
Creates and edits Obsidian JSON Canvas (.canvas) files with nodes, edges, groups for mind maps, flowcharts, and infinite visual diagrams.
Create and edit JSON Canvas files (.canvas) with nodes, edges, groups, and connections. Useful for mind maps, flowcharts, and visual canvases in Obsidian.