Eu criei o PeerSplit — uma alternativa gratuita e peer-to-peer ao Splitwise — em apenas duas semanas, da ideia ao lançamento!
PeerSplit é um aplicativo local para dividir despesas de grupo. Funciona offline, é 100% gratuito e privado e não requer inscrições ou quaisquer dados pessoais.
Veja como eu o construí e tudo que aprendi ao longo do caminho.
Há anos confio no Splitwise para gerenciar despesas com amigos e colegas de quarto. Mas com seus recentes limites de transações diárias e anúncios intrusivos, seu uso tornou-se frustrante.
Eu queria uma alternativa gratuita e que priorizasse a privacidade, que não exigisse que servidores armazenassem ou sincronizassem dados. Eu não confiaria minhas despesas com um servidor de terceiros.
Depois de trabalhar em projetos ponto a ponto que priorizam o local, como um rastreador de exercícios e um aplicativo de escrita sem distrações, percebi que poderia aplicar a mesma abordagem à divisão de despesas.
Foi assim que nasceu o PeerSplit. Comecei a projetar o aplicativo.
Eu sou péssimo em projetar UIs.
Alguns meses atrás, eu não teria pensado que poderia construir uma UI tão refinada quanto a do PeerSplit (algumas pessoas até dizem que tem uma UX melhor que o Splitwise).
Então, como consegui fazer isso? IU do Nuxt.
A UI do Nuxt é linda e oferece uma experiência de desenvolvedor incrível (DX).
Ele também vem com outros módulos úteis do Nuxt, como @nuxt/icon, @nuxtjs/tailwindcss e @nuxtjs/colormode.
Tudo o que tive que fazer foi escolher uma cor primária e tinha todos os componentes necessários – ícones, modo escuro e tudo mais – para reunir a IU do PeerSplit.
Para armazenamento e sincronização de dados locais, optei pelo cr-sqlite, que se baseia no wa-sqlite e usa CRDTs (tipos de dados replicados sem conflitos).
Os CRDTs são ótimos para sistemas peer-to-peer porque lidam com conflitos automaticamente – para que os usuários possam trabalhar off-line e, quando se reconectarem, as alterações sejam mescladas perfeitamente.
No entanto, o cr-sqlite não sincroniza alterações na rede por si só. Ele fornece apenas APIs para exportar e mesclar alterações. Você precisa enviar manualmente essas alterações entre dispositivos.
Para lidar com a sincronização ponto a ponto segura, usei Gun.js, que fornece um banco de dados gráfico distribuído ponto a ponto.
A API gun.user do Gun me permite criar nós criptografados para cada grupo. Todas as alterações de um grupo são armazenadas nesse nó e sincronizadas apenas com os membros do grupo, mantendo tudo privado.
Quando um usuário executa uma ação, pego as alterações exportadas do cr-sqlite e as envio para o nó. Quando o usuário volta a ficar online, o Gun sincroniza as novas alterações, mantendo todos atualizados.
Implementar isso de maneira eficiente foi complicado. Para mais detalhes, você pode conferir o código-fonte aqui.
Um recurso interessante do Splitwise (e agora do PeerSplit) é "simplificar dívidas".
Funciona assim: se A deve B e B deve C, A pode simplesmente pagar C diretamente para reduzir potencialmente o número de reembolsos.
No PeerSplit, primeiro calculo o saldo líquido de cada pessoa. Em seguida, classifico esses saldos e sugiro pagamentos um por um para zerar o saldo de pelo menos uma pessoa a cada vez.
Essa classificação garante que todos vejam os mesmos pagamentos em seus dispositivos.
Não é 100% ideal (alguns grupos ainda podem ter até n-1 pagamentos), mas funciona bem na maioria dos casos.
Uma solução ideal seria exponencial para calcular e economizaria apenas alguns pagamentos. Portanto, esta foi a melhor troca entre simplicidade e velocidade!
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 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; };
Eu queria que o PeerSplit funcionasse como um aplicativo offline, mas não queria passar pelo incômodo de construir vários aplicativos nativos ou lidar com o longo processo de publicá-los em lojas de aplicativos. Portanto, optar por um Progressive Web App (PWA) foi a escolha certa.
Um PWA combina o melhor dos aplicativos da web e móveis, permitindo que os usuários o instalem em seus dispositivos enquanto aproveitam os recursos off-line.
Para transformar meu aplicativo Nuxt em um PWA, usei vite-pwa.
Projetei um logotipo SVG no Figma e usei-o para gerar todos os ativos PWA necessários por meio do gerador de ativos do vite-pwa.
Depois disso, configurei o manifesto do PWA e vite-pwa configurou automaticamente o service worker para mim.
Configurei o Nuxt para pré-renderizar todas as rotas, para que meu aplicativo pudesse funcionar totalmente offline.
E isso é um embrulho. Obrigado por ler!
PeerSplit acaba de ser lançado no Product Hunt! É meu primeiro lançamento e adoraria seu apoio e feedback.
Confira PeerSplit no Product Hunt
PeerSplit é uma fonte justa, então sinta-se à vontade para contribuir ou enviar solicitações de recursos no GitHub.
PeerSplit é um aplicativo ponto a ponto gratuito, local e ponto a ponto, que ajuda você a dividir e monitorar as despesas do grupo de maneira fácil e privada.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3