NN.← Voltar ao portfólio

Estudo de caso · P01

Minhas Contas

Sistema financeiro pessoal. Construído porque eu precisava.

Comecei com uma planilha que eu usava há anos para controlar meu dinheiro. Ela cresceu, ficou complexa, cheia de fórmulas frágeis — e um dia corrompeu. Então eu decidi construir o produto que eu realmente precisava.

Status

Em desenvolvimento

Stack

ReactTypeScriptFirebaseFirestoreTailwind CSSFramer MotionPWA
01

O Problema

Planilhas para controle financeiro pessoal têm um problema fundamental: elas são estáticas. Cada mês era uma aba nova. O saldo de fevereiro não sabia o que havia acontecido em janeiro. Parcelamentos precisavam ser atualizados manualmente. Cartões de crédito eram um pesadelo.

Tentei apps de mercado. Nenhum controlava o que eu precisava:

  • →Múltiplos bancos com saldos independentes
  • →Parcelamentos que se propagam automaticamente pelos meses seguintes
  • →Benefícios VA/VR separados do dinheiro pessoal
  • →Investimentos sem misturar com conta corrente
  • →Sincronização entre dispositivos sem precisar abrir o computador

Decisão

Construir exatamente o que eu precisava. Sem tentar criar um produto genérico para todo mundo. Otimizado para o meu fluxo financeiro específico — e suficientemente estruturado para que qualquer pessoa com as mesmas necessidades possa usar.

02

Arquitetura e Decisões

A decisão mais crítica foi como modelar o banco de dados para que o saldo se propague entre meses automaticamente, sem recalcular tudo toda vez que um lançamento é adicionado.

Propagação de saldo

Cada mês armazena o saldo inicial (herdado do mês anterior) e os lançamentos do período. Ao atualizar um lançamento em março, apenas os meses posteriores são recalculados — não o histórico inteiro.

Firebase como backend

Escolha consciente: autenticação, banco de dados e hospedagem num único SDK. Para um projeto pessoal sem servidor dedicado, Firebase reduz fricção sem sacrificar consistência.

Firestore vs. SQL

Dados financeiros são hierárquicos por natureza (conta → mês → lançamento). Documentos aninhados no Firestore representam essa hierarquia melhor do que tabelas relacionais para esse caso específico.

Arquitetura reativa

onSnapshot em vez de chamadas pontuais. O estado da UI reflete sempre o estado do banco de dados — sem polling, sem cache manual.

03

Desafios Técnicos

Race Conditions no Firestore

Quando o usuário adiciona vários lançamentos rapidamente, múltiplos callbacks onSnapshot disparam quase ao mesmo tempo. Cada um lê o estado atual, calcula o novo saldo e tenta escrever de volta — resultando em estado inconsistente.

Solução: Mutex usando useRef para serializar operações de escrita. A fila garante que apenas uma operação acontece por vez, sem bloquear a UI.

const writeLock = useRef(false);
const writeQueue = useRef<(() => Promise<void>)[]>([]);

const enqueue = (op: () => Promise<void>) => {
  writeQueue.current.push(op);
  processQueue();
};

const processQueue = async () => {
  if (writeLock.current) return;
  writeLock.current = true;
  while (writeQueue.current.length > 0) {
    const op = writeQueue.current.shift()!;
    await op();
  }
  writeLock.current = false;
};

Modelagem de parcelamentos

Parcelamentos precisam aparecer nos meses corretos sem que o usuário configure cada parcela manualmente. A solução foi armazenar a parcela original com metadados (total de parcelas, data de início) e gerar as ocorrências em runtime — nunca duplicando dados no banco.

Isso significa que alterar o valor de um parcelamento atualiza todas as parcelas automaticamente, sem precisar editar cada mês individualmente.

04

O que foi construído

Múltiplos bancos

Saldos independentes por conta, propagados automaticamente entre meses.

Parcelamentos

Cartões com limite real. Parcelas que aparecem nos meses corretos sem configuração manual.

Faturas automáticas

A fatura fecha, os lançamentos se consolidam. Nenhuma soma manual.

Benefícios VA/VR

Saldo separado do dinheiro pessoal, com controle de uso diário.

Investimentos

Não misturado com conta corrente. Visão clara de patrimônio vs. liquidez.

Sync em tempo real

onSnapshot do Firestore. Abrir em dois dispositivos mostra o mesmo estado.

PWA

Instalável no celular. Funciona offline para leituras. Ícone na tela inicial.

05

O que aprendi

Modelagem no Firestore é diferente de SQL

Pensar em documentos ao invés de tabelas muda como você estrutura dados. A hierarquia natural dos dados financeiros se encaixa melhor em documentos aninhados do que em joins.

Race conditions são invisíveis até serem devastadoras

Aprendi a identificar operações potencialmente concorrentes antes de escrever. Qualquer operação que lê e escreve estado assincronamente é suspeita.

PWA é subestimado

A diferença entre abrir um link e ter um ícone na tela inicial muda o comportamento de uso completamente. Instalação é retenção.

Produto ao vivo

Minhas Contas está rodando.
Pode testar agora.