Skip to content

Latest commit

 

History

History
228 lines (182 loc) · 10.6 KB

File metadata and controls

228 lines (182 loc) · 10.6 KB

CLAUDE.md - AI Assistant Guide for draw.io Desktop

Project Overview

Draw.io Desktop is an Electron-based desktop application that wraps the core draw.io diagramming editor (included as a git submodule). It enables creating flowcharts, UML diagrams, and more, with a security-first design that isolates diagram data from the internet.

Repository: https://github.com/jgraph/drawio-desktop License: Apache 2.0 Version: see drawio/VERSION (stamped into package.json by npm run sync)

Quick Reference

# Clone (MUST be recursive for submodule)
git clone --recursive https://github.com/jgraph/drawio-desktop.git

# Install dependencies
npm install

# Run application
npm start

# Run with DevTools enabled
DRAWIO_ENV=dev npm start

# Sync version before building (required)
npm run sync

# Build for specific platforms
npm run release-win       # Windows x64
npm run release-linux     # Linux (AppImage, deb, rpm)
npm run release-appx      # Windows Store

Project Structure

drawio-desktop/
├── src/main/
│   ├── electron.js           # Main Electron process (3,700+ lines)
│   ├── electron-preload.js   # IPC bridge with contextBridge
│   ├── args.js               # CLI argument definitions and parser
│   ├── progress-bar.js       # Progress bar for long-running operations
│   └── disableUpdate.js      # Generated by sync script
├── src/test/
│   ├── cli-args.test.js      # CLI argument parsing tests (npm test)
│   └── msi-project-created.test.js # MSI shortcut icon hook tests (npm test)
├── drawio/                   # Git submodule - core draw.io editor
│   └── src/main/webapp/      # Web application loaded in Electron
├── build/                    # Build resources
│   ├── notarize.mjs          # macOS Quick Look setup, signing + notarization
│   ├── sign-trusted.mjs      # Windows signing hook (Azure Trusted Signing)
│   ├── fuses.mjs             # Electron security fuses
│   ├── msi-project-created.mjs # msiProjectCreated hook: MSI shortcuts use exe icon, not the C:\Windows\Installer icon cache
│   ├── dmg-hidden-files.mjs  # beforePack hook: parks hidden DMG support files outside the installer window
│   ├── quicklook-preview.html # Quick Look preview page (viewer-static.min.js)
│   ├── quicklook-entitlements.plist # Sandbox entitlements for .appex
│   └── entitlements.mac.plist
├── doc/
│   ├── RELEASE_PROCESS.md    # Release workflow documentation
│   ├── BUILDING_FOR_PERSONAL_USE.md # Guide for unsigned fork/personal builds
│   └── PLUGIN_SECURITY.md    # Rationale: why the signed app runs plugins + hardening notes
├── electron-builder-*.json   # Platform-specific build configs
├── sync.cjs                  # Version sync script
└── package.json

Tech Stack

  • Runtime: Node.js 22.12+ (engines in package.json; CI builds on Node 24)
  • Framework: Electron (version pinned in package.json)
  • Language: JavaScript (ES6 modules)
  • Build Tool: electron-builder
  • Package Manager: npm

Key Files

File Purpose
src/main/electron.js Main process: window management, IPC handlers, menus, auto-update
src/main/electron-preload.js Secure IPC bridge between renderer and main process
src/main/args.js CLI option definitions and argument parser (used by CLI export)
sync.cjs Pre-build script that syncs version from drawio/VERSION
electron-builder-*.json Platform-specific build configurations
build/sign-trusted.mjs electron-builder Windows signing hook (Azure Trusted Signing)

Code Style

  • ES6 modules with import/export
  • Tab indentation
  • Allman brace style (opening brace on new line)
  • camelCase for variables, PascalCase for classes
  • No ESLint/Prettier - manual style consistency
  • Sparse comments; code clarity preferred

Git Conventions

Branches

  • dev - Main development branch (PR target)
  • release - Production releases
  • releases/v*.*.* - Version-specific release branches

