Créer un suivi de dépenses avec Electron, React et SQLite

De nombreuses personnes souhaitent suivre leurs finances sans dépendre d'outils infonuagiques qui posent des questions de confidentialité ou facturent un abonnement mensuel. Une application de bureau stockée localement répond à ces deux préoccupations : les données restent sur la machine de l'utilisateur et aucun coût récurrent ne s'ajoute.

Electron, React et SQLite forment un trio cohérent pour ce type de projet. Electron fournit le runtime natif du bureau, React gère l'interface de manière déclarative, et SQLite offre un stockage sans configuration, parfaitement adapté aux données personnelles. Les sections qui suivent détaillent chaque étape de la construction.

Préparer l'environnement de développement

La mise en place du projet demande Node.js, un gestionnaire de paquets et la compréhension de la séparation entre processus principal et processus de rendu dans Electron. L'initialisation installe Electron, React (via Vite ou Create React App) et better-sqlite3, le pilote synchrone recommandé pour SQLite dans cet environnement.

Le fichier package.json déclare le point d'entrée principal ainsi que les scripts utiles au développement comme à la compilation. Une organisation classique sépare le main.js (cycle de vie Electron) du dossier src/ qui contient les composants React, ce qui clarifie les responsabilités dès le départ.

La création de la BrowserWindow exige de respecter les réglages de sécurité par défaut : contextIsolation à true, nodeIntegration à false, et un script de préchargement qui passe par contextBridge. Ces choix empêchent tout contenu distant d'accéder directement aux API Node et constituent le socle d'une application robuste.

Concevoir une architecture en couches

Une architecture propre distingue trois niveaux : la présentation (composants React), la logique métier (hooks personnalisés et services) et la persistance (module d'accès à la base). Cette découpe rend le code testable et facilite l'ajout de fonctionnalités au fil du temps.

Le pont IPC entre processus principal et renderer n'expose que des méthodes ciblées et typées : ajouterDepense, listerDepenses, supprimerDepense, mettreAJourDepense. Chaque méthode reçoit des arguments sérialisés et renvoie des objets simples, ce qui évite les fuites de références complexes à travers le contexte d'isolation.

TypeScript s'avère particulièrement utile ici. Le type Depense décrit la forme et les contraintes (montant en nombre, libellé en chaîne, date au format ISO, catégorie énumérée), et le contrat IPC devient auto-documenté. Les erreurs de frappe se détectent dès l'écriture du code.

Modéliser les dépenses dans SQLite

La table des dépenses doit se normaliser suffisamment pour permettre le filtrage par date et catégorie sans complexité superflue. Un schéma minimal comprend identifiant, montant, libellé, date et identifiant_catégorie, ainsi qu'une table séparée pour les catégories elles-mêmes.

better-sqlite3 prépare les requêtes une fois puis les réutilise, ce qui s'accorde au modèle synchrone du processus principal Electron. Le fichier de base de données se place dans app.getPath('userData'), ce qui le rend portable d'un système à l'autre et respecte les conventions de chaque plateforme.

Des index sur date et identifiant_catégorie accélèrent les rapports mensuels. Une vue agrégeant les dépenses par mois simplifie la requête du tableau de bord et offre une base stable pour des visualisations plus élaborées.

Construire l'interface avec React

Le modèle de composants React s'adapte bien aux formulaires, listes et résumés financiers. Un formulaire avec champs contrôlés, validation locale et gestionnaire de soumission maintient la cohérence entre l'état visuel et la base, sans logique dispersée.

Des bibliothèques comme Recharts ou Chart.js visualisent l'évolution des dépenses : camembert par catégorie, histogramme par mois. Les deux s'intègrent simplement aux données existantes et s'abonnent aux changements de props pour rester synchronisés.

Le renderer appelle window.api.listerDepenses() qui transite par le pont de préchargement. Les états de chargement, gérés via useEffect et un drapeau isLoading, améliorent la perception de performance lors de la lecture d'un grand nombre d'enregistrements.

Gérer les migrations et la persistance

Le schéma évolue à mesure que l'application grandit. Sans migrations, les changements de structure cassent les installations existantes et obligent les utilisateurs à réinitialiser leurs données. C'est précisément là qu'interviennent Prisma Migrate ou Knex, qui simplifient l'évolution du schéma.

Pour un projet qui utilise better-sqlite3 directement, des fichiers de migration manuels fonctionnent mais exigent de la rigueur. Les scripts s'appliquent au démarrage, en consultant une table de version qui trace les étapes déjà appliquées.

Les équipes qui envisagent des abstractions de plus haut niveau trouveront un guide détaillé sur les stratégies de migration avec Knex ou Prisma Migrate pour orchestrer ces changements sereinement, depuis un prototype jusqu'à une application multi-utilisateurs.

Emballager et distribuer l'application

electron-builder produit des installeurs pour Windows, macOS et Linux à partir d'une seule configuration. Le fichier electron-builder.yml précise les chemins d'icônes, les associations de fichiers et les réglages de mise à jour automatique, qui varient selon la plateforme cible.

La signature du code est indispensable sur macOS et recommandée sur Windows pour éviter les avertissements de sécurité. Windows exige des fichiers .pfx, macOS un certificat développeur Apple, et chaque système possède sa propre autorité de certification.

Les canaux de diffusion incluent GitHub Releases, Snap Store et Microsoft Store. Chacun impose son propre processus de soumission et de signature, mais une compilation multi-cibles automatisée réduit l'effort à un seul déclencheur de pipeline.

Bonnes pratiques pour un suivi fiable

Passer à l'étape suivante

Les développeurs qui souhaitent prolonger l'expérience retrouveront dans la zone web dédiée d'autres tutoriels et guides adaptés à ce type de stack, ainsi que des exemples de projets complets à explorer.

Un prototype fonctionnel tient en un week-end bien organisé. Les arbitrages les plus délicats concernent l'équilibre entre fonctionnalités et sobriété : viser d'abord l'essentiel, puis enrichir l'application au fil des retours utilisateurs garantit une base de code durable et facile à maintenir.