Skip to content

Open Pencil vs Penpot: Confronto architettura e prestazioni ​

Perché confrontare? OpenPencil esiste perché le piattaforme di design chiuse controllano ciò che è possibile. Comprendere le differenze architetturali mostra cosa un'alternativa aperta e local-first può fare diversamente.

Renderer WASM di Penpot

Penpot 2.x include un renderer Rust/Skia WASM (render-wasm/v1) attivabile tramite flag del server o il parametro URL ?wasm=true. Il renderer SVG rimane il default. Questa pagina copre entrambi.

1. Scala e dimensione del codice ​

MetricaOpen PencilPenpot
LOC totali~26.000~299.000
File sorgente~143~2.900
LinguaggiTypeScript, VueClojure, ClojureScript, Rust, JS, SQL, SCSS
Motore di rendering~3.200 LOC (TS, 10 Dateien)22.000 LOC (Rust/Skia WASM)
Codice UI~4.500 LOC~175.000 LOC (CLJS + SCSS)
BackendNessuno (local-first)32.600 LOC + 151 file SQL
Rapporto LOC1×~11×

Open Pencil è ~11× più piccolo — e questo è il punto. Non è una semplificazione; è un'architettura fondamentalmente diversa.

2. Architettura ​

Open Pencil: Client monolitico ​

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

Tutto in un unico processo. Nessun server, nessun database, nessun Docker.

Penpot: Client-server distribuito ​

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

Minimo 5+ servizi. PostgreSQL, Redis (Valkey), MinIO, backend JVM, esportatore Node.js (Chromium headless), più il frontend ClojureScript.

Verdetto: Architettura ​

L'architettura monoprocesso di Open Pencil elimina: latenza di rete, overhead di serializzazione, complessità di orchestrazione container e overhead di query database.

3. Pipeline di rendering ​

Open Pencil: TS → CanvasKit WASM (diretto) ​

typescript
renderSceneToCanvas(canvas, graph, pageId) {
  this.fillPaint.setColor(...)
  canvas.drawRRect(rrect, this.fillPaint)
}
  • 1 attraversamento: TS → WASM (CanvasKit)
  • 1.646 LOC di renderer totale

Penpot: JS (compilato da CLJS) → Rust WASM → Skia ​

ClojureScript (compilato in JS)
  → scomporre in primitive + impacchettare in binario nella memoria lineare WASM
  → Rust WASM (via Emscripten C FFI)
  → skia-safe (binding Rust Skia)
  → Skia (WebGL)

Quando disabilitato (default), rendering come albero DOM SVG. Quando abilitato, sistema di rendering a tile con 11 superfici.

Verdetto: Rendering ​

AspettoOpen PencilPenpot
Confine JS→WASMDiretto (oggetti TS)Impacchettamento binario (104 byte per forma)
Modello di renderingImmediato/ridisegno completoCache a tile
Gestione superfici1 superficie11 superfici
Overhead memoriaBassoAlto (1024 voci cache)
Complessità codice1.646 LOC22.000 LOC
Codice unsafeNessunoStato globale unsafe

4. Grafo della scena e modello dati ​

Open Pencil ​

typescript
nodes: Map<string, SceneNode>
// 29 tipi di nodo dallo schema Kiwi di Figma
// ~390 campi per NodeChange (compatibile Figma)

Penpot ​

  • Dati distribuiti in common/ (49.600 LOC di .cljc)
  • Validazione schema a runtime (Malli)

Verdetto: Modello dati ​

Open Pencil riutilizza lo schema provato di Figma (194 definizioni Kiwi) direttamente in TypeScript. Penpot mantiene un proprio sistema di tipi attraverso tre linguaggi.

5. Motore di layout ​

Open Pencil: Yoga WASM (314 LOC) ​

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

314 righe. Sincrono, in-process.

Penpot: Doppia implementazione ​

Penpot mantiene due motori di layout indipendenti (CLJS e Rust) che devono produrre risultati identici. ~3.000+ LOC duplicati.

6. Formato file e compatibilità Figma ​

