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
| Metrica | Open Pencil | Penpot |
|---|---|---|
| LOC totali | ~26.000 | ~299.000 |
| File sorgente | ~143 | ~2.900 |
| Linguaggi | TypeScript, Vue | Clojure, 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) |
| Backend | Nessuno (local-first) | 32.600 LOC + 151 file SQL |
| Rapporto LOC | 1× | ~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)
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
| Aspetto | Open Pencil | Penpot |
|---|---|---|
| Confine JS→WASM | Diretto (oggetti TS) | Impacchettamento binario (104 byte per forma) |
| Modello di rendering | Immediato/ridisegno completo | Cache a tile |
| Gestione superfici | 1 superficie | 11 superfici |
| Overhead memoria | Basso | Alto (1024 voci cache) |
| Complessità codice | 1.646 LOC | 22.000 LOC |
| Codice unsafe | Nessuno | Stato globale unsafe |
4. Grafo della scena e modello dati
Open Pencil
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)
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
// 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
| Metrica | Open Pencil | Penpot |
|---|---|---|
| Setup dev | bun install && bun dev | Docker Compose + JVM + Node + Rust |
| Hot reload | Vite HMR (~50ms) | shadow-cljs (secondi) |
| Type checking | TypeScript (strict) | Runtime (schemi Malli) |
| Tempo build | <5s (Vite) | Minuti (JVM + CLJS + Rust WASM) |
| Barriera prima contribuzione | Bassa (TS/Vue) | Alta (Clojure + Rust + Docker) |
| Desktop | Tauri v2 (~5MB) | N/A (solo browser) |
9. Caratteristiche di prestazione
| Scenario | Open Pencil | Penpot |
|---|---|---|
| Avvio a freddo | <2s (caricamento WASM) | 10s+ (server + client + WASM) |
| Latenza operazione | <1ms (in-process) | 10-50ms (round-trip rete) |
| Frame di render | Chiamata Skia diretta | CLJS→JS→WASM FFI→Skia |
| Memoria base | ~50MB (tab browser) | ~300MB+ (JVM + Postgres + Valkey + browser) |
| Capacità offline | Completa (local-first) | Nessuna (dipende dal server) |
10. Cosa fa meglio Penpot
- Collaborazione server — editing multi-utente centralizzato con WebSockets, account e controllo accessi
- Export PDF server — servizio export Chromium headless per PDF (Open Pencil esporta già SVG nativamente)
- Sistema plugin — API completa con esecuzione sandboxed
- Token di design — supporto nativo design token
- CSS Grid layout — implementazione propria (Open Pencil attende Yoga Grid)
- Self-hosting — deployment Docker per team
- 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.
Riepilogo
| Dimensione | Vincitore | Perché |
|---|---|---|
| Semplicità architetturale | Open Pencil | Un processo vs 5+ servizi |
| Prestazioni di rendering | Open Pencil | CanvasKit diretto vs SVG DOM (default) o WASM impacchettato |
| Manutenibilità codice | Open Pencil | ~26K LOC in 1 linguaggio vs 299K in 4+ |
| Compatibilità Figma | Open Pencil | Codec Kiwi nativo vs nessun supporto .fig |
| Onboarding sviluppatori | Open Pencil | TS/Vue vs Clojure/Rust/Docker |
| Esperienza desktop | Open Pencil | Tauri nativo vs solo browser |
| Motore di layout | Open Pencil | Yoga (provato) vs doppia implementazione |
| Collaborazione | Pareggio | Penpot: server con controllo accessi; Open Pencil: P2P via Trystero + Yjs |
| Self-hosting | Penpot | Docker-ready vs solo desktop |
| Maturità ecosistema | Penpot | Anni 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.