Desenvolvedor Full-Stack — TypeScript/Node e Python

Luiz Augusto Moreira Barbosa

Construo e opero sistemas em produção, de ponta a ponta.

2
sistemas próprios em produção
~49 mil
linhas de TypeScript
271
endpoints REST somando os dois
64
tabelas modeladas
59
arquivos de teste automatizado
1 VPS
operado por mim: Docker, Nginx, backup diário

Sistemas em produção

Dois sistemas que eu escrevi, publiquei e mantenho no ar

Não são exercícios. Rodam num VPS que eu administro, com HTTPS, backup, rotinas agendadas e monitoramento de erro. Você pode entrar e navegar.

Case 01 — SaaS multi-tenant

Plataforma de Gestão para Escritórios Contábeis

Sistema completo de operação de um escritório de contabilidade: carteira de empresas, obrigações fiscais com prazo, documentos com OCR, honorários, conciliação bancária e portal do cliente.

TypeScriptNext.js 15 React 19Prisma PostgreSQL 16BullMQ + Redis MinIO/S3NextAuth + 2FA TailwindDocker NginxGitHub Actions
49.266linhas TypeScript
202handlers HTTP
47tabelas
176índices (62 compostos)
38suítes de teste
24migrations aplicadas

O problema

Um escritório contábil toca dezenas de empresas ao mesmo tempo, e cada uma tem obrigações com prazo fatal — perder um vencimento vira multa para o cliente. Na prática, a informação fica espalhada: documentos chegam por WhatsApp e e-mail, os prazos moram na cabeça de quem executa, honorários são controlados em planilha e o extrato bancário é digitado à mão. Ninguém enxerga o todo.

A solução

Uma plataforma multi-tenant onde cada escritório tem seu próprio espaço: cadastro de empresas com carteira por departamento, geração automática das tarefas fiscais a partir de um calendário de obrigações, documentos versionados com texto extraído por OCR, honorários com cobrança, importação de extrato OFX com conciliação, chat interno e um portal onde o cliente final envia documentos e acompanha o andamento — sem precisar ligar para o escritório.

Decisões de arquitetura

1 Isolamento multi-tenant em nível de linha

Todos os dados carregam tenantId, e o acesso passa por um guard central em vez de cada consulta repetir o filtro.

Por quê: num SaaS contábil, uma falha de isolamento significa mostrar o dado fiscal de uma empresa para outra — o pior defeito possível nesse domínio. Centralizar o filtro faz o esquecimento acidental deixar de ser uma opção, e há testes de integração que tentam ativamente cruzar a fronteira entre tenants para provar que ela segura.

2 OCR assíncrono em worker dedicado

O upload apenas enfileira; um worker separado consome a fila BullMQ/Redis, extrai o texto e grava o resultado.

Por quê: OCR de um PDF grande leva de segundos a minutos. Fazer isso dentro da requisição significaria travar o upload, estourar timeout do proxy e derrubar a experiência justamente quando o usuário está enviando vários arquivos. Com fila, a resposta é imediata, o processamento ganha retry automático e o pico de trabalho não contamina o tempo de resposta do site.

3 Importação OFX com conciliação bancária

O extrato do banco entra como arquivo OFX e as transações são casadas com os lançamentos do sistema, uma a uma.

Por quê: digitar extrato é o gargalo real do escritório e a maior fonte de erro humano. Ler o formato que o banco já exporta elimina a digitação e transforma conferência em decisão: o sistema propõe o casamento, a pessoa confirma ou ignora.

4 Operação pensada como parte do produto

Duas réplicas da aplicação atrás do Nginx, pgbouncer na frente do banco, seis rotinas agendadas de negócio e backup diário.

Por quê: aplicações Next.js abrem muitas conexões e o Postgres não gosta disso — o pgbouncer concentra tudo num pool. Duas réplicas permitem publicar versão nova sem janela de indisponibilidade. E o backup roda todo dia às 02:00 porque sistema sem backup testado é sistema que ainda não caiu.

Como as peças se encaixam

Arquitetura do sistema contábil O navegador acessa o Nginx com HTTPS, que distribui entre duas réplicas da aplicação Next.js. As réplicas falam com o PostgreSQL através do pgbouncer. Uploads de documento são enfileirados no Redis e consumidos por um worker de OCR, que grava os arquivos no MinIO. Rotinas agendadas disparam tarefas de negócio diariamente. Navegador HTTPS Nginx proxy + TLS app · réplica 1 Next.js 15 app · réplica 2 Next.js 15 pgbouncer pool PostgreSQL 16 Redis fila BullMQ worker OCR MinIO / S3 documentos upload enfileirado
Requisição, fila e persistência. O ramo pontilhado é assíncrono: o upload responde na hora e o OCR acontece depois, fora do ciclo da requisição.

Entre no sistema agora

no ar dados fictícios