Open Pencil ​

  • Formato binario Kiwi nativo — stessa serializzazione di Figma
  • Import diretto .fig, incolla dagli appunti di Figma
  • Compatibile con il protocollo multiplayer di Figma

Penpot ​

  • Archivio ZIP (.penpot) con manifesti JSON e asset binari
  • Nessun import nativo .fig

Verdetto: Formato file ​

Open Pencil ha un vantaggio significativo — può leggere file Figma nativamente e incollare dati dagli appunti di Figma.

7. Gestione stato e annullamento ​

Open Pencil ​

typescript
// 110 LOC — pattern di comando inverso
class UndoManager {
  apply(entry) { entry.forward(); this.undoStack.push(entry) }
  undo() { entry.inverse(); this.redoStack.push(entry) }
}

Penpot ​

Gestione stato via Potok. Undo con vettori di cambiamenti inversi (max 50 voci), auto-scadenza dopo 20 secondi.

8. Esperienza sviluppatore ​

MetricaOpen PencilPenpot
Setup devbun install && bun devDocker Compose + JVM + Node + Rust
Hot reloadVite HMR (~50ms)shadow-cljs (secondi)
Type checkingTypeScript (strict)Runtime (schemi Malli)
Tempo build<5s (Vite)Minuti (JVM + CLJS + Rust WASM)
Barriera prima contribuzioneBassa (TS/Vue)Alta (Clojure + Rust + Docker)
DesktopTauri v2 (~5MB)N/A (solo browser)

9. Caratteristiche di prestazione ​

ScenarioOpen PencilPenpot
Avvio a freddo<2s (caricamento WASM)10s+ (server + client + WASM)
Latenza operazione<1ms (in-process)10-50ms (round-trip rete)
Frame di renderChiamata Skia direttaCLJS→JS→WASM FFI→Skia
Memoria base~50MB (tab browser)~300MB+ (JVM + Postgres + Valkey + browser)
Capacità offlineCompleta (local-first)Nessuna (dipende dal server)

10. Cosa fa meglio Penpot ​

  1. Collaborazione server — editing multi-utente centralizzato con WebSockets, account e controllo accessi
  2. Export PDF server — servizio export Chromium headless per PDF (Open Pencil esporta già SVG nativamente)
  3. Sistema plugin — API completa con esecuzione sandboxed
  4. Token di design — supporto nativo design token
  5. CSS Grid layout — implementazione propria (Open Pencil attende Yoga Grid)
  6. Self-hosting — deployment Docker per team
  7. Maturità — anni di uso in produzione

11. Scripting ed estensibilità ​

OpenPencil include un comando eval che fornisce un'API Plugin compatibile Figma per scripting headless. Inoltre, 90 strumenti AI disponibili via chat integrata, server MCP (stdio + HTTP) e CLI. Penpot ha un sistema plugin con esecuzione sandboxed ma senza API di scripting headless né integrazione MCP.

DimensioneVincitorePerché
Semplicità architetturaleOpen PencilUn processo vs 5+ servizi
Prestazioni di renderingOpen PencilCanvasKit diretto vs SVG DOM (default) o WASM impacchettato
Manutenibilità codiceOpen Pencil~26K LOC in 1 linguaggio vs 299K in 4+
Compatibilità FigmaOpen PencilCodec Kiwi nativo vs nessun supporto .fig
Onboarding sviluppatoriOpen PencilTS/Vue vs Clojure/Rust/Docker
Esperienza desktopOpen PencilTauri nativo vs solo browser
Motore di layoutOpen PencilYoga (provato) vs doppia implementazione
CollaborazionePareggioPenpot: server con controllo accessi; Open Pencil: P2P via Trystero + Yjs
Self-hostingPenpotDocker-ready vs solo desktop
Maturità ecosistemaPenpotAnni di produzione vs stadio iniziale

Open Pencil è architetturalmente più snello — un renderer CanvasKit monoprocesso in ~26K LOC TypeScript, compatibile Figma per design. Penpot è una piattaforma full-stack con ~299K LOC. Open Pencil ha scripting headless, 90 strumenti AI/MCP, export SVG e app desktop nativa.

Released under the MIT License.