Usando o Cursor para criar um aplicativo sem escrever uma única linha de código.
Há algum tempo, escrevi um artigo detalhando minha primeira incursão na criação de um aplicativo usando IA. Na época, usei Claude para gerar código, que colei em meu IDE para construir um protótipo de um jogo de dados simples chamado Pig. Para fazer o aplicativo funcionar, tive que passar algum tempo aprendendo Dart/Flutter para fazer minha própria depuração.
Muitos sugeriram que eu tentasse o Cursor, e eles estavam certos...foi uma virada de jogo, eu recomendo. Com o Cursor, consegui gerar o aplicativo inteiro sem fazer uma única edição direta no código. Peter Yang chama isso de "codificação de vibração" (ele é muito melhor nisso).
Dito isso, a integração do Cursor IDE não é tão completa quanto eu esperava e o processo não foi totalmente tranquilo. No geral, levei cerca de 15 horas para gerar um aplicativo que me senti confortável em compartilhar, mais rápido do que as 20 horas que levei na minha primeira tentativa, mas ainda muito longe da afirmação "em 25 minutos" que costumo ver nas redes sociais. (Também levei mais 5 horas para descobrir como publicá-lo.) Você pode experimentar o aplicativo aqui.
Take-aways
Que diferença faz um botão! No Cursor, o código está à esquerda e o painel de bate-papo AI está à direita. Quando a IA gera código, há um botão "Aplicar" que puxa o código, completo com "destaque de diferença" para mostrar as alterações feitas e um botão "Aceitar" para aplicá-las. O fluxo é muito mais fácil e rápido do que copiar e colar de uma janela diferente, e há muito mais clareza sobre o que exatamente foi alterado.
O cursor não está tão integrado quanto eu gostaria. Várias vezes, o Cursor perdeu o controle do código mais recente e me pediu para fornecê-lo. Mas a maneira como ele lida com anexos e copia e cola de código era realmente confusa, tornando difícil para mim entender em qual código a IA tinha visibilidade. Como usuário, minha expectativa é que o Cursor tenha acesso a todo o código do projeto, com a capacidade de inspecionar o código dentro de qualquer arquivo, conforme necessário. Acho que é uma limitação arquitetônica, mas até que isso seja corrigido, ainda há alguma "passagem para frente e para trás" de código que é bastante pesada.
O cursor não está integrado à linha de comando. Para depurar problemas com o aplicativo, o Cursor frequentemente adicionava o registro ao código e, em seguida, me pedia para executar o aplicativo e copiar e colar os registros do console de volta na janela de bate-papo. Para mim, isso levanta a questão: o fluxo de atividade do meu shell de linha de comando não deveria ser conectado à IA como parte de seu contexto?
O cursor não pode ver o aplicativo em si. A única maneira de compartilhar a saída do aplicativo é fazer uma captura de tela e anexá-la ao bate-papo. Mesmo assim, não está claro se os recursos multimodais da IA estão à altura da tarefa de interpretar a imagem e relacioná-la com a solicitação que fiz no bate-papo. Passei várias horas tentando fazer com que ele renderizasse corretamente o padrão de cinco pontos em um dado, e as tentativas de corrigir o problema resultaram principalmente em novos problemas, incluindo pontos desenhados fora da caixa delimitadora. Foi estranho tentar descrever o problema usando a interface de bate-papo, e realmente ajudaria se a exibição do próprio aplicativo (rodando em um emulador na minha máquina) foram canalizados como um fluxo adicional de entrada no contexto da IA.
Às vezes, eu realmente sentia como se estivesse falando com uma pessoa. Às vezes, eu queria orientar a IA para considerar uma determinada implementação, mas como não sei como o framework React funciona nos bastidores, hesitei em propor algo muito específico. Tive a mesma sensação no passado ao interagir com desenvolvedores humanos: com medo de fornecer orientações enganosas, mas também relutante em deixá-los prosseguir sem verificação. Os humanos tendem a se preocupar em ferir meus sentimentos; enquanto a IA tende a presumir que eu sei do que estou falando.
A IA não é boa em design. Você ainda precisa de um habilidoso (humano) designer se você quiser um aplicativo de aparência decente. Como não sou eu, meu aplicativo se parece com isso; é plausivelmente um protótipo funcional, mas não está pronto (Nem de longe) para publicar em uma loja de aplicativos. Fazer pequenos ajustes no espaço em branco era como arrancar dentes, então em algum momento desisti de tentar melhorar os layouts. Talvez se eu soubesse os prompts certos ou a biblioteca de design certa para aplicar, teria tido mais sucesso. Por favor, deixe-me saber se você tem dicas!
Processo do produto
Como antes, comecei com o ChatPRD para gerar o PRD, que então alimentei o Cursor para gerar código.
Em vez de alimentar o Cursor com todo o PRD, decidi dar informações um passo de cada vez. Mas assim que forneci o primeiro parágrafo do PRD, ele começou a escrever o código para o protótipo completo. Esperar!
Mas então eu pensei, você sabe, YOLO, vamos em frente.
Portanto, ainda mais rápido do que no mundo real, o PRD rapidamente ficou fora de sincronia com a implementação como resultado do processo iterativo de criação do aplicativo. O que eu queria era um ChatPRD reverso: uma ferramenta que pudesse gerar o PRD a partir do código, para que houvesse uma descrição legível do que foi implementado. Pontos de bônus para uma maneira de comparar o PRD gerado a partir do código com a especificação original, de modo que o (humano) O PM pode aceitar / rejeitar os diffs.
Mas talvez isso seja apenas um pensamento da velha escola. No futuro, a necessidade de manter a documentação sincronizada com o código será muito reduzida, uma vez que a documentação pode ser gerada automaticamente a partir do código a qualquer momento. Quem precisa de um PRD de qualquer maneira?
Ambiente de codificação
Considerando que optei pelo Dart / Flutter quando construí o aplicativo usando Claude, desta vez o Cursor sugeriu React Native / JavaScript, me guiando (não sem alguns soluços) através do processo de configuração do meu ambiente de desenvolvimento, incluindo a instalação do Node.js e do emulador.
Semelhante à minha experiência anterior, na qual houve um erro de sintaxe porque a estrutura de codificação havia mudado desde que o LLM foi treinado, as instruções de configuração no Cursor faziam referência a arquivos que não existem. Quando perguntei sobre isso, dizia:
Cursor: Ah, parece que você criou um projeto usando uma versão mais recente do Expo que usa a nova estrutura de arquivos com o diretório do aplicativo (esta é a nova estrutura "Expo Router").
Mais tarde, girei minhas rodas por cerca de uma hora tentando corrigir um pequeno problema com o aplicativo, antes que o Cursor finalmente sugerisse que talvez fosse melhor começar do zero. Dizia:
Cursor: Vamos tentar criar um novo projeto com um modelo específico projetado para funcionar com o Expo Router. Podemos então mover nosso código de jogo para o novo projeto.
Como observado acima, embora o Cursor esteja embutido no IDE, ele não tem o contexto dos arquivos em meu projeto ou uma visualização do software instalado em minha máquina, portanto, suas instruções às vezes presumiam configurações que não existiam. Para voltar aos trilhos, precisava que eu executasse comandos no terminal e copiasse e colasse a saída de volta no bate-papo.
Frustrantemente, o Cursor perde o histórico de bate-papo toda vez que eu o reinicio ou cometo o erro de escolher Abrir -> Pasta. Senti falta dos recursos de "biblioteca" de outras ferramentas de IA, para que pudesse voltar às perguntas e respostas anteriores. Minha experiência codificando diretamente em Claude era que eu poderia deixar o projeto e voltar, às vezes dias depois, e continuar de onde parei. Mas com o Cursor eu me peguei começando de novo de vez em quando, às vezes precisando explicar à IA que "já tentamos isso e não funcionou, lembra?"
(No entanto, encontrei um plug-in que me permitia salvar o histórico de bate-papo , desde que me lembrasse de fazê-lo antes de reiniciar o aplicativo.)
Depuração
Embora seja verdade que agora você pode criar aplicativos usando IA sem realmente escrever nenhum código, acho que seria difícil fazê-lo se você nunca escreveu código antes. Por exemplo, para corrigir o problema com a renderização do padrão de pontos no 5, tive que propor uma implementação específica:
Me: O que eu não entendo é: se o 4 for renderizado corretamente (e presumivelmente, usando espaçamento relativo?) - então por que o 5 não pode ser renderizado como o 4, mas com um ponto adicionado bem no centro?
Cursor: Esse é um ponto muito bom! Você está absolutamente certo - se o padrão 4 cria um quadrado perfeito usando o layout flexível, devemos ser capazes de usar a mesma abordagem para o 5, apenas adicionando um ponto centralizado.
Das 15 horas que levei para construir o aplicativo, provavelmente gastei pelo menos 10 depurações: 3 tentando me livrar de todos os bugs de pontuação e lógica, outras 5 para resolver os problemas na renderização do dado e da animação de rolagem e 2 tentando se livrar do som "pop" ao pressionar botões no Android (antes de finalmente desistir disso).
Também perdi pelo menos uma hora porque não sabia que precisava atualizar o aplicativo para que certos tipos de alterações fossem refletidas no emulador. Continuei aplicando alterações de código e, em seguida, relatando ao Cursor que elas "não funcionaram", quando na verdade eu ainda estava executando o código antigo. Tenho certeza de que há um nome para esse modo de falha e suspeito que todo desenvolvedor já passou por isso antes, mesmo sem IA. Quase pude sentir o tom passivo-agressivo da IA quando perguntei por que ela não havia me falado sobre a necessidade de atualizar:
Cursor: Sim, peço desculpas! Eu deveria ter mencionado o recarregamento desde o início. Esta é uma parte crucial do desenvolvimento do React Native/Expo que eu considerava garantida.
Recomendados pelo LinkedIn
Considerações sobre design
Como descobri em minhas primeiras tentativas de criar um aplicativo, a IA não é muito boa em design visual. Como não tenho as habilidades para fornecer arquivos Figma como entrada para a IA, o resultado final foi um aplicativo que se parece mais com um wireframe / protótipo do que com um produto.
Acabei gastando muito tempo dando feedback ao Cursor sobre as animações. Cursor propôs um em que os padrões de pontos giram, mas parecia um girador de carregamento. Também propôs uma versão 3D, mas parecia um pedaço de papel girando em torno de um poste. Optamos por uma abordagem que renderiza uma sequência de padrões de pontos em rápida sucessão, mas mesmo isso exigiu alguma depuração para se livrar da gagueira que acontece quando o mesmo padrão de pontos ocorre duas vezes seguidas.
No geral, pequenos espaçamentos e pequenos problemas de instabilidade exigiram muitas idas e vindas para serem resolvidos. Para entender como isso é na prática, aqui está uma transcrição da interação:
Me: Percebi que a palavra "Pontos:" se move para a esquerda quando o total de pontos se torna de dois dígitos ...
Cursor: Vamos atualizar a exibição de pontos para usar um layout fixo: ...
Me: Há muito espaço entre os "Pontos:" e o valor numérico. Eu prefiro que haja o mínimo de espaço necessário....
Cursor: Vamos ajustar a exibição de pontos para ser mais compacta: ... O texto agora deve ser centralizado sob o dado com espaçamento mínimo.
Me: Os "Pontos: XX" não parecem estar centralizados sob o dado, estão muito à esquerda.
Cursor: Vamos centralizar melhor a exibição de pontos sob o dado: ... Agora "Pontos: XX" deve estar perfeitamente centralizado sob o dado. Deixe-me saber se precisa de mais ajustes!
Me: Ainda não está centralizado, ainda está muito à esquerda.
Cursor: Vamos tentar uma abordagem diferente para centralizar: ... Isso deve centralizar melhor a exibição de pontos sob o dado. Deixe-me saber se precisa de mais ajustes!
Me: Ainda não está centralizado, a palavra "Pontos" está alinhada à esquerda (quase) com o texto "É a sua vez!" e o contorno do dado. Mas o lado direito do número exibido está sob o "t" em "turn", não está muito próximo do lado direito do dado. OBSERVE que é o valor combinado de texto + numérico, por exemplo: "Pontos: 12" que precisa ser centralizado.
Cursor: Eu entendo melhor agora - todo o texto "Pontos: XX" deve ser tratado como uma unidade e centralizado sob o dado. Vamos modificar os estilos: ... Deixe-me saber se isso parece melhor!
Me: Ok, isso parece bom, mas agora a palavra "Pontos" muda quando o número de pontos deixa de ser um único dígito (por exemplo, "7") para dois dígitos (por exemplo, "12"). Gostaria que a palavra "Pontos" não se movesse no visor. Portanto, quero que a entidade combinada seja centralizada, mas a posição da entidade combinada não deve mudar de acordo com quantos dígitos estão sendo exibidos.
Cursor: Ah, precisamos garantir uma largura fixa para a parte numérica, mantendo toda a unidade centralizada. Vamos tentar o seguinte: ... Agora, o texto "Pontos:" deve permanecer fixo no lugar enquanto os números mudam. Deixe-me saber se isso funciona melhor!
Me: Não, a palavra "Pontos" ainda muda para a esquerda quando o total de pontos passa de um dígito para dois dígitos.
Cursor: Vamos tentar uma abordagem diferente com um contêiner de largura fixa para o número: ... Agora, o texto "Pontos:" deve realmente permanecer fixo no lugar. Deixe-me saber se isso funciona!
Me: Sim, parece bom, mas talvez o recipiente seja um pouco largo demais? Ou isso ou há preenchimento adicional em algum lugar, porque a entidade combinada parece estar à esquerda do centro.
Cursor: Vamos ajustar a largura e verificar se há preenchimento extra: .... Isso deve centralizar melhor os "Pontos: XX" combinados sob o dado. Deixe-me saber se precisa de mais ajustes!
Me: Percebi que, quando os dígitos passam de um dígito para um dígito duplo, o segundo dígito parece estar "anexado" à direita. Para fazer a pontuação de um dígito (a pontuação mais comum) parecer mais centralizado, talvez a exibição do valor numérico possa ser "centralizada" no espaço alocado a ela, em vez de alinhada à esquerda?
Cursor: Sim, vamos centralizar o número dentro de seu contêiner: ... Agora, os números de um dígito devem aparecer centralizados em seu espaço, tornando a tela mais equilibrada. Deixe-me saber se isso parece melhor!
Me: Sim, parece melhor, obrigado. Agora, eu gostaria de refinar a transição que acontece depois que eu rolo um...
Tenho certeza de que consertar isso teria sido muito mais rápido apenas corrigindo o código, mas isso exigiria entender JavaScript e React.
Ao todo, tive cerca de 20 dessas pequenas conversas sobre diferentes problemas de ajuste e acabamento no aplicativo, e é por isso que leva 15 horas, não 25 minutos, para criar até mesmo um protótipo simples de aplicativo usando IA.
Conclusão
No geral, minha conclusão de usar o Cursor é que é uma grande melhoria em relação à tentativa de gerar código a partir de uma interface de bate-papo independente, mas ainda há muito atrito no fluxo de trabalho devido a limitações em como a IA obtém seu contexto: ela não tem visibilidade de todos os arquivos do projeto de uma só vez, e ainda há um "humano no circuito" necessário para interpretar a saída visual e copiar e colar informações de outras fontes, incluindo a janela do terminal.
Quando as pessoas descrevem "agentes de codificação de IA", muitas vezes fazem a analogia com um estagiário: inexperiente e propenso a cometer erros, mas entusiasmado em fazer qualquer tarefa que lhe seja atribuída, por mais tediosa que seja.
Mas um estagiário de programação de verdade, encarregado de corrigir o padrão de pontos de um 5 dados, nunca voltaria com um padrão claramente pior e perguntaria "está tudo bem agora?"
Às vezes, eu me sentia como se estivesse preso dentro da sala chinesa de Searle, tendo que passar bilhetes por baixo da porta entre mim e meu estagiário. Como a conversa é tão baixa em largura de banda, o estagiário está perdendo muito contexto, o que torna todo o fluxo de trabalho bastante ineficiente.
No entanto, dado o estado da pesquisa de IA, todos esses parecem problemas de engenharia que serão resolvidos em breve. Imagino que a próxima iteração seja um companheiro de codificação que vê o que vejo, tem acesso a toda a base de código e se integra perfeitamente à máquina local para acesso à linha de comando quando necessário. Parece que a indústria está muito perto de dar o próximo passo, e mal posso esperar para experimentá-lo quando chegar a hora.
Director of Product (AI) driving both strategy & company transformation at Neon (Brazilian Fintech).
8 mThanks, Shane McGrath, that's a great suggestion, and also a new skill I'd need to learn...
Entrepreneur Extraordinaire
8 mI’ve really been enjoying this series of posts. I think they’re screaming for some video content though. Being able to see what you’re talking about and the specific challenges you were having would be way more digestible