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 LOC~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.