Commit Messages

  • Lowercase sentence style without period
  • Issue references: [jgraph/drawio-desktop#XXXX]
  • Examples:
    • Fixes paste error
    • Adds buffer as dependency [jgraph/drawio-desktop#2301]
    • Prepare release v29.3.0

Version Tags

Format: v{MAJOR}.{MINOR}.{PATCH} (e.g., v29.3.0) Tags trigger CI/CD build workflows.

Build Process

  1. Sync version: npm run sync reads drawio/VERSION and updates package.json
  2. Install: npm ci for clean install
  3. Build: electron-builder with platform-specific config
  4. Post-build: Security fuses applied, Quick Look extension assembled (macOS), notarization (macOS)

Code Signing

  • Windows: Azure Trusted Signing via the signtoolOptions.sign hook build/sign-trusted.mjs (configured in electron-builder-win*.json, not CSC_LINK certificates). CI (electron-builder-win.yml) downloads the signing dlib, locates signtool.exe, and authenticates with AZURE_TENANT_ID/AZURE_CLIENT_ID/AZURE_CLIENT_SECRET secrets
  • macOS: Apple Developer certificate + notarization in build/notarize.mjs
  • Unsigned builds: DRAWIO_UNSIGNED=true skips signing (Windows) and notarization (macOS) for personal/fork builds

Personal / Fork Builds

  • doc/BUILDING_FOR_PERSONAL_USE.md documents building unsigned from a fork (the project is closed to contributions but Apache 2.0 licensed)
  • Set DRAWIO_UNSIGNED=true and run electron-builder directly with --publish never; use npm run sync -- disableUpdate so auto-update doesn't replace the custom build
  • .github/workflows/personal-build.yml is a manual (workflow_dispatch) workflow that builds unsigned installers on a fork with no secrets and attaches them as run artifacts

CI override: The release build workflows check out the private jgraph/drawio-dev repo at its release branch, copy the built *.min.js and VERSION into the public drawio/ submodule tree, then run npm run sync as normal. This lets CI ship from an internal release that is ahead of the public drawio tag without any change to sync.cjs. Out-of-tree builders (who have no access to drawio-dev) fall through to the public submodule's VERSION as before.

Platform Build Commands

Command Target
npm run release-win Windows x64 (NSIS + MSI)
npm run release-win32 Windows 32-bit
npm run release-win-arm64 Windows ARM64
npm run release-linux Linux (AppImage, deb, rpm)
npm run release-appx Windows Store
npm run release-snap Snap package

Architecture Notes

Security Model

  • Content Security Policy prevents remote script execution
  • contextBridge exposes only specific APIs to renderer
  • validateSender() ensures IPC calls originate from local draw.io
  • No external transmission of diagram data

IPC Pattern

The preload script uses a request/response pattern with unique IDs:

// Renderer sends request
electron.request({action: 'save', data: ...}, callbackId);

// Main process handles and responds via IPC
ipcMain.on('request', (e, data) => { ... });

macOS Quick Look Preview

  • Pressing Space in Finder shows a rendered preview of .drawio files
  • Uses quicklookjs to embed a Quick Look App Extension (.appex) in the app bundle
  • The .appex loads viewer-static.min.js (with embedded shapes) in a WKWebView
  • Build flow: afterPack (fuses.mjs) applies security fuses, then afterSign (notarize.mjs) assembles the .appex, signs it with sandbox entitlements, re-signs the outer .app, and notarizes
  • The .appex is inserted in afterSign (not afterPack) so it is never present unsigned during electron-builder's signing verification
  • Quick Look extensions require app-sandbox, but Electron helpers must not be sandboxed — so the .appex gets different entitlements than entitlementsInherit
  • The UTI com.jgraph.drawio is declared via extendInfo in electron-builder-linux-mac.json
  • viewer-static.min.js is saved to build/ during CI before the cleanup step removes it from the drawio submodule; for local dev, it's read from the submodule directly

Auto-Update

  • Checks GitHub releases on startup
  • Disable via DRAWIO_DISABLE_UPDATE=true or --disable-update flag
  • Flatpak detection disables updates automatically

Data Storage

  • macOS: ~/Library/Application Support/draw.io
  • Windows: %APPDATA%\draw.io\
  • Uses electron-store for persistent settings

Testing

npm test runs the unit tests in src/test/ (CLI argument parsing, MSI shortcut icon hook; Node's built-in test runner). Everything else is manual testing, documented in doc/RELEASE_PROCESS.md:

  • Launch, create diagram, add shapes, save, open
  • Export (PNG, PDF, SVG)
  • Undo/redo functionality
  • About dialog verification

CI/CD Workflows

Workflow Trigger Purpose
electron-builder.yml Version tag macOS/Linux builds
electron-builder-win.yml Version tag Windows builds (Azure Trusted Signing)
prepare-release.yml Manual Automated release prep
hash-gen.yml Manual Generate checksums
personal-build.yml Manual Unsigned fork builds, artifacts only (no secrets, no publish)
stale.yml Schedule Mark stale issues/PRs

Important Constraints

  1. Recursive clone required - drawio submodule must be initialized
  2. Run npm run sync before building - Updates version from submodule
  3. Version source of truth - drawio/VERSION for public builds; drawio-dev/VERSION is copied over drawio/VERSION at CI time so the internal release number wins for packaged builds
  4. Closed to contributions - PRs not accepted; maintained by JGraph (forks for personal use are fine, see doc/BUILDING_FOR_PERSONAL_USE.md)
  5. Node 22.12+ required - see engines in package.json

Development Tips

  • Set DRAWIO_ENV=dev to auto-open DevTools
  • Use npm start --enable-logging for verbose output
  • If using symlink instead of submodule, also symlink node_modules
  • Main process logs to console; check terminal for errors

Key Dependencies

Package Purpose
electron Desktop app framework
electron-builder Build/package tool
electron-updater Auto-update mechanism
electron-store Persistent storage
electron-log Logging
@cantoo/pdf-lib PDF export
quicklookjs macOS Quick Look preview extension (dev)

CLI argument parsing is hand-rolled in src/main/args.js (no commander).