Instância de demonstração com dados inventados — nenhum escritório ou empresa real. Escolha por qual perfil de acesso quer explorar: cada um enxerga uma parte diferente do sistema.

Gestor do escritório Visão completa: carteira de empresas, equipe, financeiro, honorários e calendário fiscal. gestor@demo.comsenha123
Funcionário A ótica de quem executa: só as empresas da sua carteira e as tarefas do seu departamento. ana@demo.comsenha123
Cliente (portal) O lado do cliente do escritório: enviar documentos, trocar mensagens e acompanhar processos. cliente@example.comsenha123
Painel inicial do sistema contábil: pendências da semana agrupadas por tipo (fiscal, tarefas, certificados, honorários) e lista de honorários a vencer por empresa.
Painel inicial — pendências da semana
Tela de listagem da carteira de empresas do escritório, em grade de cartões com logo, nome e filtros por status e regime tributário.
Carteira de empresas do escritório
Formulário de cadastro de nova empresa: razão social, CNPJ, regime tributário, dados de contato e endereço.
Cadastro de empresa

Case 02 — dados, scraping e IA aplicada

Plataforma de Inteligência de Preços

Sistema de monitoramento competitivo para um cliente do setor farmacêutico: coleta os preços dos concorrentes, descobre qual produto corresponde a qual e mostra onde há oportunidade de preço.

PythonFastAPI PostgreSQLPlaywright sentence-transformersAPScheduler Gunicornsystemd Nginx
22.608linhas Python
69endpoints
17tabelas
1.836produtos monitorados
2.330registros de preço
4concorrentes coletados

O problema

A empresa precisava saber, todo dia, se estava cara ou barata em relação à concorrência. Conferir isso à mão é inviável: são mais de 1.800 produtos contra quatro lojas diferentes. E existe um problema mais sutil — o mesmo item aparece com nome diferente em cada site. Comparar por texto exato simplesmente não funciona.

A solução

Uma plataforma que coleta as ofertas dos concorrentes, decide automaticamente qual produto do catálogo corresponde a qual anúncio, e classifica cada correspondência por confiança. O operador confirma ou rejeita, e o dashboard mostra onde o concorrente está mais barato — com relatórios em PDF agendados e histórico de preço acumulando desde abril de 2026.

Decisões de arquitetura

1 Correspondência semântica com decisão humana

Cada produto vira um vetor (embedding); a comparação é por similaridade de cosseno, com faixas de confiança — equivalente, muito similar, similar — e um limiar mínimo abaixo do qual nada é sugerido.

Por quê: “Lidocaína 12% — Anestésico 100 g” e “Lidocaína 12% 100g” são o mesmo produto para uma pessoa e coisas distintas para um comparador de texto. O embedding captura sentido, não grafia. As faixas existem porque decisão de preço não pode sair de um palpite fraco: acima do limiar o sistema sugere, e a confirmação humana vira sinal registrado, realimentando o motor.

2 Pool de browsers e um módulo por concorrente

Os navegadores headless ficam num pool reaproveitável, e cada loja tem seu próprio módulo de coleta, isolado dos demais.

Por quê: abrir um Chromium por requisição é caro e derruba o servidor sob carga. E sites de terceiros mudam de HTML sem avisar — com um módulo por concorrente, quando uma fonte quebra só aquela fonte para; o ciclo continua entregando as outras três em vez de falhar inteiro.

3 Cache com TTL e deduplicação de jobs

As ofertas coletadas ficam em cache por seis horas, e pedidos repetidos para o mesmo produto são unificados numa única coleta.

Por quê: sem isso, dez usuários abrindo o mesmo produto viram dez visitas simultâneas ao site do concorrente — desperdício de tempo e um jeito rápido de ser bloqueado. O TTL equilibra: dado fresco o bastante para decidir preço, leve o bastante para ser educado com quem está do outro lado.

Como as peças se encaixam

Arquitetura da plataforma de preços Um agendador e pedidos sob demanda acionam o pool de browsers headless, que executa um módulo de coleta independente por concorrente. As ofertas passam por um cache com validade de seis horas, o motor de embeddings casa produto e anúncio por similaridade, e o operador confirma ou rejeita cada correspondência antes de virar histórico no banco. Agendador APScheduler Sob demanda API FastAPI pool de browsers Playwright concorrente A concorrente B concorrente C concorrente D cache TTL 6h + dedup matching embeddings decisão humana confirma / rejeita PostgreSQL histórico de preço
Uma fonte que quebra não derruba o ciclo: cada concorrente é um módulo isolado. O que o operador confirma volta como sinal para o motor.

Entre na plataforma agora

no ar instância separada da produção

Esta é uma instância de demonstração independente — banco, serviço e domínio próprios, sem ligação com o ambiente do cliente. Os concorrentes aparecem como “Concorrente A/B/C/D” e os preços foram embaralhados: o que se demonstra aqui é o sistema, não os dados comerciais de ninguém.

