Criei um aplicativo social em uma semana com Claude Code
Passei quase uma semana construindo um aplicativo social com o Claude Code da Anthropic. A maior parte desse trabalho acontecia tarde da noite, às vezes depois das 2 da manhã, iterando recursos até que eu tivesse algo que valesse a pena compartilhar com os amigos.
A Anthropic gera um relatório semanal de insights para usuários do Claude Code. O meu contou uma história interessante: 384 mensagens, 27 sessões, 168 arquivos tocados, seis dias. Um tempo de resposta médio de 29 segundos – eu mal estava lendo a saída antes de responder. Eles descreveram meu estilo como “reativo e corretivo, em vez de orientado por especificações”, o que é correto. Eu estava me movendo rápido, consertando as coisas quando elas quebravam e aprendendo o que funcionava ao longo do caminho.
O que eu estava construindo: um aplicativo social privado para meu grupo unido de amigos. Compartilhamos gravações ao vivo de bandas – Phish, Grateful Dead, esse mundo – filmes favoritos, livros e quais shows planejamos assistir neste verão. Pense em um pequeno canto da Internet apenas para convidados, para pessoas que se preocupam profundamente com música ao vivo e querem um lugar para conversar sobre isso com pessoas que realmente conhecem. O bate-papo ao vivo entre pessoas em turnê no sofá e pessoas no pit será o próximo.
O aplicativo está ativo. Meus amigos estão usando. Ele roda em Go com uma arquitetura de UI orientada a servidor e é fornecido como aplicativos nativos para iOS e Android. Construí tudo isso em uma semana com Claude Code e quero contar como foi realmente isso.
Toda a primeira versão foi construída à noite, na cama, em um iPad de 11″, usando o aplicativo Claude Code conectado a um repositório GitHub vazio. Não toquei em um computador. Em poucas horas, eu tinha um aplicativo funcionando – login, feed, postagem – implantado e rodando no Railway. A partir daí, o escopo se moveu na direção certa: integração com Spotify para que você pudesse pesquisar e anexar álbuns e faixas diretamente, integração com setlist.fm para obter dados reais de shows – locais, datas e setlists reais à medida que são postados depois de cada noite – e deixar as pessoas marcarem as datas em que compareceriam. Os ossos estavam lá rapidamente, fazendo com que parecesse que algo que realmente valesse a pena usar demorava mais.

