The world's first open-source AI-native vector design tool and the first to feature concurrent Agent Teams. Design-as-Code. Turn prompts into UI directly on the live canvas. A modern alternative to Pencil.
Find a file
Kayshen Xu 3b00d5564d
V0.0.1 (#4)
* feat(canvas,panels): multi-selection drag, shift-key selection, and chat pipeline UI

- Preserve multi-selection when clicking a selected object without Shift,
  enabling drag-move of the whole set
- Set selectionKey to shiftKey so only Shift+click toggles multi-select
- Refactor chat-message step rendering: extract step blocks with regex,
  add pipeline checklist progress UI, separate step display from markdown
- Adjust AI chat panel selection count display and layout

* feat(opencode): integrate OpenCode SDK for enhanced AI interactions

- Add support for OpenCode as a new AI provider, allowing users to connect to a local OpenCode server.
- Implement new API endpoints for generating and streaming chat responses via OpenCode.
- Update UI components to include OpenCode in provider selection and display.
- Introduce OpenCode logo and enhance the agent settings dialog to manage OpenCode connections.
- Refactor existing chat and generation logic to accommodate provider-specific routing.
- Include type definitions for OpenCode SDK to ensure type safety and improve developer experience.

* feat(electron): integrate Electron framework for desktop application support

- Add Electron configuration and main process setup for building a desktop application.
- Implement IPC communication for file operations (open, save) between the renderer and main processes.
- Create a preload script to expose Electron APIs to the renderer.
- Update package.json to include Electron and related dependencies.
- Enhance the build process with electron-builder for packaging the application.
- Introduce a new electron-builder.yml configuration file for build settings.
- Modify Vite configuration to support Electron-specific builds.
- Update UI components to accommodate Electron's window management and drag regions.

* fix(canvas): multi-selection drag reparenting and infinite recursion guard

- Add re-entry guard to object:modified handler to prevent infinite
  recursion caused by discardActiveObject() firing object:modified
  via _finalizeCurrentTransform
- Extend drag-into detection to non-layout root frames (rootFrameBounds)
  in addition to layout containers (layoutContainerBounds)
- Add checkReparentIntoFrame() fallback for root-level objects dragged
  into frames, handling both layout and non-layout targets
- Redirect _currentTransform to ActiveSelection in mouse:down so the
  whole group moves/scales/rotates together
- Support same-container reorder in commitDragIntoMulti
- Fix guide-utils getEdges() for center-origin ActiveSelection objects
- Track selection descendants for visual drag-follow during multi-drag
- Show position coordinates during multi-selection drag in dimension label

* feat(store,canvas): add reusable component and instance system

add makeReusable/detachComponent store methods, RefNode resolution in
canvas sync with component/instance selection borders, virtual child ID
handling in selection context, purple/instance-colored frame labels,
and collision avoidance when duplicating nodes

* feat(panels): add component/instance UI to layer and property panels

layer panel shows diamond icon and purple/#9281f7 styling for
components/instances with context menu actions; property panel resolves
RefNode display, routes instance overrides, adds header with go-to and
detach buttons, and supports inline name editing on click

* feat(canvas): match hover outline to selection style for components and instances

hover outlines now use purple solid for reusable components and #9281f7
dashed for instances, consistent with their selection border styling

* fix(editor): save directly without dialog for previously opened files

prioritize fileName check over File System Access API so opened files
save via download without showing a file picker; also add Cmd+Alt+K
shortcut for creating reusable components

* refactor(canvas): remove dimension label overlay

remove the blue dimension/position label that appeared on selection,
drag, and scale interactions

* feat(export): add export section for raster image export functionality

- Introduce a new ExportSection component to facilitate exporting layers as raster images in various formats (PNG, JPEG, WEBP) with adjustable scale options.
- Integrate the ExportSection into the PropertyPanel for easy access during design editing.
- Enhance export utility functions to support exporting layers and managing descendant nodes.

* feat(assets): add new icon files for application branding

- Introduce new icon files in various formats (ICNS, ICO, PNG) for application branding.
- Add logo image for the Electron interface to enhance visual identity.
- Update canvas selection logic to allow programmatic selection from the layer panel.

* feat(electron): enhance Electron app integration and CI/CD workflows

- Add new commands for Electron development, compilation, and building processes in CLAUDE.md.
- Update README.md to reflect the availability of the application as both a web and desktop app.
- Introduce a FixedChecklist component in the AI chat panel for better user interaction with generated tasks.
- Implement CI/CD workflows for automated testing and Electron builds in GitHub Actions.
- Refactor design generator prompts to support element-by-element streaming for improved performance.

* feat(ai): enhance chat functionality and orchestration capabilities

- Introduce context optimization to manage chat history size and prevent unbounded growth.
- Implement complexity assessment for design prompts to determine orchestration needs.
- Add orchestrator functionality for parallel design generation, improving performance and responsiveness.
- Update chat message parsing to include explicit status handling for orchestrator steps.
- Refactor design generator to support orchestration and streamline context building.

* refactor(ai): streamline orchestration and remove complexity classifier

- Remove the complexity classifier as its functionality is no longer needed.
- Update design generator to always route through the orchestrator, simplifying the logic.
- Enhance error handling during orchestration to ensure fallback to direct generation is clear.
- Introduce a new sub-agent prompt for improved output formatting and clarity in design generation.

* feat(ai): refine orchestrator prompt and timeout settings

- Update the ORCHESTRATOR_PROMPT to allow for more granular task division, specifying 4-15 atomic sections.
- Enhance the JSON output structure by adding new subtasks for the hero section.
- Adjust ORCHESTRATOR_TIMEOUTS to extend hard and no-text timeout values for improved orchestration performance.

* feat(docs): update CLAUDE.md and README.md for new features and improvements

- Expand the Fabric.js integration section in CLAUDE.md to include new files and functionalities.
- Highlight new features such as double-click frame entry, advanced drag-and-drop capabilities, and per-layer export options in README.md.
- Add context optimization and multi-provider support for AI in README.md.
- Update the project structure descriptions for clarity and completeness.

* refactor(config): update Vite configuration import for Vitest compatibility

* chore(ci): update GitHub Actions workflow to trigger on main branch pushes

* feat(uikit): introduce UIKit browser and component management features

- Add a new ComponentBrowserPanel for browsing and managing UI components.
- Implement ComponentBrowserGrid and ComponentBrowserCard for displaying components.
- Integrate UIKit store for managing component kits, search queries, and active categories.
- Enhance editor layout to support toggling the UIKit browser with keyboard shortcuts.
- Include import/export functionality for UIKit components.

* feat(types): add clipContent to ContainerProps

Allow frames to explicitly clip overflowing children, essential for
cards with cornerRadius + image children.

* feat(canvas): wire letterSpacing, textGrowth and clipContent to Fabric.js

- Convert letterSpacing (px) to Fabric charSpacing (1/1000 em) in
  factory and sync
- Select IText vs Textbox based on textGrowth mode, restore canvas
  selection after text object recreation
- Add multi-line text height estimation with CJK character support
- Honor clipContent flag in clipping logic

* feat(panels): split text Layout and Typography into separate sections

- Add readOnly prop to NumberInput for non-editable dimension display
- Extract text Layout section (dimensions, fill/hug, resizing toggles)
  into text-layout-section.tsx
- Enhance Typography section with line height, letter spacing, vertical
  alignment controls
- Reorder property panel: Size → Layout → Appearance → Fill → Stroke →
  Typography → Effects
- Add hideWH prop to SizeSection to avoid duplicate W/H inputs

* feat(panels): rewrite layout-section with full Flex Layout panel

- 3x3 alignment grid with context-aware behavior per layout direction
- Gap section with numeric/space-between/space-around radio modes
- Multi-mode padding: single, 2-axis (V/H), 4-individual (T/R/B/L)
  with gear popover
- Dimensions (W/H) and sizing checkboxes (fill/hug/clip) integrated
  into layout panel

* feat(panels): improve layer panel with auto-collapse and scroll-to-selection

- Collapse all layers by default, auto-collapse newly added nodes
- Auto-expand ancestor layers when a child is selected on canvas
- Scroll selected layer item into view after expansion

* fix(panels): improve AI chat panel overflow and color picker styling

- Fix chat panel overflow with proper flex layout and min-h-0
- Cap checklist height with scrollable overflow
- Adjust color picker input sizing

* feat(codegen): add textGrowth, textAlignVertical and clipContent to code generation

- textGrowth: auto → whitespace-nowrap, fixed-width-height → overflow-hidden
- textAlignVertical: middle/bottom → vertical-align CSS
- clipContent: true → overflow-hidden on containers

* feat(ai): integrate text typography properties into design prompts

- Add textGrowth, lineHeight, letterSpacing, textAlignVertical, fontStyle
  to PEN_NODE_SCHEMA and sub-agent prompt
- Add typography scale guidelines with lineHeight/letterSpacing defaults
- Update examples with lineHeight, clipContent, fill_container usage
- Add phone placeholder and clipContent rules

* feat(ai): enhance streaming service with runtime config and thinking modes

- Extract timeout constants to ai-runtime-config.ts
- Add thinking mode control (adaptive/disabled/enabled) to stream options
- Add StyleGuide interface for orchestrator visual consistency
- Add ping timeout and first-text timeout options

* feat(ai): improve design generator with typography defaults and phone placeholder

- Set default lineHeight on text nodes (1.2 for headings, 1.5 for body)
- Expand phone/mockup placeholder detection with shape-based fallback
- Flatten nested phone-shaped frames in post-streaming tree fixes
- Increase CJK character width estimation and button padding buffer

* feat(ai): enhance orchestrator with style guide and prompt optimizer

- Pass style guide from orchestrator plan to sub-agent prompts
- Add orchestrator-prompt-optimizer for context-aware prompt tuning
- Improve parallel sub-task generation and error recovery

* feat(ai): add thinking mode and Codex provider support to server API

- Support thinkingMode/effort params in chat and generate endpoints
- Add Codex (OpenAI) provider streaming via codex-client utility
- Forward thinking config to both Anthropic SDK and Agent SDK paths

* feat(mcp): implement OpenPencil file format and MCP server integration

- Introduce support for .op file format alongside .pen
- Add MCP server functionality for document management and tool operations
- Implement batch processing tools for design and variable management
- Enhance save and open dialogs to accommodate new file format
- Update dependencies and scripts for MCP server compilation and execution

* feat(build): update electron build configuration and resource handling

- Add mcp-server.cjs to extraResources in electron-builder.yml for production packaging
- Modify package.json build script to include MCP server compilation
- Enhance main.ts to set ELECTRON_RESOURCES_PATH for resource access
- Update mcp-install.ts to resolve MCP server path from resources in production

---------

Co-authored-by: Fini <fini.yang@gmail.com>
2026-02-22 12:09:12 +08:00
.github/workflows V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
.vscode Initialize OpenPencil project with essential files and configurations 2026-02-17 21:14:16 +08:00
build V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
electron V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
public feat(ai): add Setup Agents & MCP dialog with multi-provider support 2026-02-19 03:15:36 +08:00
scripts V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
server V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
src V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
.cta.json Initialize OpenPencil project with essential files and configurations 2026-02-17 21:14:16 +08:00
.gitignore V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
bun.lock V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
CLAUDE.md V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
components.json feat(editor): scaffold core canvas engine and editor layout 2026-02-18 21:49:16 +08:00
electron-builder.yml V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
LICENSE chore: update documentation and add MIT License 2026-02-18 22:35:17 +08:00
package.json V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
README.md V0.0.1 (#4) 2026-02-22 12:09:12 +08:00
tsconfig.json Initialize OpenPencil project with essential files and configurations 2026-02-17 21:14:16 +08:00
vite.config.ts V0.0.1 (#4) 2026-02-22 12:09:12 +08:00

OpenPencil

Open-source vector design tool with a Design-as-Code philosophy. An alternative to Pencil.dev.

Available as a web app and desktop app (macOS / Windows / Linux via Electron).

Features

Canvas

  • Infinite canvas with pan (Space+drag / middle mouse / Hand tool) and zoom (scroll wheel)
  • Smart alignment guides with edge, center, and distance snapping
  • Dimension labels during object manipulation
  • Frame labels and boundary visualization
  • Double-click to enter frames with visual overlay
  • Advanced drag-and-drop: drag into auto-layout frames with insertion indicators, reparenting, reorder within layout

Drawing Tools

  • Shapes: Rectangle, Ellipse, Line, Polygon
  • Frame: Container with auto-layout support (vertical/horizontal)
  • Text: Click-to-place text with full typography controls
  • Pen tool: Bezier curve drawing with anchor points, control handles, and path closure
  • Icon picker: Search and import icons via Iconify API
  • Image import: PNG, JPEG, SVG, WebP, GIF (SVG parsed into editable nodes)

Property Editing

  • Position, size, rotation
  • Fill: solid color and gradients (linear, radial)
  • Stroke: color, width, dash patterns
  • Corner radius (unified or per-corner)
  • Opacity, visibility, lock, flip (horizontal/vertical)
  • Effects: shadow and blur
  • Auto-layout: direction, gap, padding, justify-content, align-items
  • Variable binding: bind any property to a design variable via variable picker
  • Per-layer export: export individual layers to PNG/SVG with scale options (1x/2x/3x)

Design Variables & Tokens

  • Variables panel: Floating resizable panel with theme management (Cmd+Shift+V)
  • Variable types: Color (picker + hex + opacity), Number, String
  • Multi-theme support: Create multiple theme axes (e.g. Theme-1, Theme-2), each with variants (e.g. Default, Dark, High Contrast)
  • $variable references: Bind node properties (fill, stroke, opacity, gap, padding) to variables
  • CSS sync: Auto-generate CSS custom properties (:root { --color-1: #fff; }) with per-theme variant blocks
  • Code generation: React/Tailwind and HTML/CSS output uses var(--name) for variable-bound properties
  • Live resolution: Variables resolved on-the-fly for canvas rendering, preserved as $refs in document

Layer Panel

  • Hierarchical tree view with expand/collapse
  • Drag-and-drop reordering with drop-into-children support (above/below/inside zones)
  • Visibility and lock toggles per layer
  • Rename via double-click
  • Context menu: delete, duplicate, group, lock, hide
  • Selection synced with canvas

Parent-Child System

  • Frame/Group containers with nested children
  • Parent transforms (move, scale, rotate) propagate to children proportionally
  • Circular reference prevention when reparenting

History

  • Undo/Redo with batched drag operations (Cmd+Z / Cmd+Shift+Z)
  • Up to 300 history states

Clipboard & Grouping

  • Copy, cut, paste, duplicate (Cmd+C/X/V/D)
  • Group / ungroup selected elements (Cmd+G / Cmd+Shift+G)

File Operations

  • Save/open .pen files (JSON-based, Git-friendly)
  • Auto-save with File System Access API
  • Export: PNG and SVG with scale options (Cmd+Shift+E)

Code Generation

  • React + Tailwind CSS code from designs
  • HTML + CSS code from designs
  • CSS Variables from design tokens
  • View in code panel (Cmd+Shift+C)

AI Assistant

  • Built-in AI chat panel (Cmd+J)
  • AI-powered design generation from text prompts
  • Orchestrator-based parallel design generation: decomposes requests into spatial sub-tasks for faster output
  • Design block preview with "Apply Design" action
  • Streaming responses with thinking state and JSONL real-time canvas insertion
  • Context optimizer: sliding window history trimming to prevent unbounded context growth
  • Dual provider: Anthropic API or local Claude Code (OAuth)
  • Multi-provider settings: Claude Code, Codex CLI, OpenCode

Editor UI

  • Dark / light theme toggle (persisted to localStorage)
  • Fullscreen mode
  • Draggable, snap-to-corner AI chat panel

Keyboard Shortcuts

Shortcut Action
V Select tool
R Rectangle
O Ellipse
L Line
T Text
F Frame
P Path (pen tool)
H Hand (pan)
Cmd+A Select all
Cmd+Z Undo
Cmd+Shift+Z Redo
Cmd+C/X/V/D Copy/Cut/Paste/Duplicate
Cmd+G Group
Cmd+Shift+G Ungroup
Cmd+S Save
Cmd+Shift+E Export
Cmd+Shift+C Code panel
Cmd+Shift+V Variables panel
Cmd+J AI chat
Cmd+, Agent settings
Delete/Backspace Delete selected
Arrow keys Nudge (1px, +Shift = 10px)
[ / ] Reorder layers
Escape Deselect / Cancel

Tech Stack

Getting Started

Web (Development)

bun install
bun --bun run dev

Open http://localhost:3000 and click "New Design" to enter the editor.

Electron (Desktop)

# Development: starts Vite dev server + Electron
bun run electron:dev

# Production build (current platform)
bun run electron:build

AI Configuration

The AI assistant works in multiple modes:

  • Anthropic API: Set ANTHROPIC_API_KEY in .env
  • Local Claude Code: No config needed — uses Claude Agent SDK with OAuth login as fallback
  • OpenCode: Connect via OpenCode SDK for additional model support

Scripts

Command Description
bun --bun run dev Start web dev server on port 3000
bun --bun run build Production web build
bun --bun run preview Preview production build
bun --bun run test Run tests (Vitest)
npx tsc --noEmit Type check
bun run electron:dev Start Vite + Electron for desktop dev
bun run electron:compile Compile electron/ with esbuild
bun run electron:build Full Electron package (web build + compile + electron-builder)

CI / CD

CI (ci.yml)

Runs on every push and PR to main / v0.0.1:

  1. Lint & Test — type check (tsc --noEmit) + unit tests (vitest)
  2. Build Web — production web build, uploads .output/ as artifact

Build Electron (build-electron.yml)

Triggered by version tags (v*) or manual dispatch:

  1. Build — parallel matrix across macOS, Windows, Linux
    • macOS: .dmg + .zip
    • Windows: .exe (NSIS installer + portable)
    • Linux: .AppImage + .deb
  2. Release — creates a draft GitHub Release with all platform artifacts

To create a release:

git tag v0.1.0
git push origin v0.1.0

Project Structure

src/
  canvas/              # Fabric.js canvas engine (25 files: sync, events, guides, drag-drop, pen tool, etc.)
  variables/           # Design variables/tokens system (resolve, replace refs)
  components/
    editor/            # Editor layout, toolbar, tool buttons, top bar, status bar
    panels/            # Layer panel, property panel, AI chat, code panel, variables panel, export section
    shared/            # ColorPicker, NumberInput, VariablePicker, ExportDialog, etc.
    icons/             # Provider logos (Claude, OpenAI, OpenCode)
    ui/                # shadcn/ui primitives (Button, Select, Slider, Switch, etc.)
  hooks/               # Keyboard shortcuts
  lib/                 # Utility functions (cn class merging)
  services/
    ai/                # AI chat, orchestrator, context optimizer, design generation, prompts
    codegen/           # React+Tailwind, HTML+CSS, and CSS variables generators
  stores/              # Zustand stores (canvas, document, history, AI, agent-settings)
  types/               # PenDocument/PenNode types, style types, variables, agent settings, Electron IPC
  utils/               # File operations, export, node clone, SVG parser, syntax highlight
  routes/              # TanStack Router pages (/, /editor)
electron/
  main.ts              # Electron main process (window, Nitro server, IPC, fullscreen handling)
  preload.ts           # Context bridge for renderer ↔ main IPC
server/
  api/ai/              # Nitro API: streaming chat, generation, agent connection, models
  utils/               # Server utilities: Claude CLI resolver, OpenCode client manager
.github/
  workflows/
    ci.yml             # CI: type check, test, web build
    build-electron.yml # Electron build for macOS/Windows/Linux + GitHub Release

Roadmap

  • Component system (reusable components with instances & overrides)
  • Design variables/tokens with CSS sync
  • Boolean operations (union, subtract, intersect)
  • Multi-page support
  • Collaborative editing

License

MIT