A node-based visual editor for outlining flows, ideas, pipelines, mindmaps, knowledge graphs, and spatial thinking.
Think spatially. Connect everything.
Nodepad replaces linear note-taking with a spatial canvas. Drag nodes, draw connections, and build visual structures for any kind of thinking — system architecture, user flows, research maps, brainstorms, or just messy creative exploration.
- Infinite canvas — Pan, zoom, and arrange ideas in 2D space
- Rich node types — Text, code, images, checklists, tables, links, groups, and more
- Connections — Bezier, straight, and step edges with labels and arrows
- Extensible — Plugin system for custom node types and behaviors
- Local-first — Your data stays on your machine. No account. No cloud required.
- Multi-canvas — Tabs for multiple canvases, each saved independently
- Dark & light themes — Polished UI with smooth transitions
- Command palette — Ctrl+K to access any action instantly
- Keyboard-first — Full keyboard shortcuts for power users
# Open Nodepad in your browser
npx nodepad
# Temporary scratchpad (saves to temp dir, prompts to save on close)
npx nodepad --temp
# Open a specific file
npx nodepad my-project.nodepad
# Custom port
npx nodepad --port 4000Download the latest release for your platform:
- macOS: Nodepad.dmg
- Windows: Nodepad-Setup.msi
- Linux: Nodepad.AppImage
The desktop app provides native file system access, system tray, file associations (.nodepad files), and auto-updates.
Visit nodepad.dev to use Nodepad directly in your browser. Data is stored locally in your browser (IndexedDB). Works offline via PWA.
- Double-click on the canvas to create a text node
- Use the toolbar (left side) to select a node type, then click to place
- Press N for quick node creation
- Drag and drop an image file onto the canvas to create an image node
- Hover over a node to reveal connection ports (circles on each side)
- Drag from a port to another node's port to create an edge
- Edges can be bezier (curved), straight, or stepped (right-angle)
| Action | Mouse | Keyboard |
|---|---|---|
| Pan | Middle-click drag / Space+drag | Arrow keys |
| Zoom | Scroll wheel / Pinch | Ctrl/Cmd + / - |
| Zoom to fit | — | Ctrl/Cmd + 0 |
| Select | Click | — |
| Multi-select | Shift+Click / Drag rectangle | — |
| Delete | — | Delete / Backspace |
| Undo | — | Ctrl/Cmd + Z |
| Redo | — | Ctrl/Cmd + Shift + Z |
| Duplicate | — | Ctrl/Cmd + D |
| Search | — | Ctrl/Cmd + F |
| Command Palette | — | Ctrl/Cmd + K |
| Save | — | Ctrl/Cmd + S |
| New Tab | — | Ctrl/Cmd + T |
| Type | Description |
|---|---|
| Text | Rich text with Markdown support |
| Note | Colored sticky note |
| Code | Syntax-highlighted code block |
| Image | Embedded image (URL or file) |
| Link | Web bookmark with title and favicon |
| Group | Container that holds other nodes |
| Checklist | Task list with checkboxes |
| Table | Tabular data grid |
| Anchor | Minimal waypoint for edge routing |
| Embed | Embedded web content (iframe) |
| Type | Style |
|---|---|
| Bezier | Smooth curves (default) |
| Straight | Direct lines |
| Step | Right-angle segments |
| Smoothstep | Rounded right-angle segments |
Nodepad saves files as .nodepad (JSON format). Files are human-readable and version-controlled friendly.
{
"version": "1.0.0",
"meta": { "title": "My Canvas", "created": "...", "modified": "..." },
"canvas": { "viewport": { "x": 0, "y": 0, "zoom": 1 }, "grid": { "type": "dot" } },
"nodes": [ ... ],
"edges": [ ... ]
}- PNG / SVG — Canvas as image
- JSON —
.nodepadfile - Markdown — Structured text export
Nodepad supports plugins for custom node types, edge types, commands, and behaviors.
import type { NodepadPlugin } from '@nodepad/core';
const myPlugin: NodepadPlugin = {
id: 'my-plugin',
name: 'My Plugin',
version: '1.0.0',
description: 'Adds custom functionality to Nodepad',
nodeTypes: [
{
type: 'my-custom-node',
label: 'Custom Node',
icon: '🔷',
defaultSize: { width: 200, height: 100 },
render(ctx, node, state) {
// Custom Canvas 2D rendering
},
},
],
commands: [
{
id: 'my-command',
label: 'Do Something',
execute(ctx) {
// Custom action
},
},
],
};
export default myPlugin;- Node.js 20+
- pnpm 9+
- Rust (for Tauri desktop app only)
git clone https://github.com/your-org/nodepad.git
cd nodepad
pnpm install# Start web app dev server
pnpm dev
# Start Tauri desktop app with hot reload
pnpm dev:desktop
# Build all packages
pnpm build
# Run tests
pnpm test
# Lint
pnpm lint
# Type check
pnpm typechecknodepad/
├── packages/
│ ├── shared/ # Types, utilities, constants
│ ├── core/ # Canvas engine, data model, plugin system
│ ├── storage/ # Storage abstraction (IndexedDB, filesystem)
│ └── ui/ # React components, hooks, stores
├── apps/
│ ├── web/ # Vite web app
│ ├── cli/ # npx nodepad CLI
│ └── desktop/ # Tauri desktop app
├── plugins/ # Built-in and example plugins
└── docs/ # Design documents
The codebase is a pnpm monorepo managed by Turborepo:
- @nodepad/core — Custom Canvas 2D engine with no React dependency. Handles rendering, interaction, hit testing, and the plugin system.
- @nodepad/ui — React layer using Zustand for state, shadcn/ui for components, Tailwind for styling. Wraps the canvas engine in React components.
- @nodepad/storage — Platform-agnostic storage interface with implementations for IndexedDB (web), filesystem (CLI/desktop), and temp storage.
- apps/web — Vite-bundled SPA deployed to the web.
- apps/cli — Express server that bundles the web app and serves it locally. Published to npm as
nodepad. - apps/desktop — Tauri v2 app wrapping the web frontend with native filesystem access.
- Fork the repo
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes
- Run
pnpm lint && pnpm test && pnpm buildto verify - Open a pull request
MIT