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
250 lines
12 KiB
Markdown
250 lines
12 KiB
Markdown
# Open Pencil vs Penpot : Comparaison d'architecture et de performances
|
||
|
||
Pourquoi comparer ? OpenPencil existe parce que les plateformes de design fermées contrôlent ce qui est possible. Comprendre les différences architecturales montre ce qu'une alternative ouverte et local-first peut faire différemment.
|
||
|
||
::: info Renderer WASM de Penpot
|
||
Penpot 2.x inclut un renderer Rust/Skia WASM (`render-wasm/v1`) activable via les flags du serveur ou le paramètre URL `?wasm=true`. Le renderer SVG reste le défaut. Cette page couvre les deux.
|
||
:::
|
||
|
||
## 1. Échelle et taille du code
|
||
|
||
| Métrique | Open Pencil | Penpot |
|
||
|----------|-------------|--------|
|
||
| LOC total | **~26 000** | **~299 000** |
|
||
| Fichiers source | ~143 | ~2 900 |
|
||
| Langages | TypeScript, Vue | Clojure, ClojureScript, Rust, JS, SQL, SCSS |
|
||
| Moteur de rendu | ~3 200 LOC (TS, 10 plików) | 22 000 LOC (Rust/Skia WASM) |
|
||
| Code UI | ~4 500 LOC | ~175 000 LOC (CLJS + SCSS) |
|
||
| Backend | Aucun (local-first) | 32 600 LOC + 151 fichiers SQL |
|
||
| Ratio LOC | **1×** | **~11×** |
|
||
|
||
Open Pencil est **~11× plus petit** — et c'est tout l'intérêt. Ce n'est pas une simplification ; c'est une architecture fondamentalement différente.
|
||
|
||
## 2. Architecture
|
||
|
||
### Open Pencil : Client monolithique
|
||
|
||
```
|
||
┌─────────────────────────────────┐
|
||
│ Tauri (shell natif) │
|
||
│ ┌───────────────────────────┐ │
|
||
│ │ Vue 3 + TypeScript │ │
|
||
│ │ ┌─────────┐ ┌──────────┐│ │
|
||
│ │ │ Editor │ │ Kiwi ││ │
|
||
│ │ │ Store │ │ Codec ││ │
|
||
│ │ └────┬─────┘ └──────────┘│ │
|
||
│ │ │ │ │
|
||
│ │ ┌────▼────────────────┐ │ │
|
||
│ │ │ Scene Graph (TS) │ │ │
|
||
│ │ │ Map<string, Node> │ │ │
|
||
│ │ └────┬────────────────┘ │ │
|
||
│ │ │ │ │
|
||
│ │ ┌────▼────┐ ┌──────────┐│ │
|
||
│ │ │ Skia │ │ Yoga ││ │
|
||
│ │ │CanvasKit│ │ Layout ││ │
|
||
│ │ │ (WASM) │ │ (WASM) ││ │
|
||
│ │ └─────────┘ └──────────┘│ │
|
||
│ └───────────────────────────┘ │
|
||
└─────────────────────────────────┘
|
||
```
|
||
|
||
**Tout dans un seul processus.** Pas de serveur, pas de base de données, pas de Docker.
|
||
|
||
### Penpot : Client-serveur distribué
|
||
|
||
```
|
||
┌───────────────────────────────────────────────────────┐
|
||
│ Docker Compose │
|
||
│ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ │
|
||
│ │ Frontend │ │ Backend │ │ Exporter │ │
|
||
│ │ ClojureScript│ │ Clojure │ │ (Chromium) │ │
|
||
│ │ shadow-cljs │ │ JVM │ │ │ │
|
||
│ │ ┌─────────┐ │ │ ┌────────┐ │ └──────────────┘ │
|
||
│ │ │render- │ │ │ │Postgres│ │ │
|
||
│ │ │wasm │ │ │ │Valkey │ │ ┌──────────────┐ │
|
||
│ │ │(Rust→ │ │ │ │ MinIO │ │ │ MCP │ │
|
||
│ │ │ Skia │ │ │ └────────┘ │ │ Server │ │
|
||
│ │ │ WASM) │ │ │ │ └──────────────┘ │
|
||
│ │ └─────────┘ │ │ │ │
|
||
│ └──────────────┘ └─────────────┘ │
|
||
└───────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Minimum 5+ services.** PostgreSQL, Redis (Valkey), MinIO, un backend JVM, un exporteur Node.js (Chromium headless), plus le frontend ClojureScript.
|
||
|
||
### Verdict : Architecture
|
||
|
||
L'architecture monoprocessus d'Open Pencil élimine : la latence réseau, l'overhead de sérialisation aux frontières de services, la complexité d'orchestration de conteneurs et l'overhead de requêtes base de données.
|
||
|
||
## 3. Pipeline de rendu
|
||
|
||
### Open Pencil : TS → CanvasKit WASM (direct)
|
||
|
||
```typescript
|
||
renderSceneToCanvas(canvas, graph, pageId) {
|
||
this.fillPaint.setColor(...)
|
||
canvas.drawRRect(rrect, this.fillPaint)
|
||
}
|
||
```
|
||
|
||
- **1 franchissement de frontière :** TS → WASM (CanvasKit)
|
||
- Le graphe de scène vit dans le heap JS — pas de sérialisation pour le rendu
|
||
- 1 646 LOC de renderer au total
|
||
|
||
### Penpot : JS (compilé depuis CLJS) → Rust WASM → Skia
|
||
|
||
```
|
||
ClojureScript (compilé en JS)
|
||
→ décomposer en primitives + empaqueter en binaire en mémoire linéaire WASM
|
||
→ Rust WASM (via Emscripten C FFI)
|
||
→ skia-safe (bindings Rust Skia)
|
||
→ Skia (WebGL)
|
||
```
|
||
|
||
Quand désactivé (défaut), les formes sont rendues comme un arbre DOM SVG. Quand activé, système de rendu par tuiles avec 11 surfaces et cache de 1024 entrées.
|
||
|
||
### Verdict : Rendu
|
||
|
||
| Aspect | Open Pencil | Penpot |
|
||
|--------|-------------|--------|
|
||
| Frontière JS→WASM | Direct (objets TS) | Empaquetage binaire (104 octets par forme) |
|
||
| Modèle de rendu | Immédiat/redessin complet | Cache par tuiles |
|
||
| Gestion des surfaces | 1 surface | 11 surfaces |
|
||
| Overhead mémoire | Faible (pas de cache tuiles) | Élevé (1024 entrées cache) |
|
||
| Complexité du code | 1 646 LOC | 22 000 LOC |
|
||
| Code unsafe | Aucun | État global `unsafe` |
|
||
|
||
## 4. Graphe de scène et modèle de données
|
||
|
||
### Open Pencil
|
||
|
||
```typescript
|
||
nodes: Map<string, SceneNode>
|
||
// 29 types de nœuds du schéma Kiwi de Figma
|
||
// ~390 champs par NodeChange (compatible Figma)
|
||
```
|
||
|
||
- Interfaces TypeScript avec types stricts
|
||
- GUIDs au format `sessionID:localID` de Figma
|
||
|
||
### Penpot
|
||
|
||
- Données réparties dans `common/` (49 600 LOC de .cljc)
|
||
- Validation de schéma au runtime (Malli)
|
||
- Les données doivent traverser la frontière CLJS→Rust pour le rendu
|
||
|
||
### Verdict : Modèle de données
|
||
|
||
Open Pencil réutilise le schéma éprouvé de Figma directement en TypeScript — zéro traduction. Penpot maintient son propre système de types à travers trois langages.
|
||
|
||
## 5. Moteur de 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 lignes au total. Synchrone, dans le processus.
|
||
|
||
### Penpot : Double implémentation
|
||
|
||
Penpot maintient **deux moteurs de layout indépendants** (CLJS et Rust) qui doivent produire des résultats identiques. ~3 000+ LOC de code layout personnalisé dupliqué.
|
||
|
||
### Verdict : Layout
|
||
|
||
Open Pencil délègue à Yoga (utilisé par React Native sur des milliards d'appareils) en 314 lignes.
|
||
|
||
## 6. Format de fichier et compatibilité Figma
|
||
|
||
### Open Pencil
|
||
|
||
- **Format binaire Kiwi natif** — même sérialisation que Figma
|
||
- Import direct `.fig`, collage depuis le presse-papiers Figma
|
||
- Compatible avec le protocole multiplayer de Figma
|
||
|
||
### Penpot
|
||
|
||
- **Archive ZIP** (`.penpot`) avec manifestes JSON et assets binaires
|
||
- Pas d'import natif `.fig`
|
||
- Trois versions de format avec système de migration
|
||
|
||
### Verdict : Format de fichier
|
||
|
||
Open Pencil a un avantage significatif — il peut lire les fichiers Figma nativement et coller les données du presse-papiers Figma.
|
||
|
||
## 7. Gestion d'état et annulation
|
||
|
||
### Open Pencil
|
||
|
||
```typescript
|
||
// 110 LOC — patron de commande inverse
|
||
class UndoManager {
|
||
apply(entry) { entry.forward(); this.undoStack.push(entry) }
|
||
undo() { entry.inverse(); this.redoStack.push(entry) }
|
||
}
|
||
```
|
||
|
||
110 lignes. Closures forward/inverse avec état minimal.
|
||
|
||
### Penpot
|
||
|
||
Gestion d'état via Potok (bibliothèque Redux-like pour atomes ClojureScript). Undo stocke des vecteurs de changements inverses (max 50 entrées), avec auto-expiration après 20 secondes.
|
||
|
||
## 8. Expérience développeur
|
||
|
||
| Métrique | Open Pencil | Penpot |
|
||
|----------|-------------|--------|
|
||
| Setup dev | `bun install && bun dev` | Docker Compose + JVM + Node + Rust |
|
||
| Rechargement à chaud | Vite HMR (~50ms) | shadow-cljs (secondes) |
|
||
| Vérification de types | TypeScript (strict) | Runtime (schémas Malli) |
|
||
| Temps de build | <5s (Vite) | Minutes (JVM + CLJS + Rust WASM) |
|
||
| Barrière première contribution | Basse (TS/Vue) | Haute (Clojure + Rust + Docker) |
|
||
| Desktop | Tauri v2 (~5Mo) | N/A (navigateur uniquement) |
|
||
| Bassin de recrutement | Massif (devs TS/Vue) | Petit (ClojureScript + Rust) |
|
||
|
||
## 9. Caractéristiques de performance
|
||
|
||
| Scénario | Open Pencil | Penpot |
|
||
|----------|-------------|--------|
|
||
| Démarrage à froid | <2s (chargement WASM) | 10s+ (serveur + client + WASM) |
|
||
| Latence d'opération | <1ms (dans le processus) | 10-50ms (aller-retour réseau) |
|
||
| Frame de rendu | Appel Skia direct | CLJS→JS→WASM FFI→Skia |
|
||
| Mémoire de base | ~50Mo (onglet navigateur) | ~300Mo+ (JVM + Postgres + Valkey + navigateur) |
|
||
| Capacité hors ligne | Complète (local-first) | Aucune (dépend du serveur) |
|
||
| Rendu 10K formes | Une passe, sans cache | Par tuiles avec 11 surfaces |
|
||
|
||
## 10. Ce que Penpot fait mieux
|
||
|
||
1. **Collaboration serveur** — édition multi-utilisateurs centralisée avec WebSockets, comptes et contrôle d'accès
|
||
2. **Export PDF serveur** — service d'export Chromium headless pour PDF (Open Pencil exporte déjà en SVG nativement)
|
||
3. **Système de plugins** — API complète avec exécution sandboxée
|
||
4. **Tokens de design** — support natif des design tokens
|
||
5. **CSS Grid layout** — implémentation personnalisée (Open Pencil attend Yoga Grid)
|
||
6. **Self-hosting** — déploiement Docker pour les équipes
|
||
7. **Maturité** — années d'utilisation en production
|
||
|
||
## 11. Scripting et extensibilité
|
||
|
||
OpenPencil inclut une [commande `eval`](/programmable/cli/scripting) offrant une API Plugin compatible Figma pour le scripting headless. De plus, 90 outils IA sont disponibles via le chat intégré, le serveur MCP (stdio + HTTP) et le CLI. Penpot a un système de plugins avec exécution sandboxée mais pas d'API de scripting headless ni d'intégration MCP.
|
||
|
||
## Résumé
|
||
|
||
| Dimension | Gagnant | Pourquoi |
|
||
|-----------|---------|----------|
|
||
| **Simplicité architecturale** | Open Pencil | Un processus vs 5+ services |
|
||
| **Performance de rendu** | Open Pencil | CanvasKit direct vs SVG DOM (défaut) ou WASM empaqueté |
|
||
| **Maintenabilité du code** | Open Pencil | ~26K LOC en 1 langage vs 299K en 4+ |
|
||
| **Compatibilité Figma** | Open Pencil | Codec Kiwi natif vs pas de support .fig |
|
||
| **Onboarding développeur** | Open Pencil | TS/Vue vs Clojure/Rust/Docker |
|
||
| **Expérience desktop** | Open Pencil | Tauri natif vs navigateur uniquement |
|
||
| **Moteur de layout** | Open Pencil | Yoga (éprouvé) vs double implémentation |
|
||
| **Collaboration** | Égalité | Penpot : serveur avec contrôle d'accès ; Open Pencil : P2P via Trystero + Yjs |
|
||
| **Self-hosting** | Penpot | Prêt Docker vs desktop uniquement |
|
||
| **Maturité écosystème** | Penpot | Années de production vs stade précoce |
|
||
|
||
Open Pencil est architecturalement plus léger — un renderer CanvasKit monoprocessus en ~26K LOC TypeScript, compatible Figma par conception. Penpot est une plateforme full-stack avec ~299K LOC. Open Pencil a le scripting headless, **90 outils AI/MCP**, export SVG et une app desktop native.
|