Je sors mes boards de Miro pour les ramener dans Obsidian
Le bouton Export de Miro te donne un PNG ou un PDF — une photo des données, pas les données. Si tes boards sont des load-bearing maps of thinking accumulées sur des années, leur place est dans Obsidian : editable, searchable, dans un vault local. Comment j'ai sorti les boards de Miro via la REST API et converti vers Excalidraw / Obsidian Canvas — en gardant positions, couleurs, fontes, curved connectors, mindmap nodes — et la leçon dépasse Miro : tout SaaS mérite un exit plan AVANT la première utilisation.
N'importe quel outil qui vit dans le navigateur te tient en otage de son UI. Surtout quand tu y as mis du temps, des cartes, des boards — et que tu réalises soudain que ta map of thinking est sur le serveur de quelqu'un d'autre, dans un format que tu ne peux pas ouvrir sans leur page.
J'ai quelques boards Miro devenus depuis longtemps load-bearing — réflexions, plans, cartes mentales accumulés sur des années. Le bouton Export te donne un PNG ou un PDF. Ce ne sont pas des données, c'est une photo des données.
Pourquoi les sortir
Le vendor lock-in n'est pas un problème théorique. C'est très concret : pour télécharger tes propres données via l'API, il faut upgrade en Expert tier. Autrement dit, tu payes pour avoir l'autorisation de reprendre ce qui est déjà à toi.
Je vis depuis longtemps selon le principe Obsidian-first : tout ce qui compte vit dans un vault local, en plain files, que je peux git-er, grep-er, relire dans dix ans. Un outil qui n'exporte pas vers ce format-là, c'est un outil dont il faut fuir avant que la dépendance ne devienne incassable.
Pourquoi Export ne te sauve pas
Le bouton Export de Miro te donne un PNG ou un PDF. C'est du raster — la structure est perdue. Tu ne peux pas changer le texte dans un box. Tu ne peux pas déplacer un shape. Tu ne peux pas grep-er un libellé. C'est le faire-part de décès du board, pas le board.
Obsidian a deux alternatives qui vivent dans le vault : le plugin Excalidraw et Canvas natif. Les deux sont en JSON. Les deux sont editable. Les deux sont searchable. Les deux vivent dans ton vault à côté de tes notes, et tu peux grep-er le texte directement depuis Obsidian.
Comment les sortir quand il n'y a pas de bouton 'Export to Obsidian'
Quand l'Export du UI ne te donne pas ce qu'il te faut, tu rentres dans l'API. Miro a une REST API : elle renvoie une description JSON de chaque shape d'un board. Excalidraw et Obsidian Canvas sont tous deux du JSON open-format. Entre les deux, il y a un mapping.
J'ai écrit deux scripts Python. miro_to_excalidraw.py et miro_to_canvas.py. Standard library only — zéro deps. Tu les lances avec un token et un board ID, tu obtiens un fichier, tu le jettes dans le vault.
Ce qui a survécu à la conversion
L'objectif n'était pas juste de transférer des shapes — c'était de préserver le visuel pour que le board se lise comme dans Miro.
- Positions et tailles — coordonnées de chaque shape au 1:1
- Couleurs avec fill opacity (un jaune à 40 % reste à 40 %)
- Borders — couleur, épaisseur, style (solid / dashed)
- Fontes et alignment — monospace reste monospace, center reste center
- Connectors — les flèches s'accrochent aux mêmes points que dans Miro
- Curved connectors — arcs bow au lieu de lignes droites
- Images embarquées dans le fichier (pas d'URLs externes)
- Mindmap nodes — texte sorti via l'experimental Mindmap API
- Z-ordering — les overlaps ne s'emmêlent pas
Là où c'était inconfortable
L'API Miro a quelques trous autour desquels il a fallu travailler en reverse engineering.
- Curved connectors — Miro n'expose pas les control points dans l'API. Du coup, au lieu de la courbe d'origine exacte, je synthétise un bow — un arc de rayon fixe entre les deux endpoints. Visuellement proche, mathematically pas identique.
- Z-index — l'API Miro ne renvoie tout simplement pas de champ z. Quel shape doit passer au-dessus, lequel en dessous ? Heuristique : plus c'est grand en surface, plus c'est loin derrière. Ça marche parce que dans les vrais boards les gros conteneurs sont en général sous les petits éléments.
- Mindmap — le texte des mindmap nodes n'est pas accessible via l'items API standard. Il te faut un call séparé vers l'experimental Mindmap endpoint. Les filled nodes deviennent des boxes, les unfilled du plain text.
Excalidraw vs Canvas — comment choisir
Si tu penses en mode drawings — sketchy lines, hand-drawn feel, compositions freeform — prends Excalidraw. Le plugin Excalidraw rend le fichier dans le même style esthétique que ce que tu as vu sur les whiteboards.
Si tes boards sont surtout des rectangles avec du texte reliés par des flèches et que tu vis dans Obsidian comme second brain — prends Canvas. Canvas est natif, s'ouvre en un clic, branché sur les backlinks et tags du vault.
Je convertis certains boards en Excalidraw (quand le visual style compte), d'autres en Canvas (quand la vitesse et le feel natif comptent). Le repo gère les deux formats — tu choisis au lancement.
Bilan
Python 3, standard library only. Pas de pip install, pas de virtualenv, pas de node_modules. python3 miro_to_excalidraw.py 'BOARD_ID' 'output.excalidraw' — et le fichier est entre tes mains.
Repo : github.com/oleksiimazurenko/miro-to-obsidian. Licence MIT. PRs bienvenues — surtout pour les edge cases que je n'ai pas encore rencontrés.
La leçon dépasse Miro
Le SaaS lock-in est une drogue. Les premiers mois, c'est gratuit. À six mois, c'est devenu une habitude. À un an, tes données vivent dans un format que seul leur UI sait lire. À deux ans, tu payes l'Expert tier pour extraire ce qui était déjà à toi.
La conclusion n'est pas « n'utilise pas de SaaS ». La conclusion, c'est que chaque outil qui devient load-bearing mérite un exit plan AVANT la première utilisation. La question « comment je sors d'ici quand il le faudra » pèse autant que « à quel point l'UI est agréable ». Un outil sans export plain-text ni API ouverte, c'est un outil avec une étiquette de prix cachée que tu payeras dans deux ans.
Obsidian-first, pas parce qu'Obsidian est parfait. Mais parce que les plain markdown files sont un format qui survivra à Obsidian lui-même. De la même manière qu'un fichier JSON Excalidraw nu survivra au plugin. De la même manière que ce script Python survivra à Miro.