
Contextualização: entendendo a aplicação
Antes de começar a explicar mais a fundo os motivos que me fizeram evoluir a aplicação em si, vamos tentar entender o que é a aplicação.
Motivação
A Droppe nada mais é que uma aplicação com o foco no compartilhamento de arquivos sem a necessidade de login ou pareamento com nosso dispositivo.
Vocês podem estar se perguntando, mas não é só eu conectar o WhatsApp ou minha conta do Google no navegador? Ou, é só eu mandar por Bluetooth, não? Bom, você pode usar estas alternativas, mas convenhamos, não é tão prático assim.
Fora que em muitos lugares, como em empresas ou ambientes controlados, não permitem pareamento com dispositivos externos, ou transferências de arquivos por USB, pendrive etc.
Funcionamento
Como já entendemos o porquê da aplicação, vamos ao funcionamento. Basicamente a aplicação tem duas entidades principais, a Sessão e Arquivos.
- Sessões são criadas e acessadas por qualquer usuário e possuem a duração de aproximadamente 15 minutos.
- Arquivos são vinculados a Sessões . Ou seja, uma Sessão pode ter muitos arquivos vinculados e, se uma Sessão deixar de existir, Arquivos relacionados também deixarão.
As Sessões possuem um nome definido pelo usuário e um código de 6 dígitos gerado aleatoriamente pelo sistema. Com esses dados em mãos, elas podem ser acessadas por outros usuários ou dispositivos.
Código e Tecnologias
Indo para uma parte mais técnica, vou descrever mais sobre o código e as tecnologias usadas inicialmente.
O código seguia um padrão amador MVC, pois eu não tinha domínio na época. Era tudo em um único repositório.
Foi utilizado JavaScript puro, express, mongoose e handlebars. O sistema funcionou, mas era muito frágil. É muito difícil de você manter um projeto onde o frontend está acoplado com o backend.
Por não entender muito bem, foi o que eu fiz. Utilizei o handlebars para renderização de páginas estáticas no meu servidor, estas páginas estavam em uma pasta específica, /views, mas suas estilizações e códigos JavaScript estavam na pasta /public, isso quando não havia um script jogado no meio da página.
Ao mesmo tempo em que havia uma certa organização amadora tinha suas bagunças.

Acima vocês podem ver a estrutura de pastas da primeira versão, caso queiram ver o projeto por um todo, vou deixar o link do repositório aqui. O nome do repositório nem se chamava Droppe ainda.
A Revolução: motivações para refatoração
Houveram alguns motivos pelos quais eu decidi reformular a aplicação.
- Aprendizado: o principal motivo sem dúvidas foi o aprendizado. Eu estava com o desejo de aprender algo novo, mais especificamente o TypeScript. Comecei a estudar e pesquisar mais, então decidi aplicar em um projeto real.
- Experiência: queria ter a experiência de projetar e estruturar melhor um projeto com qualidade e novas tecnologias.
- Realização: por mais que o projeto já estivesse pronto, eu sentia que não era o suficiente. Eu via melhorias, talvez isso me deixasse insatisfeito com o resultado.
Concepção e Modelagem
Antes de colocar a mão no código, eu precisava definir melhor os requisitos e o escopo do projeto. Portanto, decidi aplicar alguns conhecimentos que eu havia aprendido na faculdade, como alguns diagramas da UML, o de Casos de Uso e o Diagrama de Classes.
Diagrama de Casos de Uso:

Diagrama de Classes:

Decidi que o projeto seria desacoplado, onde eu separaria o repositório frontend do backend. Um projeto Multi-Repo.
As tecnologias usadas foram:
- Frontend:
- TypeScript
- Next.js
- TailwindCss
- Amazon S3
- ZOD
- Backend
- TypeScript
- Prisma
- Express
- MongoDB
- Amazon S3
Como o meu foco principal era o aprendizado, eu queria usar tecnologias que eu não tinha muita familiaridade e que fossem agregar na minha carreira e nos meus conhecimentos.
Anteriormente eu havia usado o mongoose como ORM, desta vez eu utilizei o Prisma, por ter uma integração melhor com o TypeScript.
Observações: comecei desenvolvendo o frontend primeiro, e eu não sou tão experiente assim com Next.js, mas vi que poderia criar a aplicação sem o backend. Tentei, algumas partes funcionaram, mas devido a algumas limitações do Next, não foi possível dar continuidade.
Codificação
Para apresentar melhor como foi a etapa de desenvolvimento, vou separar em três etapas: frontend, backend e integração.
Etapa 1: frontend
Eu já tinha o design pronto, o que eu fiz foi componentizar o projeto antigo para usar com o Next.js e criar as páginas.
Não posso esquecer também que tive que 'traduzir' o CSS da primeira versão para o TailwindCSS.
Enquanto desenvolvia, percebi que estava passando mais de uma vez a mesma prop, aconteceu o famoso Prop Drilling, então arrumei criando um Context API.
E criei um hook personalizado para o timer presente na aplicação.
Etapa 2: backend
Esta também não foi uma parte tão complicada assim.
Desde a primeira versão eu havia aprendido muitas coisas em alguns cursos na Alura, então coloquei em prática.
Usei conceitos de Orientação a Objetos para a criação dos controllers e services, como herança e polimorfismo. E centralizei as rotas em um arquivo único para exportação.
Etapa 3: integração
Não sofri tanto assim, mas como eu queria me desafiar, utilizei uma biblioteca que eu já tinha usado em um curso, mas nunca cheguei a me aprofundar tanto assim, o Axios.
Assim como nossas aplicações, estamos sempre em constante evolução. Quando conheci o Axios não vi a hora de aplicá-lo em um projeto prático, então não perdi a oportunidade.
Estruturei o front com uma pasta /services, onde eu organizei os arquivos para as requisições no backend. E no back configurei o CORS, este negócio importante e chato.
No bucket da S3 configurei o CORS também, para performance e redução de custos, o meu servidor devolve uma URL personalizada para upload direto na S3, assim não é consumido muita banda e processamento.
Bugs e Desafios
Como todos nós sabemos, é quase inevitável desenvolver uma aplicação sem que ocorra ao menos um problema.
Tive problema na fase de criação no frontend e no backend, na fase de integração e na hora do deploy.
No front foram erros pontuais, como usar ou importar client components em server components, e vice-e-versa.
E um outro problema foi em relação ao useRouter pois para que criam duas funções com o mesmo nome? Quando usava o auto-import do VS Code, importava errado. Como eu fiquei um tempo tentando resolver da primeira vez, já fiquei ligado quando importava novamente.
Agora no backend, sofri com o Prisma.
Na documentação do Prisma, diz que até o momento o MongoDB só funciona com o Prisma na versão 6.19. E depois que eu já tinha instalado tudo que eu fui ler está parte da documentação. Mas acontece.
Agora o que mais me estressou foi quando fui fazer o deploy do backend. Sorte que foi fácil de resolver.
Eu hospedei na Vercel, mas estava dando erro. Quando fui ver os logs, as importações estavam erradas.
Quando estava rodando em desenvolvimento, estava funcionando, quando fazia o build não. Faltava um .js no final das importações.
Arrumei tudo, fui averiguar, e estava dando erro de importação de novo. Eu havia esquecido de ajustar uma única importação.
Um problema que eu já ia esquecendo, foi em relação ao job de autolimpeza. A Vercel roda nossa api como serverless, ou seja, ela só acorda quando chamamos ela. Uma função embutida no código que foi programada não ia funcionar.
Pesquisei e descobri que a Vercel nos fornece a opção de criarmos nosso job, mas ele não executa uma função, mas acessa uma rota que pode chamar uma função. O problema é que ela só executaria uma vez ao dia, na versão gratuita - a que eu uso.
Encontrei uma opção alternativa, um site que permite que cadastremos nossos cron-jobs com o tempo que quisermos. Então criei uma rota que executa está função, que só pode ser acessada com autorização de um token e cadastrei neste site.
Resultados
Após todos esses processos descritos anteriormente. Tive como resultado o que eu mais almejava, o conhecimento e a experiência.
Pude aprender e ver na prática os benefícios do uso do TypeScript. Apliquei meus conhecimentos em um projeto prático, como um pouco de Orientação a Objetos, e diagramas UML.
Como artefato principal, podemos dizer assim, consegui ter uma melhora evidente na performance e experiência do usuário em relação à aplicação anterior. A navegação está muito mais fluída e reativa. O código está muito bem estruturado, organizado, sendo mais fácil de manter.
Repositórios:
Aplicação: [Droppe]
Conclusão
Com este longo processo, eu posso afirmar que eu estou aprendendo TypeScript, e que eu sei da importância de organização, planejamento e documentação de um projeto.
Escrevi este artigo como uma forma de documentar meu processo de aprendizado de reformulação da Droppe. Não sei se alguém vai ler, mas... Se alguém leu até o final, reage com o emoji de confetes.