Bem-vindo ao meu blog! Celebrando mais esse projeto concluído, venho já deixar meu primeiro post! E não podia ser diferente, vai ser sobre o próprio blog: por que eu fiz ele, quais as intenções e, mais importante, como eu fiz ele. Ao longo das próximas semanas usarei este espaço para falar sobre desafios técnicos, dilemas, aprendizados, problemas, e também alguns tutoriais de como eu fiz cada projeto. Não vou só disponibilizar o código no GitHub, mas farei tutoriais para que você possa entender como e por que eu fiz cada parte da aplicação. E tem também uma seção de comentários onde você vai poder opinar, discordar e deixar sua mensagem. Se eu mudar ou fizer a diferença de uma única pessoa, o objetivo deste blog terá sido atingido!
Meu site devgustavovieira.com estava funcionando perfeitamente bem em React com JavaScript e CSS puro. Você deve estar se perguntando: por que mexer em time que está ganhando? A verdade é que eu tinha alguns objetivos em mente. Primeiro, queria reforçar meus conceitos em Next.js e TypeScript através de um projeto real e significativo. Nada melhor que colocar a mão na massa em algo que você realmente vai usar no dia a dia. Segundo, eu sabia que a performance e o SEO poderiam ser muito melhores com renderização server-side. E terceiro, a estrutura mais rigorosa que o Next.js impõe acabaria me forçando a organizar melhor meus componentes, algo que em React puro às vezes a gente acaba deixando meio bagunçado.
Os resultados superaram minhas expectativas. Consegui alcançar 100 pontos de SEO no Lighthouse, algo que era bem mais complicado de atingir com uma SPA em React puro. A renderização server-side do Next.js realmente faz diferença, e a política mais rigorosa de estruturação de componentes do App Router me obrigou a pensar melhor sobre a arquitetura da aplicação. Foi um upgrade significativo em todos os sentidos.
Durante o planejamento da migração, percebi que seria o momento ideal para adicionar algo que faltava no meu site: uma seção de blog. Há tempos eu queria ter um espaço próprio para compartilhar estudos, conclusões, avanços, curiosidades e novidades sobre tecnologia. Claro que existem várias plataformas prontas para isso, mas ter meu próprio blog, totalmente sob meu controle, sempre foi algo que me atraiu. Poder escrever do jeito que eu quiser, sem limitações de formatação ou regras de plataforma, é libertador.
Comecei desenvolvendo toda a UI seguindo a filosofia mobile-first. Redesenhei a home page, criei a página de listagem de posts com sistema de busca, e desenvolvi a página individual para cada artigo com suporte completo a markdown. Tudo construído com Tailwind CSS desde o início, garantindo que ficasse responsivo em qualquer dispositivo. Foi interessante trabalhar dessa forma porque você realmente pensa primeiro na experiência mobile, que é onde a maioria das pessoas vai acessar.
Para armazenar os posts, avaliei algumas opções e acabei escolhendo o Supabase. Os motivos foram bem práticos: é open source, o que me dá tranquilidade em termos de transparência e apoio da comunidade, o tier gratuito é bem generoso - posso armazenar centenas de posts sem pagar nada, e ele oferece tudo que eu precisava em uma única plataforma. PostgreSQL para o banco de dados, Storage para as imagens, e autenticação já integrada. Não precisei ficar juntando mil ferramentas diferentes para fazer tudo funcionar.
Criei duas tabelas principais: uma para os posts, com todos os campos necessários como título, slug, conteúdo, imagem de capa, data de publicação, e outra para comentários, com nome do autor, email e o comentário em si. Nada muito complexo, mas estruturado de forma a ser escalável no futuro se eu quiser adicionar mais features.
Uma das coisas que mais me preocupava era a segurança. Configurei o Row Level Security do Supabase com políticas bem específicas. Para os posts, apenas usuários admin, no caso eu, podem criar, editar e deletar. Qualquer pessoa pode ler posts publicados, mas rascunhos ficam completamente invisíveis para visitantes. Já para os comentários, decidi que qualquer pessoa pode comentar, só precisa informar nome e email. Os comentários se tornam públicos após a criação, mas usuários não podem editar ou deletar seus próprios comentários. Essa última decisão foi proposital. Prefiro ter que moderar manualmente a dar poder de edição que poderia ser abusado ou gerar confusão. É mais trabalho para mim, mas garante mais controle sobre o que fica publicado.
Construí um dashboard completo onde posso gerenciar tudo. Criar novos posts, editar posts existentes, deletar quando necessário, fazer upload de imagens tanto para capa quanto para inserir no conteúdo, e visualizar separadamente os rascunhos e os posts já publicados. Uma decisão interessante que tomei foi sobre o fluxo de publicação. O botão "Publicar" na página de criação não publica de fato, ele salva como rascunho. Por quê? Para me obrigar a revisar antes de colocar no ar. O fluxo ficou assim: escrevo o post, clico em publicar, o sistema salva como rascunho, depois eu vou na aba de edição, reviso tudo com calma, e só então publico de verdade. Isso garante que nenhum post sai sem uma revisão prévia cuidadosa. Já me salvou de alguns erros de digitação embaraçosos.
Enquanto desenvolvia, me empolguei e resolvi adicionar uma funcionalidade que vi em um tutorial no YouTube: preview ao vivo. Agora, enquanto escrevo, posso clicar em um botão e ver exatamente como o post vai ficar quando publicado. O preview mostra a formatação do markdown, as imagens no tamanho real, o layout responsivo, até o tempo de leitura calculado. Isso economiza muito tempo porque não preciso mais publicar e despublicar só para testar como algo vai aparecer. Foi uma daquelas features que eu não sabia que precisava até implementar, e agora não consigo imaginar trabalhar sem.
Implementei dois sistemas de upload diferentes para as imagens. O primeiro é para a imagem de capa, aquela que aparece nos cards da listagem de posts. É um upload simples e direto no formulário, com preview instantâneo para você ver como ficou. O segundo é mais sofisticado: um sistema para adicionar múltiplas imagens ao longo do conteúdo. Você faz upload, o sistema gera automaticamente o markdown, tem um botão para copiar e facilitar a inserção no texto, e mostra preview de todas as imagens que você enviou. Ficou super prático para adicionar screenshots, diagramas ou fotos aos artigos. Antes de implementar isso, eu estava meio receoso de como seria trabalhar com imagens, mas acabou ficando até mais fácil do que em algumas plataformas prontas que já usei.
Desde o início do projeto, fiz questão de planejar cada etapa antes de começar a codar de verdade. Criei uma lista completa de features e fui riscando uma por uma conforme avançava. Migrei a home page para Next.js, configurei TypeScript, fiz o setup do Supabase, criei as tabelas com RLS, implementei o sistema de autenticação, desenvolvi o dashboard administrativo, construí o CRUD completo de posts, adicionei upload de imagens, implementei a renderização de markdown, criei o sistema de busca, desenvolvi o preview, e otimizei tudo para SEO. Essa abordagem metódica e planejada garantiu que nenhum detalhe ficasse de fora e que todas as peças se encaixassem perfeitamente no final. Não houve aquela sensação de "ah, esqueci de fazer isso" ou "não sei onde encaixar aquilo". Tudo fluiu naturalmente porque estava tudo mapeado desde o começo. Foi meio trabalhoso fazer esse planejamento inicial, mas valeu cada minuto.
Claro que nem tudo foram flores. Enfrentei alguns desafios técnicos interessantes ao longo do caminho. O primeiro foi descobrir que os Server Actions do Next.js têm um limite padrão de 1MB para uploads. Quando tentei subir a primeira imagem, tomei um erro na cara. Tive que aumentar para 10MB no arquivo de configuração para permitir imagens maiores. Outro desafio foi configurar os domínios externos para o componente Image do Next.js. Ele exige que você faça um whitelist de onde as imagens podem vir, por questões de segurança. Tive que adicionar o domínio do Supabase Storage na configuração, caso contrário as imagens simplesmente não carregavam.
E tem as políticas de Row Level Security, que foram mais complexas do que eu imaginava inicialmente. Criar policies que permitissem apenas admins criar posts mas qualquer um comentar, garantindo ao mesmo tempo que rascunhos ficassem invisíveis e comentários ficassem visíveis, exigiu um bom entendimento de SQL e dos conceitos de segurança do Supabase. Passei algumas horas lendo a documentação e testando diferentes abordagens até acertar. Mas quando funcionou, que sensação boa. É aquele tipo de conhecimento que você sabe que vai usar em vários outros projetos no futuro.
A stack que acabei usando foi Next.js 15 com App Router e TypeScript no frontend, Tailwind CSS com Shadcn/ui para os componentes visuais, Supabase para todo o backend, banco de dados, storage e autenticação, React Markdown para renderizar o conteúdo dos posts, e deploy na Vercel. Tudo versionado com Git e GitHub, obviamente. É uma stack moderna, bem documentada, e com uma comunidade ativa. Sempre que tive dúvidas, encontrei respostas rapidamente.
Uma das lições que fica desse projeto é: sempre use Shadcn/ui. Sério, poupa muito tempo depois com responsividade e simplifica tudo absurdamente. Os componentes já vêm prontos, acessíveis e totalmente customizáveis. Você não fica preso a um design system engessado, mas também não precisa reinventar a roda toda vez que precisa de um dropdown ou um modal. É o equilíbrio perfeito entre flexibilidade e produtividade. Gastei muito menos tempo ajustando breakpoints e testando em diferentes tamanhos de tela do que gastaria se tivesse construído tudo do zero ou usado uma biblioteca de componentes mais rígida.
Os resultados foram excelentes. A performance está ótima, com score perfeito de SEO no Lighthouse, algo que me deixou bem satisfeito. O server-side rendering garante carregamento rápido das páginas, e as imagens são otimizadas automaticamente pelo Next.js. No código, a segurança de tipos do TypeScript cobre toda a aplicação, os componentes ficaram reutilizáveis e bem organizados, e consegui manter uma separação clara entre Server e Client Components. A experiência de uso também ficou muito boa. O sistema é intuitivo para escrever posts, o preview facilita demais na hora de criar conteúdo, e o dashboard está limpo e funcional. Escrever este post que você está lendo agora foi uma experiência bem mais agradável do que seria em plataformas de terceiros.
Já tenho uma lista de features que quero adicionar no futuro. Penso em implementar um sistema de tags e categorias, adicionar sugestões de posts relacionados, criar um contador de visualizações, botões de compartilhamento social, gerar um RSS feed, adicionar dark mode, e melhorar o syntax highlighting para blocos de código. Mas essas são melhorias para o futuro, por enquanto, o sistema está completo e funcional para o que eu preciso. Prefiro ir adicionando aos poucos, conforme sinto necessidade, do que tentar fazer tudo de uma vez e me perder no meio do caminho.
Migrar o site para Next.js e construir um sistema de blog do zero foi um projeto desafiador, mas extremamente recompensador. Aprendi muito sobre arquitetura de aplicações modernas, segurança com Row Level Security, otimização de performance e SEO na prática. E o melhor de tudo: agora tenho uma plataforma totalmente sob meu controle para compartilhar conhecimento e experiências. Não dependo de algoritmos de recomendação, não tenho que seguir regras de formatação de outras plataformas, e posso experimentar à vontade com o design e as funcionalidades.
Se você está pensando em criar seu próprio blog, realmente recomendo essa stack. A experiência de desenvolvimento é excelente, você tem controle total sobre tudo, e o resultado final é um blog rápido, seguro e fácil de manter. Sim, dá mais trabalho do que usar uma plataforma pronta, mas a liberdade que você ganha compensa. E o aprendizado que vem junto é valiosíssimo. Este é o primeiro post deste blog, e muitos outros virão. Vamos juntos nessa jornada de aprendizado e descobertas no mundo do desenvolvimento web!