No dia em que convidei a maioria dos meus amigos, uma migração de banco de dados corrompeu os dados do carimbo de data/hora de produção.
A migração modificou os tipos de coluna em um banco de dados em execução. Os carimbos de data e hora codificam suposições de fuso horário no nível do tipo – altere-os no meio do voo e os dados não migram, eles quebram. A alimentação caiu. Pedi a Claude para consertar. Cada correção piorou as coisas: nomes de colunas errados, sintaxe SQL quebrada, aritmética de fuso horário incorreta, até que finalmente foi executada uma substituição que não pôde ser desfeita. O relatório da Anthropic resumiu isso como “as migrações de banco de dados de Claude se tornaram um filme de desastre completo – cada correção gerou um novo incidente de produção, destruindo permanentemente os dados de carimbo de data/hora”. Isso é exato. Alguns desses dados simplesmente desapareceram.
Passei anos trabalhando em bancos de dados. Eu sabia exatamente o que estava acontecendo e por que era catastrófico. Deixei acontecer de qualquer maneira porque estava codificando a vibração, sem tirar as mãos do volante, apenas observando Claude dirigir.
O desastre do carimbo de data e hora foi o pior incidente, mas o padrão por trás dele aparecia constantemente: Claude se movendo com confiança na direção errada e eu não parando logo. A depuração de notificações push é outro exemplo. A falta de tokens de APNs fez com que Claude se aprofundasse no provisionamento de perfis, certificados e direitos – um caminho longo e de aparência plausível que se revelou completamente errado. O problema real estava faltando AppDelegate métodos no código que o próprio Claude havia escrito anteriormente. O relatório contou 30 casos de depuração de abordagem errada em todo o projeto. É muito tempo assistindo uma coisa muito capaz resolver o problema errado.
O problema de reinicialização do servidor era mais mundano, mas de alguma forma mais enlouquecedor. Após qualquer alteração no código Go, você deve reiniciar o backend para que as alterações tenham efeito – linguagem compilada, nada exótico. Claude continuou esquecendo. Continuei não vendo nenhuma mudança, presumindo que algo estava quebrado, investigando, não encontrando nada, eventualmente percebendo que o processo antigo ainda estava em execução. Isso aconteceu em quatro ou mais sessões antes de eu escrever uma regra explícita o suficiente para que ela realmente funcionasse. pkill foi o culpado – ele falha silenciosamente, deixando o antigo processo vivo. A correção foi lsof para encontrar o PID, kill -9 nesse processo específico, espere, reinicie, verifique. Um procedimento que leva trinta segundos e tem que ser anotado ou não acontece.
O que foi construído, apesar de tudo isso, é genuinamente surpreendente para mim.
Uma migração de UI completa orientada pelo servidor – o back-end envia toda a interface como JSON, o front-end do React apenas a renderiza, sem páginas codificadas. Este tem uma história. Eu instruí Claude desde o início a construir um aplicativo SDUI, mas a maior parte do código inicial chegou ao React de qualquer maneira. A vantagem é que as páginas iniciais eram genuinamente bonitas – Claude tem bom gosto em React UI – e adorei sua aparência. A desvantagem era que permitir uma estratégia móvel adequada exigia SDUI completo, o que significava migrar cada página individualmente, cada uma precisando ser reestilizada do zero. Esse trabalho levou tempo real.
A migração também expôs um padrão que se repetiria ao longo do projeto: Claude reivindicando vitória prematuramente. Botões que não funcionaram. Chamadas de front-end para rotas de back-end que não existiam — APIs fantasmas, conectadas com segurança. Formulários enviados com êxito da interface do usuário, enquanto eliminam silenciosamente metade de seus parâmetros no caminho para o back-end. Claude criaria um formulário, criaria um endpoint de API, conectaria-os e declararia o recurso concluído. O formulário seria enviado. O endpoint retornaria 200. Nada seria realmente salvo.
Eventualmente, tive que codificar regras explícitas: quando você adiciona uma nova API de backend, teste-a com curl antes de tocar no frontend. Ao conectar uma chamada de front-end, verifique se a rota realmente existe. Quando um formulário for enviado, confirme se todos os parâmetros chegam ao backend. A qualidade melhorou significativamente depois que essas proteções foram escritas.
Aplicativos iOS e Android, ambos no TestFlight e prontos para testes Android na mesma semana. Notificações push de ponta a ponta conectadas a cada interação. Um recurso alimentado por IA que mostra o que seus amigos estão fazendo agora. Um sistema de gerenciamento de convites, scripts de construção automatizados, 107 migrações de banco de dados, gráficos de engajamento do usuário, um changelog que notifica os usuários quando algo novo é lançado.
A capacidade de Claude de manter em mente uma grande mudança de vários arquivos — uma migração de banco de dados, um novo manipulador de API, um componente de front-end e uma correção de layout móvel, tudo em uma sessão coerente — é onde ele ganha tudo. Quando o escopo está claro e o padrão é conhecido, ele se move a uma velocidade que não parece real.
Apenas 2 das minhas 27 sessões alcançaram plenamente o que me propus fazer. Esse número parece contundente até você considerar que 27 sessões em seis dias trouxeram algo real que as pessoas estão usando. As sessões que falharam quase sempre tiveram o mesmo formato: abertas, sem ponto de parada claro, depurando algo visual ou com estado onde Claude não tinha ciclo de feedback e eu tinha muita paciência para abordagens erradas. As sessões que funcionaram foram intensas – uma coisa conhecida, feita corretamente, depois para.
O relatório de insights também veio com recomendações e vale a pena transmiti-las.
O maior deles: ganchos. Claude Code suporta ganchos de pós-edição – comandos shell que são acionados automaticamente após a alteração dos arquivos. O relatório sugeriu conectar um para reiniciar o back-end Go após qualquer .go edição de arquivo, o que teria eliminado a perda de tempo mais recorrente em todo o projeto. Ainda não configurei. Eu vou.
O relatório também sugeriu a adição de barreiras de proteção explícitas CLAUDE.md — o arquivo de instruções do projeto que Claude lê no início de cada sessão. Coisas como: após qualquer alteração no código de backend, sempre reinicie o servidor antes de testar. Nunca execute migrações ou implemente correções sem a aprovação explícita do usuário. Quando o usuário informar que uma camada está funcionando, pare de investigar essa camada. Limite-se a duas tentativas de uma única abordagem – se não funcionou duas vezes, dê um passo atrás e explique o que aprendeu antes de tentar novamente. A maioria deles eu cheguei da maneira mais difícil ao longo da semana. Tê-los anotados desde o início teria economizado dias.
A outra recomendação foi sobre a disciplina da sessão. Cinco das minhas sessões foram completamente perdidas nos limites do contexto – a conversa ficou muito longa e, quando tentei me recuperar com /compactele simplesmente retornou “falha ao compactar” e me deixou preso no meio da tarefa, sem nenhum caminho a seguir, exceto fechar Claude e começar do zero. Perder o contexto no meio da sessão, no meio do pensamento, no meio da correção, sem transferência e sem resumo, é um tipo particular de frustração. A solução é óbvia em retrospecto: termine cada sessão em um ponto de parada natural, escreva um breve resumo do estado, comece do zero. As sessões em que enviei algo foram as mais restritas. Continuei ignorando esse sinal.
O relatório chamou meu estilo de “ambicioso” e observou que “tolero alto atrito devido a repetidas abordagens erradas”. Eu diria de outra forma: eu estava construindo algo que realmente me importava, para pessoas que eu realmente conhecia, e o prazo era real. A turnê de primavera é o teste. A turnê de verão é o objetivo. Isso muda sua relação com o atrito.
Você não está escrevendo código com Claude Code. Você está dirigindo. A lacuna entre essas duas coisas é onde mora toda a frustração e também de onde vem toda a velocidade. Quando você aceita que é a camada de julgamento – decidindo quando redirecionar, quando parar, quando uma solução está piorando as coisas – a ferramenta se torna algo genuinamente extraordinário.
A turnê de primavera está chegando. O aplicativo está pronto.
Postscript: enquanto escrevia esta postagem no blog, o mesmo padrão me atingiu novamente. O aplicativo foi implantado perfeitamente no Railway com uma construção simples de nixpacks. Ao corrigir um recurso não relacionado, adicionei uma verificação de integridade à configuração como uma alteração indireta – desnecessária, mas parecia inofensiva. Posteriormente, mudar para uma compilação do Dockerfile para incorporar uma variável de ambiente fez com que a compilação demorasse mais do que os nixpacks, de modo que a verificação de integridade começou a expirar antes que o serviço estivesse pronto. As implantações falharam. Em vez de identificar a verificação de integridade como culpada, cinco commits sucessivos alteraram a porta, o construtor, o comando start e o Dockerfile em várias combinações. Nada disso funcionou, porque o verdadeiro problema nunca foi diagnosticado. Toda a cadeia de falhas remonta a uma linha desnecessária adicionada enquanto se trabalhava em algo totalmente diferente. Algumas coisas não mudam.
