Skip to content

Open Pencil vs Penpot: Porównanie architektury i wydajności

Dlaczego porównujemy? OpenPencil istnieje, ponieważ zamknięte platformy projektowe kontrolują co jest możliwe. Zrozumienie różnic architektonicznych pokazuje, co otwarta alternatywa local-first może zrobić inaczej.

Renderer WASM Penpota

Penpot 2.x zawiera renderer Rust/Skia WASM (render-wasm/v1) aktywowany przez flagi serwera lub parametr URL ?wasm=true. Stary renderer SVG pozostaje domyślny. Ta strona obejmuje oba.

1. Skala i rozmiar kodu

MetrykaOpen PencilPenpot
LOC ogółem~26 000~299 000
Pliki źródłowe~143~2 900
JęzykiTypeScript, VueClojure, ClojureScript, Rust, JS, SQL, SCSS
Silnik renderowania~3 200 LOC (TS, 10 plików)22 000 LOC (Rust/Skia WASM)
Kod UI~4 500 LOC~175 000 LOC (CLJS + SCSS)
BackendBrak (local-first)32 600 LOC + 151 plików SQL
Stosunek LOC~11×

Open Pencil jest ~11× mniejszy — i o to chodzi. To nie uproszczenie; to fundamentalnie inna architektura.

2. Architektura

Open Pencil: Klient monolityczny

┌─────────────────────────────────┐
│         Tauri (natywna powłoka) │
│  ┌───────────────────────────┐  │
│  │  Vue 3 + TypeScript       │  │
│  │  ┌─────────┐ ┌──────────┐│  │
│  │  │  Editor  │ │  Kiwi    ││  │
│  │  │  Store   │ │  Codec   ││  │
│  │  └────┬─────┘ └──────────┘│  │
│  │       │                    │  │
│  │  ┌────▼────────────────┐  │  │
│  │  │  Scene Graph (TS)    │  │  │
│  │  │  Map<string, Node>   │  │  │
│  │  └────┬────────────────┘  │  │
│  │       │                    │  │
│  │  ┌────▼────┐ ┌──────────┐│  │
│  │  │  Skia   │ │  Yoga    ││  │
│  │  │CanvasKit│ │  Layout  ││  │
│  │  │  (WASM) │ │  (WASM)  ││  │
│  │  └─────────┘ └──────────┘│  │
│  └───────────────────────────┘  │
└─────────────────────────────────┘

Wszystko w jednym procesie. Bez serwera, bazy danych, Dockera.

Penpot: Rozproszony klient-serwer

┌───────────────────────────────────────────────────────┐
│                    Docker Compose                      │
│  ┌──────────────┐  ┌─────────────┐  ┌──────────────┐ │
│  │   Frontend    │  │   Backend   │  │   Exporter   │ │
│  │  ClojureScript│  │   Clojure   │  │  (Chromium)  │ │
│  │  shadow-cljs  │  │   JVM       │  │              │ │
│  │  ┌─────────┐ │  │  ┌────────┐ │  └──────────────┘ │
│  │  │render-  │ │  │  │Postgres│ │                    │
│  │  │wasm     │ │  │  │Valkey  │ │  ┌──────────────┐ │
│  │  │(Rust→   │ │  │  │ MinIO  │ │  │   MCP        │ │
│  │  │ Skia    │ │  │  └────────┘ │  │   Server     │ │
│  │  │ WASM)   │ │  │             │  └──────────────┘ │
│  │  └─────────┘ │  │             │                    │
│  └──────────────┘  └─────────────┘                    │
└───────────────────────────────────────────────────────┘

Minimum 5+ usług. PostgreSQL, Redis (Valkey), MinIO, backend JVM, eksporter Node.js (headless Chromium), plus frontend ClojureScript.

Werdykt: Architektura

Architektura jednoprocesowa Open Pencil eliminuje: opóźnienie sieci, narzut serializacji, złożoność orkiestracji kontenerów i narzut zapytań do bazy danych.

3. Pipeline renderowania

Open Pencil: TS → CanvasKit WASM (bezpośrednio)

typescript
renderSceneToCanvas(canvas, graph, pageId) {
  this.fillPaint.setColor(...)
  canvas.drawRRect(rrect, this.fillPaint)
}
  • 1 przekroczenie granicy: TS → WASM (CanvasKit)
  • 1 646 LOC renderera łącznie

Penpot: JS (skompilowany z CLJS) → Rust WASM → Skia

ClojureScript (skompilowany do JS)
  → dekompozycja na prymitywy + pakowanie binarne do pamięci liniowej WASM
  → Rust WASM (przez Emscripten C FFI)
  → skia-safe (bindingi Rust Skia)
  → Skia (WebGL)

Gdy wyłączone (domyślnie), renderowanie jako drzewo DOM SVG. Gdy włączone, system renderowania oparty na kafelkach z 11 powierzchniami.

Werdykt: Renderowanie

AspektOpen PencilPenpot
Granica JS→WASMBezpośrednia (obiekty TS)Pakowanie binarne (104 bajty na kształt)
Model renderowaniaNatychmiastowy/pełne przerysowanieCache kafelkowy
Zarządzanie powierzchniami1 powierzchnia11 powierzchni
Narzut pamięciNiskiWysoki (1024 wpisy cache)
Złożoność kodu1 646 LOC22 000 LOC
Kod unsafeBrakGlobalny stan unsafe

4. Graf sceny i model danych

Open Pencil

typescript
nodes: Map<string, SceneNode>
// 29 typów węzłów ze schematu Kiwi Figmy
// ~390 pól na NodeChange (kompatybilny z Figmą)

