# 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. ::: info 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 | Metryka | Open Pencil | Penpot | |---------|-------------|--------| | LOC ogółem | **~26 000** | **~299 000** | | Pliki źródłowe | ~143 | ~2 900 | | Języki | TypeScript, Vue | Clojure, 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) | | Backend | Brak (local-first) | 32 600 LOC + 151 plików SQL | | Stosunek LOC | **1×** | **~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 │ │ │ │ │ └────┬────────────────┘ │ │ │ │ │ │ │ │ │ ┌────▼────┐ ┌──────────┐│ │ │ │ │ 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 | Aspekt | Open Pencil | Penpot | |--------|-------------|--------| | Granica JS→WASM | Bezpośrednia (obiekty TS) | Pakowanie binarne (104 bajty na kształt) | | Model renderowania | Natychmiastowy/pełne przerysowanie | Cache kafelkowy | | Zarządzanie powierzchniami | 1 powierzchnia | 11 powierzchni | | Narzut pamięci | Niski | Wysoki (1024 wpisy cache) | | Złożoność kodu | 1 646 LOC | 22 000 LOC | | Kod unsafe | Brak | Globalny stan `unsafe` | ## 4. Graf sceny i model danych ### Open Pencil ```typescript nodes: Map // 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 | Metryka | Open Pencil | Penpot | |---------|-------------|--------| | Setup dev | `bun install && bun dev` | Docker Compose + JVM + Node + Rust | | Hot reload | Vite HMR (~50ms) | shadow-cljs (sekundy) | | Sprawdzanie typów | TypeScript (strict) | Runtime (schematy Malli) | | Czas buildu | <5s (Vite) | Minuty (JVM + CLJS + Rust WASM) | | Bariera pierwszej kontrybucji | Niska (TS/Vue) | Wysoka (Clojure + Rust + Docker) | | Desktop | Tauri v2 (~5MB) | N/A (tylko przeglądarka) | ## 9. Charakterystyki wydajności | Scenariusz | Open Pencil | Penpot | |------------|-------------|--------| | Zimny start | <2s (ładowanie WASM) | 10s+ (serwer + klient + WASM) | | Opóźnienie operacji | <1ms (w procesie) | 10-50ms (round-trip sieci) | | Klatka renderowania | Bezpośrednie wywołanie Skia | CLJS→JS→WASM FFI→Skia | | Pamięć bazowa | ~50MB (karta przeglądarki) | ~300MB+ (JVM + Postgres + Valkey + przeglądarka) | | Zdolność offline | Peł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`](/programmable/cli/scripting) 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 | Wymiar | Zwycięzca | Dlaczego | |--------|-----------|----------| | **Prostota architektoniczna** | Open Pencil | Jeden proces vs 5+ usług | | **Wydajność renderowania** | Open Pencil | Bezpośredni CanvasKit vs SVG DOM (domyślnie) lub WASM pakowany | | **Utrzymywalność kodu** | Open Pencil | ~26K LOC w 1 języku vs 299K w 4+ | | **Kompatybilność z Figmą** | Open Pencil | Natywny kodek Kiwi vs brak wsparcia .fig | | **Onboarding developerów** | Open Pencil | TS/Vue vs Clojure/Rust/Docker | | **Doświadczenie desktop** | Open Pencil | Natywne Tauri vs tylko przeglądarka | | **Silnik layoutu** | Open Pencil | Yoga (sprawdzony) vs podwójna implementacja | | **Współpraca** | Remis | Penpot: serwer z kontrolą dostępu; Open Pencil: P2P przez Trystero + Yjs | | **Self-hosting** | Penpot | Gotowy Docker vs tylko desktop | | **Dojrzałość ekosystemu** | Penpot | Lata 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.