Operador O uso do dia a dia: comparar produtos, revisar correspondências e confirmar ou rejeitar cada match. operador2demo1234
Administrador Tudo do operador, mais gestão de usuários, agendamento de relatórios e trilha de auditoria. admindemo1234
Dashboard da plataforma de preços: produtos ativos, matches gerados, concorrentes mais baratos, maiores gaps de preço e fila de correspondências pendentes de revisão.
Dashboard — visão geral competitiva
Catálogo de produtos em grade, com preço, categoria e indicador de produto em destaque, navegável por categoria na barra lateral.
Catálogo de produtos monitorados
Painel de correspondência de um produto: quatro concorrentes lado a lado, cada um com o item casado, similaridade calculada e opção de confirmar ou corrigir manualmente.
Correspondência de produto — decisão do operador

Outros projetos

Projetos menores e trabalho acadêmico

Recortes de coisas que construí estudando sistemas operacionais, redes, hardware e web — com código aberto onde faz sentido.

Simulador de concorrência e escalonamento

Threads competindo por região crítica com semáforo, e comparação prática entre os algoritmos de escalonamento FCFS e SJF.

Python ver no GitHub

BioPag — pagamento por biometria

Projeto de feira tecnológica (FETIN/Inatel): aplicação Django conversando com um Arduino por comunicação serial para autenticar pagamento por impressão digital.

Django · Arduino ver no GitHub

Projeto Biblioteca

API em Django REST com front próprio: consulta de acervo, reservas, empréstimos e painel administrativo para os funcionários.

Django REST ver no GitHub

Quiz com sockets TCP

Cliente e servidor escritos em Python puro, sem framework: protocolo próprio sobre TCP para um jogo de perguntas multiusuário.

Python · sockets ver no GitHub

Observatório do Turismo em desenvolvimento

Trabalho de conclusão de curso: plataforma web do Observatório do Turismo de Santa Rita do Sapucaí, em parceria com a Secretaria Municipal de Turismo.

TCC · 2026

Ferramentas

Stack técnica

O que eu uso de verdade nos sistemas acima — não uma lista de tudo que já vi.

Linguagens

TypeScriptJavaScript PythonSQL Java

Backend

Next.js (App Router)Node.js FastAPIDjango NextAuth · JWT · 2FA TOTPREST

Front-end

React 19Tailwind HTML semânticoCSS moderno Acessibilidade

Dados e filas

PostgreSQLPrisma SQLAlchemyRedis BullMQpgbouncer MinIO / S3

Infraestrutura

Docker · ComposeNginx Linux (Ubuntu)systemd Let's EncryptGitHub Actions cron · backup

Qualidade

VitestPlaywright pytestESLint SentryZod

Método

Como eu trabalho

Meu ciclo não termina no merge. Termina quando está no ar, monitorado e alguém consegue usar.

Entender antes de codar

Primeiro o problema de quem vai usar. A conciliação bancária existe porque digitar extrato consumia horas — não porque era interessante de implementar.

Propor e decidir

Escolho a solução mais simples que resolve, e registro o motivo. Toda decisão de arquitetura aqui tem um “por quê” que sobrevive a uma pergunta difícil.

Implementar com teste

Teste onde o erro dói: isolamento entre clientes, cálculo de prazo fiscal, fluxo de login. Cobertura não é meta — proteção do que importa é.

Publicar de forma reversível

Backup antes de migrar, imagem anterior guardada para rollback, validação de configuração antes de recarregar. Deploy que não dá para desfazer é aposta.

Manter e observar

Depois do deploy vem o log, o alerta de erro, o certificado que renova sozinho e a rotina que roda de madrugada. Operar ensina o que desenvolver esconde.

IA como ferramenta, com revisão

Uso IA no dia a dia para acelerar, mas leio, questiono e testo o que sai — a responsabilidade pelo código que vai para produção continua sendo minha.

Sobre

Quem está por trás

Sou graduando em Engenharia de Computação pelo Inatel, com conclusão prevista para dezembro de 2026. Hoje trabalho como Técnico de Sistemas 1 no Inatel/CIDC, onde além das minhas entregas sou responsável por treinar e acompanhar os estagiários do time — o que me obriga a explicar decisão técnica em voz alta, revisar código dos outros e documentar o que antes só existia na minha cabeça.

Meu histórico público de código começa em julho de 2023, e os dois sistemas desta página nasceram de necessidades reais: um escritório contábil que precisava parar de perder prazo em planilha, e uma empresa que precisava acompanhar preço de concorrente sem fazer isso à mão. Ambos estão no ar, e sou eu quem mantém o servidor de pé.

Contato

Vamos conversar

Estou aberto a oportunidades como desenvolvedor full-stack. Se quiser entender qualquer decisão técnica desta página em profundidade, é só chamar — todo número aqui tem código atrás.