Penpot

  • Dane rozproszone w common/ (49 600 LOC .cljc)
  • Walidacja schematu w runtime (Malli)

Werdykt: Model danych

Open Pencil reutylizuje sprawdzony schemat Figmy (194 definicje Kiwi) bezpośrednio w TypeScript. Penpot utrzymuje własny system typów w trzech językach.

5. Silnik layoutu

Open Pencil: Yoga WASM (314 LOC)

typescript
import Yoga from 'yoga-layout'
const root = Yoga.Node.create()
root.setFlexDirection(FlexDirection.Row)
root.calculateLayout()

314 linii. Synchroniczny, w procesie.

Penpot: Podwójna implementacja

Penpot utrzymuje dwa niezależne silniki layoutu (CLJS i Rust) — ~3 000+ LOC zduplikowanego kodu.

6. Format pliku i kompatybilność z Figmą

Open Pencil

  • Natywny format binarny Kiwi — ta sama serializacja co Figma
  • Bezpośredni import .fig, wklejanie ze schowka Figmy
  • Kompatybilny z protokołem multiplayer Figmy

Penpot

  • Archiwum ZIP (.penpot) z manifestami JSON i zasobami binarnymi
  • Brak natywnego importu .fig

Werdykt: Format pliku

Open Pencil ma znaczącą przewagę — może czytać pliki Figmy natywnie i wklejać dane ze schowka Figmy.

7. Zarządzanie stanem i cofanie

Open Pencil

typescript
// 110 LOC — wzorzec komendy odwrotnej
class UndoManager {
  apply(entry) { entry.forward(); this.undoStack.push(entry) }
  undo() { entry.inverse(); this.redoStack.push(entry) }
}

Penpot

Zarządzanie stanem przez Potok. Cofanie z wektorami zmian odwrotnych (max 50 wpisów), auto-wygasanie po 20 sekundach.

8. Doświadczenie developerskie

MetrykaOpen PencilPenpot
Setup devbun install && bun devDocker Compose + JVM + Node + Rust
Hot reloadVite HMR (~50ms)shadow-cljs (sekundy)
Sprawdzanie typówTypeScript (strict)Runtime (schematy Malli)
Czas buildu<5s (Vite)Minuty (JVM + CLJS + Rust WASM)
Bariera pierwszej kontrybucjiNiska (TS/Vue)Wysoka (Clojure + Rust + Docker)
DesktopTauri v2 (~5MB)N/A (tylko przeglądarka)

9. Charakterystyki wydajności

ScenariuszOpen PencilPenpot
Zimny start<2s (ładowanie WASM)10s+ (serwer + klient + WASM)
Opóźnienie operacji<1ms (w procesie)10-50ms (round-trip sieci)
Klatka renderowaniaBezpośrednie wywołanie SkiaCLJS→JS→WASM FFI→Skia
Pamięć bazowa~50MB (karta przeglądarki)~300MB+ (JVM + Postgres + Valkey + przeglądarka)
Zdolność offlinePełna (local-first)Brak (zależy od serwera)

10. Co Penpot robi lepiej

  1. Współpraca serwerowa — centralna edycja wieloużytkownikowa z WebSockets, kontami i kontrolą dostępu
  2. Serwerowy eksport PDF — usługa eksportu headless Chromium dla PDF (Open Pencil eksportuje już SVG natywnie)
  3. System pluginów — pełne API z sandboxowanym wykonywaniem
  4. Tokeny projektowe — natywne wsparcie design tokenów
  5. CSS Grid layout — własna implementacja (Open Pencil czeka na Yoga Grid)
  6. Self-hosting — wdrożenie Docker dla zespołów
  7. Dojrzałość — lata użytkowania w produkcji

11. Scripting i rozszerzalność

OpenPencil zawiera komendę eval oferującą API Plugin kompatybilne z Figmą do skryptowania headless. Ponadto 90 narzędzi AI dostępnych przez wbudowany chat, serwer MCP (stdio + HTTP) i CLI. Penpot ma system pluginów z sandboxem, ale bez API skryptowania headless ani integracji MCP.

Podsumowanie

WymiarZwycięzcaDlaczego
Prostota architektonicznaOpen PencilJeden proces vs 5+ usług
Wydajność renderowaniaOpen PencilBezpośredni CanvasKit vs SVG DOM (domyślnie) lub WASM pakowany
Utrzymywalność koduOpen Pencil~26K LOC w 1 języku vs 299K w 4+
Kompatybilność z FigmąOpen PencilNatywny kodek Kiwi vs brak wsparcia .fig
Onboarding developerówOpen PencilTS/Vue vs Clojure/Rust/Docker
Doświadczenie desktopOpen PencilNatywne Tauri vs tylko przeglądarka
Silnik layoutuOpen PencilYoga (sprawdzony) vs podwójna implementacja
WspółpracaRemisPenpot: serwer z kontrolą dostępu; Open Pencil: P2P przez Trystero + Yjs
Self-hostingPenpotGotowy Docker vs tylko desktop
Dojrzałość ekosystemuPenpotLata produkcji vs wczesny etap

Open Pencil jest architektonicznie szczuplejszy — jednoprocesowy renderer CanvasKit w ~26K LOC TypeScript, kompatybilny z Figmą z założenia. Penpot to platforma full-stack z ~299K LOC. Open Pencil ma skryptowanie headless, 90 narzędzi AI/MCP, eksport SVG i natywną aplikację desktop.

Released under the MIT License.