Vignette : un projet complet, du brief au binaire signé
L'exemple grandeur nature de tout ce guide : une app de post-its multi-plateforme conçue, construite, hébergée et livrée par des agents sur le mini-PC, en une nuit et une matinée. Avec les vrais pièges et les vraies captures.
Sur cette fiche
- 01Le point de départ : un brief, pas un prompt
- 02Les choix techniques : langages, architecture, et une stack taillée
- 03Le design : que ça ressemble à de vrais post-its
- 04L’hébergement : le circuit décrit dans ce guide, sans exception
- 05La qualité : tests unitaires, tests utilisateur, et la mémoire
- 06Trois agents, deux machines, zéro clé qui voyage
- 07Les pièges payés cash
- 08Les difficultés, et les limites de l’exercice
- 09Ce que cet exemple montre, et ce qu’il ne montre pas
- 10Questions fréquentes
Fiche vérifiée il y a 3 mois : certaines commandes ont pu changer. Signalez-le si c’est le cas.
En bref
Vignette, une app de post-its dockés au bord de l'écran, a été conçue, construite, hébergée et livrée par des agents sur le mini-PC de ce guide, en une nuit et une matinée fin août 2026. Elle tourne en ligne (web, macOS, Linux, Android), avec un backend Supabase auto-hébergé, des tests unitaires, 24 scénarios de bout en bout et des sauvegardes. Le récit montre ce qui a marché (un brief avec maquettes, des décisions humaines prises tôt, plusieurs sessions d'agents qui se vérifient) et ce qui a coincé : ne jamais valider sur un code de sortie, et une v0.1 reste une v0.1.
À faire avant : Cadrer un projet avec un LLMFaire travailler plusieurs agents ensemble
Tout ce guide vous explique comment monter la machine, installer les agents et cadrer le travail. Cette fiche montre ce que ça donne au bout : un vrai projet, mené du premier message au binaire téléchargeable, sur le mini-PC décrit dans ces pages. Le projet, mené fin août 2026, s’appelle Vignette, une app de post-its collés au bord de l’écran. Vous pouvez l’ouvrir, la télécharger, lire son code. Rien n’est maquillé, et c’est justement ce qui la rend intéressante à décortiquer.
Le point de départ : un brief, pas un prompt
Le soir, le brief est plus fourni qu’un simple message : deux maquettes griffonnées sur un coin de papier et photographiées au téléphone, des captures d’écran d’une app dont l’esthétique plaît, une liste d’exigences précises (« premium, natif, multi-plateforme, partage synchronisé, back office, français par défaut »), une demande de propositions de noms, et une mini étude concurrentielle : qu’est-ce qui existe, à quel prix, et surtout qu’est-ce qui manque. Le constat tenait en une phrase : les apps de notes traitent l’écran comme un document, aucune ne traite son bord comme un lieu. C’est exactement la méthode de la fiche Cadrer un projet avec un LLM : montrer plutôt que décrire, dire ce qu’on veut obtenir plutôt que comment le coder.
L’étude concurrentielle a d’ailleurs resservi en cours de route : chez un concurrent macOS payant et mono-plateforme, deux bonnes idées ont été repérées puis reprises (les raccourcis clavier, l’annulation dix secondes après une suppression), et le positionnement inverse s’est affirmé : multi-plateforme, open source, auto-hébergeable. Regarder la concurrence n’est pas copier ; c’est savoir où l’on se place.
Trois décisions humaines ont eu lieu avant la première ligne de code : le nom (Vignette, choisi parmi des propositions), le desktop en Tauri v2 plutôt qu’Electron (binaires dix fois plus légers, la web app réutilisée telle quelle), et le backend en Supabase auto-hébergé plutôt qu’un service cloud. L’agent a argumenté chaque option, l’humain a tranché, et ces trois choix ont tenu jusqu’au bout.
Les choix techniques : langages, architecture, et une stack taillée
Côté langages et architecture, tout est fait pour qu’un agent s’y repère vite. Un monorepo pnpm en TypeScript strict de bout en bout, avec un paquet core qui contient le modèle métier pur (tri du deck, règles de statut, imports Markdown), sans une ligne d’interface, testé par Vitest. Autour, des apps séparées : la web app en React 19 + Vite avec Framer Motion pour les animations à ressort, le site vitrine en HTML statique, le back office, une petite API d’administration en Node sans aucune dépendance, et la coque native en Tauri v2, où le Rust se limite à ce que le web ne sait pas faire (fenêtres, tray, raccourci global, mises à jour signées). Détail assumé : pas de Tailwind, un design system maison en CSS à variables, parce que l’esthétique manuscrite du projet ne rentre dans aucune grille toute faite. Et un seul nom de domaine pour tout : Caddy route l’app, le site, l’admin et l’API selon le chemin, ce qui simplifie le CORS, le TLS et la vie.
Supabase auto-hébergé livre d’habitude une dizaine de conteneurs. Vignette en fait tourner six : Postgres, l’authentification (GoTrue), l’API REST (PostgREST), le temps réel, une petite API d’administration en Node sans aucune dépendance, et Caddy devant. Kong, Studio et l’analytics ont sauté. Résultat : environ 450 Mo de RAM, une part raisonnable du mini-PC, qui héberge aussi tout le reste.
La sécurité repose sur la Row Level Security de Postgres : chaque table porte des règles qui décident, ligne par ligne, qui lit et qui écrit. Un compte ne peut pas lire les notes d’un autre, même en parlant directement à l’API. C’est le genre de garantie qu’on vérifie, pas qu’on suppose : une suite de tests rejoue chaque nuit dix invariants (« un intrus ne peut pas lire », « un éditeur invité ne peut pas supprimer ») contre la vraie instance, comme le recommande la fiche Relire, auditer, sécuriser.
Le design : que ça ressemble à de vrais post-its
Le parti pris visuel est venu des maquettes du brief : des onglets pastel dockés au bord, une écriture manuscrite (la police Caveat), des animations à ressort, douze couleurs. La règle d’or, née d’un retour utilisateur en cours de route : rien ne se décolle jamais du bord. Un onglet survolé grossit vers la page au lieu de se détacher de la tranche, un post-it déplié reste soudé à l’écran. Ce sont des détails, et c’est eux qui font qu’on y croit.
Sur desktop, le concept va au bout : une note peut s’épingler en vraie fenêtre sans bordure, toujours au premier plan, posée sur le bureau. Et quand elle gêne, elle se range en onglet collé au bord de l’écran, comme un vrai post-it qu’on décale du coin de l’œil.
L’hébergement : le circuit décrit dans ce guide, sans exception
Le chemin d’une requête suit exactement les fiches du chapitre réseau : le domaine passe par un tunnel Cloudflare (aucun port ouvert sur la box), arrive sur Caddy qui route vers la bonne brique, et Postgres n’est jamais exposé. Les sauvegardes suivent la doctrine de Git, GitHub et sauvegardes : un dump SQL chaque nuit, une copie sur le NAS, un miroir hebdomadaire ailleurs. Le monitoring alerte sur Telegram en moins de six heures si un invariant casse, et l’alarme elle-même a été testée volontairement un matin à 8 h 35, parce qu’une alarme jamais déclenchée ne compte pas.
Deux détails d’hébergement valent la peine d’être copiés :
0 étape sur 2 faite Vos cases cochées restent dans ce navigateur.
-
Le SMTP est optionnel, vraiment
Sans serveur mail, tout marche : les comptes créés depuis le back office sont actifs immédiatement, le lien « mot de passe oublié » se masque tout seul, et un mot de passe perdu se remplace en deux clics d’administrateur. Exiger un SMTP aurait éliminé la moitié des gens qui veulent s’auto-héberger.
-
Les apps se connectent avec une URL, rien d'autre
Chaque instance expose un petit point d’entrée public qui décrit sa configuration. Au premier lancement, l’app native demande « où vivent tes notes ? » : l’instance officielle, la vôtre (collez l’URL, elle découvre le reste), ou un mode local sans serveur du tout.
La qualité : tests unitaires, tests utilisateur, et la mémoire
Trois filets superposés gardent le projet, chacun attrapant ce que les autres laissent passer.
Le premier est classique : les tests unitaires de core (Vitest) verrouillent le modèle, et une suite de bout en bout de 24 scénarios rejoue chaque parcours dans un vrai navigateur : connexion, mauvaise connexion, création, couleurs, deck, rappels, partage temps réel entre deux comptes, imports, exports, réglages, mobile. Une commande, cinq minutes, verdict. Amusant et instructif : lors de sa première exécution, ses quatre échecs étaient des bugs du test, pas de l’app ; un sélecteur trop large cliquait « importer » en croyant cliquer « exporter ». Les tests aussi se déboguent.
Le deuxième filet, ce sont les tests utilisateur, version artisanale : l’utilisateur se réveille, essaie tout, et envoie ses impressions en vrac (« l’icône est illisible », « le widget est vide », « ce menu est trop chargé », « ça se décolle bizarrement »). Chaque remarque est traitée comme un ticket : reproduite, corrigée, re-testée, redéployée, souvent en moins de dix minutes. Deux de ces remarques sont devenues des règles de design gravées dans la mémoire du projet. Aucune suite automatisée ne remplace un humain qui trouve un bouton moche.
Le troisième filet est la mémoire, au sens de la fiche Les fichiers mémoire : un fichier de consignes dans le dépôt qui accumule les pièges payés cash (avec leur solution, pour ne jamais payer deux fois), et une mémoire de session persistante où vivent les décisions, les préférences de l’utilisateur et les leçons. La sécurité ferme la marche : une passe dédiée a vérifié qu’aucune valeur secrète ne traîne dans l’historique git (en cherchant des segments des vraies valeurs, pas des noms de variables), que seul le point d’entrée public est exposé, que les inscriptions sont fermées côté serveur, et que les en-têtes de base sont posés. Relu par des agents, pas par un auditeur externe : la nuance est dans la section suivante.
Trois agents, deux machines, zéro clé qui voyage
Le mini-PC ne sait pas compiler pour macOS. Une deuxième session d’agent tourne donc sur un MacBook, et les deux se parlent comme le décrit la fiche Plusieurs agents ensemble : celle du Mac construit l’app, dépose le binaire, annonce son empreinte ; celle du mini-PC vérifie l’empreinte, signe, publie, met à jour les sommes de contrôle. Sept builds macOS ont traversé ce circuit en une nuit.
Ils n’étaient d’ailleurs pas deux mais trois. Une session d’orchestration, toujours allumée sur le mini-PC, joue le régisseur : elle détient les accès sensibles (le tunnel Cloudflare, dont chaque modification peut tout casser), pose le monitoring et les sondes, distribue les outils et les consignes (le jeton de purge du cache, les règles propres à chaque dépôt), relaie les retours de l’utilisateur quand il écrit ailleurs, et surtout vérifie les déclarations des autres sessions au lieu de les croire sur parole. Quand la session de build a annoncé avoir modifié le site personnel, l’orchestratrice est allée contrôler la page en ligne avant de classer la déclaration. Les bâtisseuses construisent ; elle tient le plateau.
Le meilleur moment de cette collaboration : la clé qui signe les mises à jour ne quitte jamais le mini-PC. Quand il a fallu signer les artefacts du Mac, la session macOS a refusé de transporter la clé privée entre machines et proposé mieux : rapatrier les fichiers et signer sur place, en signature détachée. C’est l’agent qui a durci la procédure de sécurité, pas l’inverse.
Les pièges payés cash
Un récit de projet qui ne raconte que les réussites ne vous apprend rien. Trois bugs de cette nuit méritent le détour, parce qu’ils partagent la même morale :
- La fenêtre blanche. Le premier build macOS s’ouvrait sur du blanc : les chemins d’assets du bundle natif étaient faux. Le code de sortie de la compilation, lui, était parfait.
- L’icône noire. L’outil en ligne de commande qui convertissait le logo SVG rendait les dégradés en noir, sans un mot d’erreur. L’icône « jaune fluo » livrée dans le dock était un pâté sombre.
- Le post-it vide. La fenêtre épinglée chargeait son thème mais jamais ses données : le module qui démarre la synchronisation n’était appelé que par l’écran de connexion, que cette fenêtre ne traverse pas. Deux agents ont tracé la même chaîne de cause à effet, chacun de son côté, avant de corriger.
La morale, devenue règle de travail entre les deux sessions : ne jamais valider sur un code de sortie. Lancer le binaire, regarder l’image, mesurer la couleur des pixels s’il le faut. Trois fois dans la nuit, quelque chose qui « avait réussi » ne fonctionnait pas.
Les difficultés, et les limites de l’exercice
Le récit serait suspect sans sa part d’os. Voici ce qui a coincé, et ce que cet exemple ne prouve pas.
Les difficultés d’abord. Le cycle natif est lourd : chaque retouche visible dans les apps exige de recompiler, re-signer et redéposer les binaires des trois plateformes ; les sept builds macOS de la nuit sont un symptôme, pas un exploit. La preuve à distance a des bornes : depuis SSH, aucun agent ne peut cliquer dans une fenêtre macOS ni voir la barre de menus, donc certaines vérifications (le raccourci global, un lien qui ouvre Safari) reviennent obligatoirement à l’humain. Le MacBook s’est endormi trois fois en plein transfert avant qu’un caffeinate borné ne règle la question : la machine la moins préparée devient le goulot de tout le monde. Et le piège le plus instructif : une preuve automatisée qui teste le mauvais scénario rassure à tort. Le post-it épinglé avait sa preuve d’affichage, prise en mode local ; le bug ne vivait qu’en mode connecté, et il a fallu l’œil de l’utilisateur pour le voir.
Les limites ensuite, dites franchement. « Quatre plateformes en une nuit » produit une v0.1 solide, pas un produit mûri : pas d’utilisateurs en charge, pas de montée en charge éprouvée, une accessibilité encore partielle. Au 1er octobre 2026, iOS s’arrête au simulateur (il faut un compte développeur Apple), Windows attend une machine pour compiler, les widgets et la synchro pair-à-pair restent sur la feuille de route. La sécurité a été passée au crible par des agents, pas par un auditeur externe : la RLS est testée chaque nuit, mais un pentest humain reste une autre paire de manches. Enfin, rien ici ne remplace la vision produit : sans le flot de retours du matin, l’app serait restée correcte et un peu fausse partout. L’agent amplifie une direction ; il n’en fournit pas.
Ce que cet exemple montre, et ce qu’il ne montre pas
En chiffres : une nuit et une matinée, quatre plateformes en ligne (web, macOS, Linux, Android) avec binaires signés et mises à jour intégrées, un back office, des sauvegardes, du monitoring, et une suite de 24 scénarios de test qui rejoue chaque parcours dans un navigateur.
Ce que ça ne montre pas : un miracle. Il a fallu la machine préparée (tout ce guide), un brief avec des maquettes, des décisions humaines à chaque bifurcation, et un flux continu de retours au réveil (« l’icône est illisible », « le widget est vide », « ce menu est trop chargé »), chacun corrigé, testé et redéployé en quelques minutes. L’agent fait le travail ; la direction, c’est vous. L’histoire complète, racontée côté humain, est sur ulrichrozier.com/vignette.
Toutes les commandes de cette fiche
Questions fréquentes
Avec quelles technologies Vignette a-t-elle été construite ?
Un monorepo pnpm en TypeScript strict, avec un paquet core pour le modèle métier, testé par Vitest, une web app en React 19 et Vite, et une coque native en Tauri v2 où le Rust se limite à ce que le web ne sait pas faire. Le backend est un Supabase auto-hébergé réduit à six conteneurs : Postgres, l'authentification, l'API REST, le temps réel, une petite API d'administration en Node et Caddy, qui route l'app, le site, l'admin et l'API sur un seul domaine.
Pourquoi choisir Tauri plutôt qu'Electron pour une app de bureau ?
Pour Vignette, Tauri v2 l'a emporté pour deux raisons : des binaires dix fois plus légers et la web app réutilisée telle quelle. Le Rust ne sert qu'à ce que le web ne sait pas faire, comme les fenêtres, l'icône dans la zone de notification, le raccourci global et les mises à jour signées. Ce choix a été tranché par l'humain avant la première ligne de code et a tenu jusqu'au bout.
Comment compiler une app macOS quand on travaille sur un mini-PC Linux ?
Le mini-PC ne sait pas compiler pour macOS, alors une deuxième session d'agent tournait sur un MacBook. Celle du Mac construisait l'app, déposait le binaire et annonçait son empreinte ; celle du mini-PC vérifiait l'empreinte, signait, publiait et mettait à jour les sommes de contrôle. La clé qui signe les mises à jour n'a jamais quitté le mini-PC : les fichiers ont été rapatriés et signés sur place.
Comment empêcher un utilisateur de lire les données d'un autre avec Supabase ?
Vignette s'appuie sur la Row Level Security de Postgres : chaque table porte des règles qui décident, ligne par ligne, qui lit et qui écrit, même quand on parle directement à l'API. Cette garantie est vérifiée : une suite de tests rejoue chaque nuit dix invariants contre la vraie instance, comme « un intrus ne peut pas lire » ou « un éditeur invité ne peut pas supprimer ».
Faut-il un serveur mail pour auto-héberger Vignette ?
Non, le SMTP est optionnel. Sans serveur mail, les comptes créés depuis le back office sont actifs immédiatement, le lien « mot de passe oublié » se masque tout seul, et un mot de passe perdu se remplace en deux clics d'administrateur. L'exiger aurait éliminé la moitié des gens qui veulent s'auto-héberger.
Les termes de cette fiche : Open source (vs open-weight)AgentMarkdownAPIConteneurGitOrchestrateurCLISSHLinux
Une erreur ?
Une commande ne marche plus, un prix a changé ?
Les outils bougent tous les mois. Dites-moi ce qui cloche dans cette fiche, je corrige et je redate.