New 'AI & Automation' top-level nav section with 9 pages: - AI Chat: setup, 87 tools, example prompts - Collaboration: room sharing, cursors, follow mode - JSX Renderer: elements, style props, visual diffing - CLI (4 pages): inspecting, exporting, analyzing, scripting - MCP Server: moved from Reference, setup + 90 tools New CLI reference page in Reference with all 12 commands, every option, alias, and default value. Formatting fixes across all 7 locales: - Wrap enum values in backticks (FRAME, SOLID, ROUND, etc.) - Fix single-backtick code blocks → triple backticks - Use <kbd> for all keyboard shortcuts - Remove implementation details from user guide - Delete stale eval-command.md and mcp-tools.md (14 files) - Update dead links to new locations
236 lines
11 KiB
Markdown
236 lines
11 KiB
Markdown
# 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.
|
||
|
||
::: info 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)
|
||
|
||
```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
|
||
|
||
| 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
|
||
|
||
```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
|
||
|
||
| 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
|
||
|
||
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`](/programmable/cli/scripting) 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.
|