Thursday, March 26, 2026

I Built a Node-Based Visual Memo Board with Claude Code — Here's How

Digital Lab · Claude Code Build

I Built a Node-Based Visual Memo Board
with Claude Code — Here's How

March 2026  ·  8 min read  ·  Kai Lee · A7 Studio

#ClaudeCode #VisualMemo #NodeBased #AIBuilt #VanillaJS #Productivity
K
Kai Lee
Architect · BIM Specialist · A7 Studio
2026.03

What if your sticky notes could talk to each other? I asked Claude Code to build a node-based visual memo board from scratch — no frameworks, no libraries, just pure HTML, CSS, and vanilla JavaScript. Here's what came out of it.

01 — The Idea

As an architect who's been working with BIM tools for years, I'm obsessed with visual thinking. Revit, Dynamo, concept maps — I process information spatially. Standard to-do apps feel flat to me. I wanted something closer to a node graph: memos as floating cards, connected by arrows, rearranged freely on an infinite canvas.

So I opened Claude Code and typed a prompt. About 20 minutes later, I had a working app.

🧠 The prompt was simple: "Build a node-based visual memo board — floating sticky cards on an infinite canvas, with drag-to-connect arrows between nodes, zoom/pan, dark/light theme toggle, and localStorage persistence. Vanilla JS only."

02 — What It Looks Like

Here's a live mockup of the interface. The real app runs as a single self-contained .html file — no server, no install:

+ New Memo Reset View Clear All
🌙 Double-click → add memo  |  Port drag → connect  |  Scroll → zoom
n1 ×
Review BIM coordination
report before Friday
✓ Done
n2 ×
Update Revit family
library — done ✓
↩ Undo
n3 ×
Write blog post about
Claude Code workflow
✓ Done

03 — Core Features

🖱️
Infinite Canvas

Pan by dragging, zoom with scroll wheel. The canvas is 6000×6000px — room for hundreds of nodes.

📌
Floating Memo Nodes

Each memo is a draggable card. Double-click anywhere on the canvas to spawn a new one instantly.

🔗
Bezier Connections

Drag from any port (top/right/bottom/left) to draw smooth bezier arrows between nodes.

Done State

Mark memos complete with a glowing red strikethrough line. One click to undo.

🌙
Dark / Light Theme

Toggle between a deep space dark theme and a clean light mode. Preference saved locally.

💾
Auto-Save

Everything — nodes, edges, zoom level, pan position — saves to localStorage automatically.

04 — Under the Hood

The whole app is 614 lines of vanilla HTML/CSS/JS. No React, no Vue, no build step. Here's the architecture Claude designed:

  • 🎨
    CSS Custom Properties for Theming
    All colors live as :root variables. The light mode is a single html.light override block — toggling the class switches the entire theme instantly with transition: .3s.
  • 📐
    Transform-Based Pan & Zoom
    The canvas uses transform: translate() scale(). Mouse wheel events adjust the zoom factor (0.18× to 3×) while keeping the cursor as the zoom origin — exactly like Figma.
  • 〰️
    SVG Bezier Edges
    Connections are rendered as SVG <path> elements with cubic bezier curves. The control point distance is calculated dynamically based on node separation — tighter nodes get tighter curves.
  • 🧠
    Auto Side Detection
    When dropping a connection on a node (not a specific port), the app automatically picks the best source/target sides based on relative position — left-right if horizontal, top-bottom if vertical.
  • 💾
    localStorage Persistence
    The entire state (nodes array, edges array, counters, pan X/Y, zoom) is serialized to JSON and saved after every interaction. Reload the page — everything is exactly where you left it.
// State shape — what gets saved to localStorage // vmemo-v2 key stores the complete app state { nodes: [{ id, x, y, text, done }], edges: [{ id, from, fromSide, to, toSide }], nCount: number, // node ID counter eCount: number, // edge ID counter panX: number, panY: number, zoom: number // 0.18 – 3.0 }

05 — What Claude Code Got Right

I've been using Claude Code for a few months now as part of my BIM workflow — mostly for Dynamo scripts and data automation. This was my first pure front-end UI build with it, and a few things stood out:

The bezier curve math was spot-on on the first pass. Getting cubic bezier control points to feel natural — especially the auto-side detection — is genuinely tricky. Claude nailed it without any back-and-forth.

The CSS theming architecture was also cleaner than what I'd typically write myself. Using html.light as the single override selector means the component styles stay clean — you never have to duplicate rules for each theme.

⚠️ One thing I had to fix manually: the initial version had some duplicate CSS rule blocks (the dark defaults were written twice). Easy to clean up, but worth knowing — always review the output, especially for longer files.

614
Lines of Code
~20
Minutes to Build
0
Dependencies

06 — How I Use It in My Workflow

As a BIM coordinator, I often need to map out dependencies between tasks — which model element needs to be finalized before another discipline can proceed. A linear to-do list doesn't capture that. This memo board does.

I keep it open as a local HTML file during project coordination meetings. Nodes represent tasks or deliverables. Arrows represent dependencies. When something is done, the red strikethrough makes it visually obvious without removing the card.

The infinite canvas also means I can use spatial grouping — cluster related items together, spread unrelated items apart. Your eye naturally groups things by proximity. No tags or folders needed.

· · ·

If you work in architecture, engineering, or any field where thinking spatially matters — this kind of tool is worth trying. The fact that it's a single HTML file means you can drop it anywhere, share it with anyone, and it just works.

I'll be sharing more Claude Code builds here on the blog. Next up: a Dynamo script generator that takes natural language task descriptions and outputs ready-to-run Dynamo graphs. Stay tuned.

Want the source file?

Drop a comment below and I'll share the .html file directly.
No sign-up, no strings — just a single file that runs in any browser.

→ Leave a comment

No comments: