J'ai créé PeerSplit, une alternative peer-to-peer gratuite à Splitwise, en seulement deux semaines, de l'idée au lancement !
PeerSplit est une première application locale pour partager les dépenses de groupe. Il fonctionne hors ligne, est 100 % gratuit et privé, et ne nécessite aucune inscription ni aucune donnée personnelle.
Voici comment je l'ai construit et tout ce que j'ai appris en cours de route.
Je compte sur Splitwise depuis des années pour gérer les dépenses avec mes amis et colocataires. Mais avec ses récentes limites de transactions quotidiennes et ses publicités intrusives, son utilisation est devenue frustrante.
Je voulais une alternative gratuite, axée sur la confidentialité, qui ne nécessite pas de serveurs pour stocker ou synchroniser les données. Je ne confierais pas mes dépenses à un serveur tiers.
Après avoir travaillé sur des projets peer-to-peer et locaux comme un suivi d'entraînement et une application d'écriture sans distraction, j'ai réalisé que je pouvais appliquer la même approche au partage des dépenses.
C’est ainsi qu’est né PeerSplit. J'ai commencé à concevoir l'application.
Je suis nul en conception d'interfaces utilisateur.
Il y a quelques mois, je n'aurais pas pensé pouvoir créer une interface utilisateur aussi raffinée que celle de PeerSplit (certaines personnes disent même qu'elle a une meilleure UX que Splitwise).
Alors, comment ai-je réussi à faire ça ? Interface utilisateur Nuxt.
L'interface utilisateur de Nuxt est magnifique et offre une expérience de développement (DX) incroyable.
Il est également livré avec d'autres modules Nuxt utiles comme @nuxt/icon, @nuxtjs/tailwindcss et @nuxtjs/colormode.
Tout ce que j'avais à faire était de choisir une couleur primaire et j'avais tous les composants dont j'avais besoin (icônes, mode sombre et tout le reste) pour rassembler l'interface utilisateur de PeerSplit.
Pour le stockage et la synchronisation des données locales, j'ai opté pour cr-sqlite, qui s'appuie sur wa-sqlite et utilise des CRDT (types de données répliqués sans conflit).
Les CRDT sont parfaits pour les systèmes peer-to-peer car ils gèrent automatiquement les conflits : les utilisateurs peuvent donc travailler hors ligne et lorsqu'ils se reconnectent, les modifications fusionnent de manière transparente.
Cependant, cr-sqlite ne synchronise pas automatiquement les modifications sur le réseau. Il fournit uniquement des API pour exporter et fusionner les modifications. Vous devez envoyer manuellement ces modifications entre les appareils.
Pour gérer la synchronisation peer-to-peer sécurisée, j'ai utilisé Gun.js, qui fournit une base de données de graphiques distribués peer-to-peer.
L'API gun.user de Gun me permet de créer des nœuds cryptés pour chaque groupe. Toutes les modifications apportées à un groupe sont stockées sur ce nœud et synchronisées uniquement avec les membres du groupe, gardant tout privé.
Lorsqu'un utilisateur effectue une action, je prends les modifications exportées depuis cr-sqlite et je les transmets au nœud. Lorsque l'utilisateur revient en ligne, Gun synchronise les nouvelles modifications, gardant tout le monde au courant.
La mise en œuvre de cela de manière performante était délicate. Pour plus de détails, vous pouvez consulter le code source ici.
Une fonctionnalité intéressante de Splitwise (et maintenant de PeerSplit) est de « simplifier les dettes ».
Voici comment cela fonctionne : si A doit à B et que B doit à C, A peut simplement payer C directement pour potentiellement réduire le nombre de remboursements.
Dans PeerSplit, je calcule d'abord le solde net de chaque personne. Ensuite, je trie ces soldes et suggère des paiements un par un pour ramener le solde d’au moins une personne à zéro à chaque fois.
Ce tri garantit que tout le monde voit les mêmes remboursements sur ses appareils.
Ce n'est pas optimal à 100 % (certains groupes peuvent encore avoir jusqu'à n-1 paiements), mais cela fonctionne bien dans la plupart des cas.
Une solution optimale serait exponentielle à calculer et ne permettrait d'économiser que quelques paiements. C’était donc le meilleur compromis entre simplicité et rapidité !
export const groupGetPayments = (group) => { const payments = []; const balances = Object.entries(groupGetBalances(group)).map(([a, b]) => [ b, a, ]); balances.sort(); let i = 0, j = balances.length - 1; while (i < j) { if (balances[i][0] === 0) { i++; } else if (balances[j][0] === 0) { j--; } else if (-balances[i][0] > balances[j][0]) { payments.push({ from: balances[i][1], to: balances[j][1], value: round(balances[j][0]), }); balances[i][0] += balances[j][0]; balances[j][0] = 0; } else { payments.push({ from: balances[i][1], to: balances[j][1], value: round(-balances[i][0]), }); balances[j][0] += balances[i][0]; balances[i][0] = 0; } } return payments; };
Je voulais que PeerSplit fonctionne comme une application hors ligne, mais je ne voulais pas avoir à créer plusieurs applications natives ni à gérer le long processus de publication sur les magasins d'applications. Opter pour une Progressive Web App (PWA) était donc un choix évident.
Une PWA combine le meilleur des applications Web et mobiles, permettant aux utilisateurs de l'installer sur leurs appareils tout en bénéficiant de fonctionnalités hors ligne.
Pour transformer mon application Nuxt en PWA, j'ai utilisé vite-pwa.
J'ai conçu un logo SVG dans Figma et l'ai utilisé pour générer tous les actifs PWA nécessaires via le générateur d'actifs de vite-pwa.
Après cela, j'ai configuré le manifeste PWA et vite-pwa a automatiquement configuré le service worker pour moi.
J'ai configuré Nuxt pour qu'il pré-affiche tous les itinéraires, afin que mon application puisse fonctionner pleinement hors ligne.
Et c'est terminé. Merci d'avoir lu !
PeerSplit vient d'être lancé sur Product Hunt ! C'est mon premier lancement et j'aimerais votre soutien et vos commentaires.
Découvrez PeerSplit sur Product Hunt
PeerSplit est une source équitable, alors n'hésitez pas à contribuer ou à soumettre des demandes de fonctionnalités sur GitHub.
PeerSplit est une application peer-to-peer gratuite, d'abord locale, qui vous aide à partager et suivre facilement et en privé les dépenses de groupe.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!