Excalidraw est un tableau blanc pour dessiner des diagrammes dont la caractéristique principale est un style de trait à main levée, et une bibliothèque React qui permet d'intégrer ce même éditeur dans ta propre application. La version actuelle du paquet est la 0.18, sous licence MIT.
Deux choses portant le même nom méritent d'être distinguées, car les confondre mène à de mauvaises conclusions. La bibliothèque ouverte et le tableau blanc gratuit accessible à une adresse publique, c'est une chose. Le service payant avec un backend, des comptes et une gestion d'équipe, c'en est une autre.
Le style à main levée n'est pas un ornement
L'apparence du trait ressemble à un choix esthétique, mais c'est en réalité un choix fonctionnel, qui mérite d'être compris avant de choisir un outil.
Un diagramme dessiné avec des lignes précises a l'air fini. Le même diagramme dans un style à main levée a l'air d'un brouillon. La différence porte sur la façon dont les gens y réagissent : face à un brouillon, il est plus facile de dire « et si on faisait autrement », alors qu'un dessin peaufiné inspire une réticence à remettre en question quelque chose que quelqu'un a visiblement soigné.
Pour concevoir une architecture, discuter d'un flux ou réfléchir ensemble, cette propriété joue en ta faveur. Pour une présentation devant un comité de direction ou une documentation censée paraître sérieuse, elle joue contre toi, et c'est alors un outil d'un autre genre qu'il faut choisir.
C'est d'ailleurs le critère principal pour choisir entre cet outil et ses alternatives : pas le nombre de fonctionnalités, mais le moment de la conversation où le diagramme apparaît.
Intégration dans ta propre application
La bibliothèque est un composant React qui s'intègre en quelques lignes.
import { Excalidraw } from '@excalidraw/excalidraw'
import '@excalidraw/excalidraw/index.css'
export function Board() {
return (
<div style={{ height: '100vh' }}>
<Excalidraw
initialData={{ elements: savedElements }}
onChange={(elements) => save(elements)}
/>
</div>
)
}Trois choses posent le plus de problèmes lors d'un premier essai.
La feuille de styles doit être importée séparément. Sans elle, le composant s'affiche de façon éparpillée, ce qui se confond facilement avec un défaut de configuration de build.
Le conteneur a besoin d'une hauteur définie. Le canvas s'étire jusqu'à son parent, donc dans un élément à hauteur automatique, il reçoit zéro pixel et disparaît.
Avec Next.js, une troisième chose apparaît : le composant touche des objets du navigateur au montage, donc le rendu côté serveur doit être désactivé en le chargeant dynamiquement.
import dynamic from 'next/dynamic'
const Excalidraw = dynamic(
() => import('@excalidraw/excalidraw').then((m) => m.Excalidraw),
{ ssr: false, loading: () => <Skeleton /> }
)Sans ça, tu obtiens une erreur sur un objet window non défini, levée pendant le build plutôt que dans le navigateur, ce qui fait facilement chercher la cause au mauvais endroit.
L'état du dessin est un simple tableau d'objets que tu stockes où tu veux. Il n'y a aucun backend imposé par la bibliothèque, donc la persistance, le versionnement et les permissions sont à concevoir toi-même, exactement comme pour toute autre donnée dans une application.
Collaboration et auto-hébergement
C'est un point où la prudence paie, car la documentation à ce sujet induit facilement en erreur.
Lancer l'éditeur seul comme conteneur donne un tableau blanc fonctionnel sans collaboration. Tu dessines, tu enregistres localement, un point c'est tout.
La collaboration entre plusieurs personnes nécessite un composant séparé, un serveur de salons qui relaie les changements entre les clients. C'est un second conteneur et une seconde chose à maintenir, ce que les guides qui décrivent un lancement en une seule commande omettent généralement.
La conséquence pratique : si tu veux seulement un outil de dessin, l'auto-hébergement est simple. Si tu veux un travail partagé à l'échelle d'une entreprise, attends-toi à deux services, plus la configuration des noms de domaine et des certificats.
Sache aussi que les données du dessin, dans la version publique, sont chiffrées côté navigateur, donc le serveur relais n'en voit pas le contenu. C'est une propriété utile, qui ne remplace cependant pas le contrôle d'accès : qui détient le lien détient l'accès, et le lien transporte la clé.
L'offre payante et ce qu'elle apporte
Le service payant coûte 7 dollars par personne et par mois en facturation mensuelle, et 6 dollars en facturation annuelle, après un essai de deux semaines. C'est le seul poste avec un prix publié : une offre pour les grandes entreprises existe, mais le fournisseur n'en publie aucun montant et te renvoie vers un entretien commercial.
Elle apporte des choses que la bibliothèque n'a pas par nature : des comptes, un stockage des dessins dans le cloud, des dossiers, des conversations vocales, le partage d'écran et des fonctionnalités assistées par modèle.
Il vaut la peine de déterminer si tu en as besoin, car la réponse est négative plus souvent que ne le suggère la page de tarifs. Une équipe qui dessine des diagrammes pendant un appel et colle les résultats dans la documentation se contente de la version gratuite. Une équipe qui traite les tableaux comme des artefacts durables avec historique et permissions a besoin d'un backend, donc le choix se joue entre ce service et le fait de le construire soi-même sur la bibliothèque.
La seconde voie est parfois judicieuse précisément parce que la licence est entièrement ouverte. Construire un backend avec une liste de dessins, des permissions et une recherche représente quelques jours de travail, et là où les données doivent rester dans ta propre infrastructure, c'est parfois la seule option.
À quoi ça sert vraiment
Ça vaut la peine de nommer des usages concrets, car « un tableau blanc pour dessiner » ne dit rien sur le moment où le sortir.
Un diagramme d'architecture pendant un appel. Trois rectangles, deux flèches et des légendes apparaissent plus vite que l'ouverture d'un outil avec une palette de formes prêtes à l'emploi, et la conversation continue au lieu d'attendre.
Un croquis d'interface avant de la construire. Le style à main levée joue double jeu ici : ça se dessine vite, et personne n'imagine que c'est déjà une maquette qui attend une validation.
Une explication dans un rapport de bug. Une capture d'écran avec des flèches et des légendes dessinées dessus en dit plus qu'un paragraphe de description, et coller l'image dans un ticket prend quelques secondes.
Du matériel pédagogique. Un diagramme expliquant un flux de données ou une structure de répertoires paraît accessible précisément parce qu'il ne ressemble pas à un document officiel.
Ce à quoi ça ne sert pas : les schémas exigeant de la précision, les dessins techniques avec une échelle, les diagrammes générés depuis du code, et tout ce qui doit être produit automatiquement. Pour des diagrammes décrits en texte et rendus à la construction de la documentation, le bon outil est un générateur plutôt qu'un éditeur graphique, car celui-là se versionne comme du code.
Bibliothèques de formes et extension
Au-delà des formes de base, des ensembles d'éléments prêts à l'emploi existent et méritent d'être connus avant de te mettre à dessiner des icônes à la main.
Les bibliothèques sont des collections d'éléments réutilisables : icônes de cloud, symboles réseau, éléments d'interface. Tu les ajoutes à l'éditeur et les glisses sur le canvas, et ta propre bibliothèque peut être construite à partir d'éléments dessinés et partagée avec une équipe sous forme de fichier.
Ce dernier scénario est souvent sous-estimé. Une équipe qui dessine chaque semaine des diagrammes d'architecture des mêmes systèmes arrête de dessiner à partir de rien une fois son propre jeu de formes construit, et se met à assembler, et les diagrammes deviennent au passage cohérents d'une personne à l'autre.
Étendre l'éditeur lui-même est plus limité ici que dans les outils construits autour de l'extensibilité. Tu peux remplacer des éléments d'interface, ajouter tes propres boutons et piloter l'éditeur par code, mais ajouter un type de forme entièrement nouveau avec sa propre logique n'est pas ce pour quoi cette bibliothèque a été conçue.
C'est un autre élément qui la distingue de solutions plus riches, et c'est aussi pour ça qu'elle s'intègre plus vite. Moins de possibilités veut dire moins de décisions à prendre au moment de l'intégrer.
Excalidraw face aux alternatives
| Outil | Licence | Style | Quand le choisir |
|---|---|---|---|
| Excalidraw | MIT, sans clé | À main levée | Croquis, intégration dans un produit, budget zéro |
| tldraw | Licence propriétaire, clé requise | Épuré | Le canvas est le cœur du produit et tu as du budget |
| Outils de diagrammes | Fermée, payante | Précis | Documentation qui doit paraître officielle |
| Tableaux blancs hébergés | Fermée, par personne | Soigné | Tu achètes un produit plutôt que tu n'en construis un |
Les deux premières lignes forment aujourd'hui la comparaison clé, et la différence a nettement bougé. tldraw a introduit une exigence de clé de licence pour un usage en production, donc l'intégrer dans un produit commercial entraîne des frais. Cette bibliothèque est restée en MIT, sans clé et sans filigrane.
Ça ne la rend pas meilleure pour autant. tldraw offre un système plus riche de formes et d'outils personnalisés, donc pour un produit où le canvas est l'interface principale, cette différence vaut parfois son prix. Pour un tableau blanc ajouté à côté de la fonction principale d'une application, justifier la facture est difficile quand une alternative gratuite fait le même travail.
La troisième ligne mérite un examen honnête. Un diagramme destiné à une proposition client ou à une documentation de conformité a meilleure allure dessiné avec précision, et c'est exactement le cas où un style à main levée gêne.
Piloter l'éditeur depuis le code
Intégrer le composant n'est qu'un début, et la plupart des usages réels exigent de lui parler par code.
Le composant expose un objet de contrôle à travers lequel tu lis les éléments actuels, remplaces le contenu du canvas, défiles jusqu'à un endroit choisi et changes le mode de travail. Ça suffit pour construire des choses qu'un utilisateur perçoit comme des fonctionnalités de l'application plutôt que comme des capacités du tableau blanc.
Exemples typiques : un bouton qui insère sur le canvas un diagramme généré à partir de données, un bouton pour basculer entre mode édition et aperçu, l'enregistrement du dessin vers ton propre backend à chaque changement avec un délai, le chargement d'un modèle à la création d'un nouveau document.
Le même principe s'applique à l'enregistrement que dans tout éditeur qui réagit aux changements : l'écouteur se déclenche très souvent, y compris à chaque image du glisser d'un élément, donc enregistrer sans délai signifie des dizaines d'écritures par seconde.
const [api, setApi] = useState<ExcalidrawImperativeAPI | null>(null)
const saveDebounced = useMemo(
() => debounce((elements: readonly ExcalidrawElement[]) => {
fetch('/api/board', {
method: 'PUT',
body: JSON.stringify({ elements })
})
}, 1000),
[]
)
<Excalidraw
excalidrawAPI={setApi}
onChange={(elements) => saveDebounced(elements)}
/>Un délai d'environ une seconde après le dernier changement règle le problème une bonne fois pour toutes. L'objet impératif arrive via une prop qui le passe à un callback plutôt que via une ref, et c'est ce sur quoi la plupart des gens trébuchent au premier essai.
Sache aussi que l'état du dessin est une structure de données ordinaire, donc elle peut être créée et modifiée sans passer par l'éditeur.
import { convertToExcalidrawElements } from '@excalidraw/excalidraw'
const elements = convertToExcalidrawElements([
{ type: 'rectangle', x: 0, y: 0, width: 180, height: 80, id: 'api' },
{ type: 'rectangle', x: 300, y: 0, width: 180, height: 80, id: 'db' },
{
type: 'arrow',
x: 190, y: 40,
width: 100, height: 0,
start: { id: 'api' },
end: { id: 'db' }
}
])
api?.updateScene({ elements })La fonction d'aide complète avec des valeurs par défaut les champs que tu n'as pas fournis, donc tu n'as pas besoin de connaître la forme complète d'un élément. Générer un diagramme à partir d'une description dans le code et le fournir comme contenu initial est une approche qui, pour une documentation automatisée, bat souvent le dessin à la main.
Export et intégration dans la documentation
Un dessin s'exporte vers une image matricielle, vers un format vectoriel et vers un format natif qui préserve une édition ultérieure.
Le choix entre eux compte plus en pratique qu'il n'y paraît. Une image matricielle est pratique et non modifiable, donc une correction un mois plus tard signifie redessiner depuis le début. Le format vectoriel s'adapte sans perdre en netteté et convient à la documentation, mais ne retourne pas non plus vers l'éditeur.
La bonne pratique garde les deux : le fichier source dans le dépôt à côté de la documentation, et l'image exportée insérée dans le texte. Une correction six mois plus tard devient alors l'ouverture d'un fichier plutôt que la reconstruction d'un dessin à partir d'une image.
Sache aussi que le format vectoriel peut intégrer les données source, donc un seul fichier remplit les deux rôles. Cette voie est pratique pour une documentation conservée dans un dépôt.
Pour intégrer un aperçu dans une application, le mode sans interface aide, où le composant affiche le dessin sans barre d'outils. Un diagramme dans une documentation technique ressemble alors à une image, tout en gardant sa netteté une fois agrandi.
Erreurs courantes
La première est d'oublier l'import de la feuille de styles. Le composant s'affiche de façon éparpillée, et la cause ressemble à un problème d'outil de build.
La deuxième est un conteneur sans hauteur définie. Le canvas reçoit zéro pixel et donne l'impression que le composant ne s'est jamais monté.
La troisième est le rendu côté serveur sans le désactiver. Le composant plante au montage en cherchant à atteindre un objet du navigateur.
La quatrième est d'attendre de la collaboration après avoir lancé l'éditeur seul. Échanger des changements entre personnes nécessite un serveur de salons séparé, qui est un second composant.
La cinquième est de traiter le chiffrement du lien comme un contrôle d'accès. Qui détient le lien détient l'accès, puisque la clé en fait partie.
La sixième est de n'enregistrer qu'un export en image. Une correction un mois plus tard signifie alors redessiner le diagramme plutôt qu'ouvrir le fichier source.
La septième est d'enregistrer à chaque changement sans délai. L'écouteur se déclenche à chaque image du glisser d'un élément, donc sur un dessin plus grand, ça produit des dizaines d'écritures par seconde et un ralentissement perceptible.
FAQ
Excalidraw est-il gratuit ?
La bibliothèque et le tableau blanc à l'adresse publique le sont, sous licence MIT, sans clé et sans filigrane. Ce qui coûte de l'argent, c'est un service séparé avec comptes, stockage dans le cloud et fonctionnalités d'équipe, à 7 dollars par personne et par mois, ou 6 dollars en facturation annuelle.
Puis-je l'intégrer dans un produit commercial ?
Oui, la licence MIT ne pose aucune condition ici et n'exige aucune clé pour un usage en production. C'est actuellement la principale différence avec tldraw, qui exige depuis sa quatrième version une licence pour un usage en production.
Comment le faire tourner chez moi ?
L'éditeur seul est un conteneur unique et donne un tableau blanc fonctionnel sans collaboration. Échanger des changements entre personnes nécessite en plus un serveur de salons, un second composant, que les guides décrivant un lancement en une seule commande omettent généralement.
Les données sont-elles sûres dans la version publique ?
Le contenu du dessin est chiffré côté navigateur, donc le serveur relais ne le voit pas. Ça ne remplace pas le contrôle d'accès, puisque la clé fait partie du lien, donc quiconque le reçoit pourra ouvrir le dessin.
Quand vaut-il mieux choisir autre chose ?
Quand le diagramme doit paraître officiel, car un style à main levée nuit à une documentation destinée à un client. Et quand le canvas est l'interface principale de ton produit et que tu as besoin d'un système étendu de formes personnalisées, car tldraw en offre davantage sur ce point.
La documentation de la bibliothèque se trouve sur le site pour développeurs, et le code dans le dépôt GitHub.