Skip to content

Contributing

Project Structure

packages/
  core/              @open-pencil/core — engine (zero DOM deps)
    src/             Scene graph, renderer, layout, codec, kiwi, types
  cli/               @open-pencil/cli — headless CLI for .fig operations
    src/commands/    info, tree, find, export
src/
  components/        Vue SFCs (canvas, panels, toolbar, color picker)
    properties/      Property panel sections (Appearance, Fill, Stroke, etc.)
  composables/       Canvas input, keyboard shortcuts, rendering hooks
  stores/            Editor state (Vue reactivity)
  engine/            Re-export shims from @open-pencil/core
  kiwi/              Re-export shims from @open-pencil/core
  types.ts           Shared types (re-exported from core)
  constants.ts       UI colors, defaults, thresholds
desktop/             Tauri v2 (Rust + config)
tests/
  e2e/               Playwright visual regression
  engine/            Unit tests (bun:test)
docs/                VitePress documentation site
openspec/
  specs/             Capability specifications (source of truth)
  changes/           Active and archived changes

Development Setup

sh
bun install
bun run dev          # Editor at localhost:1420
bun run docs:dev     # Docs at localhost:5173

Code Style

Tooling

ToolCommandPurpose
oxlintbun run lintLinting (Rust-based, fast)
oxfmtbun run formatCode formatting
tsgobun run typecheckType checking (Go-based TypeScript checker)

Run all checks:

sh
bun run check

Conventions

  • File names — kebab-case (scene-graph.ts, use-canvas-input.ts)
  • Components — PascalCase Vue SFCs (EditorCanvas.vue, ScrubInput.vue)
  • Constants — SCREAMING_SNAKE_CASE
  • Functions/variables — camelCase
  • Types/interfaces — PascalCase

AI Agent Conventions

Developers and AI agents working on the codebase should read AGENTS.md in the repo root (view on GitHub). Covers rendering, scene graph, components & instances, layout, UI, file format, Tauri conventions, and known issues.

Making Changes

  1. Check existing openspec specs for the capability you're modifying
  2. Create an openspec change if adding new behavior: openspec new change "my-change"
  3. Implement the change
  4. Run bun run check and bun run test
  5. Submit a pull request

Key Files

Engine source lives in packages/core/src/. The app's src/engine/ and src/kiwi/ are re-export shims — edit the core package, not the shims.

FilePurpose
packages/core/src/scene-graph.tsScene graph: nodes, variables, instances, hit testing
packages/core/src/renderer.tsCanvasKit rendering pipeline
packages/core/src/layout.tsYoga layout adapter
packages/core/src/undo.tsUndo/redo manager
packages/core/src/clipboard.tsFigma-compatible clipboard
packages/core/src/vector.tsVector network model
packages/core/src/render-image.tsOffscreen image export (PNG/JPG/WEBP)
packages/core/src/kiwi/codec.tsKiwi binary encoder/decoder
packages/core/src/kiwi/fig-import.ts.fig file import logic
packages/cli/src/index.tsCLI entry point
packages/cli/src/commands/CLI commands (info, tree, find, export)
src/stores/editor.tsGlobal editor state
src/composables/use-canvas.tsCanvas rendering composable
src/composables/use-canvas-input.tsMouse/touch input handling
src/composables/use-keyboard.tsKeyboard shortcut handling

Released under the MIT License.