Voltar para artigos
Arquitetura··14 min de leitura

Construindo o Monney Works — do mock ao deploy em ~4 horas

A arquitetura por trás do meu blog pessoal

Este é o primeiro artigo do Monney Works. Ele documenta por que eu quis construir o blog e como ele saiu da ideia pra estar no ar em monneyworks.com em menos de 4 horas.

Por que eu quis construir isso

Eu comecei a acompanhar o Fábio Akita faz pouco tempo. Em março, ele fechou um ciclo que chamou de "37 dias de imersão em vibe coding" — 37 dias construindo projeto atrás de projeto com o Claude Code e documentando cada um. No fim, publicou um artigo e um vídeo fazendo o balanço do período: 653 commits, 144 mil linhas de código, 8 projetos em produção, entre eles a refundação do blog dele próprio, que acaba de completar 20 anos no ar.

O que me chamou a atenção no vídeo foi a quantidade e a qualidade dos projetos que ele entregou em tão pouco tempo. Isso me mostrou, de forma muito concreta, a grande oportunidade que a gente tem hoje na arquitetura e no desenvolvimento de software.

Eu tenho muita ideia. MVPs de aplicação, estratégias de negócio digital, a metodologia proprietária que chamo de Arquitetura de Escala, estudos sobre o que me desperta curiosidade. Sempre tive. A diferença é que, até pouco tempo atrás, tirar uma ideia do papel exigia um investimento de semanas em setup manual: configurar tooling, decidir stack, escrever boilerplate, lutar com typecheck, lidar com bibliotecas incompatíveis, migrações, build pipeline. O impeditivo nunca foi "não saber". Foi "não ter tempo de passar por tudo isso de novo."

As LLMs mudaram esse ponto. Elas não removeram a obrigação de entender o que você está construindo — eu continuo exigindo arquitetura pensada, tipos estritos, testes que rodam antes do código, i18n de verdade em vez de gambiarra. O que mudou é que o ciclo entre ter a ideia e ter o protótipo rodando encolheu de semanas pra horas. Hoje, sabendo o que você quer, você consegue construir.

O que me faltava, com as ideias que eu tinha acumuladas, era o lugar pra colocar tudo isso. Decidi que esse lugar ia ser o Monney Works — um ativo bilíngue, indexável pelo Google no idioma nativo do leitor, que vai funcionar como matéria-prima pra todos os outros formatos de comunicação que eu produzo.

Como começou

Antes de escrever uma linha de código, usei o V0 da Vercel pra prototipar o visual. Eu sabia o que queria — barra de busca centralizada com efeito de vidro líquido (inspiração que veio deste vídeo), preto e branco, lista de artigos ocupando dois terços da tela com uma sidebar de tópicos à direita, tudo minimalista. Mas antes de investir energia em implementação real, quis ver a ideia funcionando no navegador.

O rascunho inicial do blog no V0, ainda com o nome de trabalho "mindlog" que eu descartei depois
O rascunho inicial do blog no V0, ainda com o nome de trabalho "mindlog" que eu descartei depois

Quando o rascunho ficou próximo do que eu tinha na cabeça, era hora de sair do protótipo e desenvolver do jeito certo. Baixei o código gerado, abri no VS Code com o Claude Code, e o projeto começou de verdade.

O código do V0 era mais ou menos o que eu esperava de um mock: dados mockados em lib/mock-data.ts, ignoreBuildErrors: true no next.config (ou seja, erros de typecheck sendo escondidos em vez de corrigidos), i18n implementado como um Context com useState no lugar de uma solução de internacionalização real, zero testes, nenhuma separação entre domínio e apresentação. A estrutura servia pra navegar e validar UX, e é exatamente pra isso que um mock serve. Só que não ia pra produção como base de um projeto meu.

Então apliquei as diretrizes que eu já uso em projeto real: o meu CLAUDE.md, um arquivo onde vivem as regras de arquitetura, as convenções do projeto, os princípios de Domain-Driven Design, as regras de TDD estrito, a exigência de fases pequenas (no máximo cinco arquivos por vez) com verificação de typecheck, lint e testes antes de avançar, e a política de commits granulares. Desenhei um plano junto com o Claude Code, ajustei até ficar do jeito que eu queria, e comecei a implementação.

O que eu queria do blog

Antes de escrever qualquer linha, o importante é a ideia. A minha era clara:

  • Minimalista e elegante. Preto e branco, sem firula. Foco no texto, nos componentes modernos, no vidro translúcido da barra de busca fixa em todas as páginas.

  • Markdown-first, com o estudo virando artigo. O fluxo de base é o seguinte: sempre que estou desenvolvendo um projeto, aprofundando uma metodologia, ou estudando um assunto que me interessa, eu crio um arquivo markdown de rascunho. Jogo tudo lá — o que eu sei, o que eu quero aprender, os ângulos que quero aprofundar. Depois peço ao Claude pra montar um plano de estudo conectando o que escrevi a áreas do conhecimento que me interessam. Um exemplo concreto: esses dias revi o primeiro Homem-Aranha, o de 2002 com o Tobey Maguire, pela primeira vez em uns 15 anos. Uma cena em particular me chamou a atenção — o Willem Dafoe interpretando o Norman Osborne e o Duende Verde dialogando no espelho, dois personagens opostos contracenando sem corte. Aquilo me fez querer analisar a cena cruzando PNL, o arquétipo da sombra em Jung, e a ideia de que o Duende Verde se apresentando é o Norman confrontando seu lado mais sombrio e perverso. Virou material de estudo, e vai render um artigo aqui em breve. A ideia é essa: aproveitar o que aprendo em projetos pessoais e profissionais, e compartilhar do meu jeito. O resto do pipeline — gerar slug, traduzir pro outro idioma, organizar a pasta cronológica, achar artigos relacionados — é automatizado por uma skill no Claude Code que processa o rascunho.

  • Bilíngue desde o primeiro dia. pt-BR e inglês, URLs localizadas (/pt-BR/... e /en/...), cada artigo vivendo como dois arquivos (pt-BR.md + en.md) no mesmo diretório. Espanhol e português de Portugal vêm depois, mas a arquitetura já precisa aguentar.

  • Git-based admin. Sou o único administrador. Mas "acesso" aqui não é login em painel — é git commit + git push. A Vercel detecta o push, rebuilda o site, e o conteúdo novo está no ar.

  • Código no GitHub. Versionado, rastreável, passível de ser aberto no futuro. Mais importante: o blog é onde eu aplico, em projeto próprio, os mesmos padrões que eu uso profissionalmente — DDD, TDD, tipos estritos.

Por que não seguir com o código do V0 como está

O V0 é ótimo pra prototipar e não foi feito pra ser a base do que vai pra produção. A arquitetura do mock assume coisas que simplesmente não servem num projeto que precisa durar.

Quando eu penso em "projeto real", não estou falando só de rodar numa máquina local. É sobre código que precisa ser deployável, seguro, observável, com possibilidade de escalar. Que pode começar pequeno, mas precisa aguentar crescimento. Principalmente se o projeto vai ter usuários reais — e mais ainda se lida com dados de terceiros. Aí entram aspectos inegociáveis: autenticação, criptografia de dados em trânsito e em repouso, separação clara entre camadas, testes cobrindo o comportamento crítico, auditabilidade.

A ideia não é arquitetar um monstro já no começo. É raciocinar, desde a primeira decisão, sobre o que faz sentido e o que não faz pra que o projeto possa evoluir sem virar retrabalho. Decisões arquiteturais tomadas cedo ficam cravadas — mudá-las depois custa muito mais caro do que pagar o custo agora.

O mock do V0 falhava nesse filtro em quatro pontos:

  • Dados mockados em vez de uma camada real de persistência. O clássico "é só trocar depois" costuma adiar uma migração que, na prática, nunca acontece.
  • ignoreBuildErrors: true no build. Isso significa que erros de tipagem eram silenciados em vez de corrigidos. E tipagem estática só tem valor quando um erro de tipagem quebra o build.
  • Context + useState como i18n. Funciona pra alternar strings em runtime, mas não suporta roteamento localizado (/pt-BR/..., /en/...) nem SEO multilíngue de verdade.
  • Zero testes. Nenhuma garantia de que a próxima mudança não quebra o que já funcionava.

Cada um desses pontos, se passasse pro projeto principal, viraria dívida técnica em questão de dias. Prefiro investir o tempo certo no começo do que pagar a taxa composta depois.

Como a aplicação está estruturada

A aplicação foi construída em quatro camadas separadas, seguindo os princípios de Clean Architecture e Domain-Driven Design. Cada camada tem uma responsabilidade clara e depende apenas de contratos definidos por camadas mais internas.

  • Domínio — o núcleo. Representa os conceitos do negócio (artigo, tag, categoria, data de publicação, tempo de leitura) sem saber nada sobre o resto do mundo. Não depende de Next.js, não depende de arquivo, não depende de banco.
  • Aplicação — os casos de uso. Orquestram o domínio e consomem os contratos (listar artigos, buscar por slug, encontrar relacionados, listar tópicos).
  • Infraestrutura — a ponte com o mundo externo. Implementa os contratos definidos pelo domínio. Neste blog, lê os arquivos markdown do filesystem e traduz pra objetos do domínio.
  • Apresentação — a camada do Next.js. Páginas do App Router, componentes React, DTOs que cruzam a fronteira servidor → cliente.

Essa separação mantém o que é regra de negócio longe do que é detalhe de implementação. Se amanhã os artigos saírem do filesystem e forem pra um banco, só a camada de infraestrutura precisa mudar — domínio, casos de uso e páginas continuam intactos.

O desenvolvimento foi executado em fases pequenas, cada uma com no máximo cinco arquivos, commit granular, e verificação automatizada (npx tsc --noEmit pra typecheck, npm test pros testes, npm run lint pra análise estática) antes de avançar. O histórico de 32 commits no repositório mostra essa cadência — nenhum commit representa mais do que uma unidade de trabalho encerrada e verificada.

Como reconstruí, fase por fase

Fase 0 — Bootstrap. Configuração do projeto: Next.js 16, React 19, TypeScript em modo estrito com noUncheckedIndexedAccess (checagem de acesso a arrays), noUnusedLocals e noUnusedParameters ligados. Tailwind v4. ESLint com flat config. Prettier. Vitest pros testes. Sem ignoreBuildErrors — erros de typecheck falham o build.

Fases 1 e 2 — Domínio. O Article é o aggregate root — em DDD, o ponto de entrada do agregado, a entidade que garante que todas as regras de negócio relacionadas a um artigo sejam respeitadas. É identificado pelo seu Slug.

Ao redor dele vivem os value objects: Slug, Tag, Category, PublishDate, Locale, LocalizedText, ReadingTime. Value object é um conceito do DDD pra representar valores sem identidade própria — uma data de publicação é igual a outra se forem o mesmo dia, diferente de dois artigos que, mesmo com o mesmo título, são entidades distintas.

Cada value object tem construtor privado e uma factory estática que valida os dados antes de permitir a criação. Isso significa que um Article em memória nunca está em estado inválido — não existe artigo com tags vazias, categoria desconhecida ou data malformada. Se a construção passa, o objeto é confiável dali pra frente.

Os testes vêm antes da implementação. O ciclo é o clássico red-green-refactor: primeiro escreve-se um teste que falha (red), depois o mínimo de código pra fazer passar (green), depois refatora-se mantendo os testes verdes (refactor). Isso inverte a ordem natural do desenvolvimento — o código nasce atendendo um comportamento esperado, não o contrário — e como efeito colateral produz cobertura total do que foi implementado.

Os contratos ArticleRepository e ArticleIndex vivem no domínio apenas como tipos, sem implementação. A camada de domínio não sabe se os artigos vêm de arquivos markdown, de um Postgres ou de uma API remota. Quem escolhe é a infraestrutura, e essa escolha pode mudar no futuro sem que o domínio precise saber disso.

Fase 3 — Infraestrutura de markdown. Aqui entra o conceito de anti-corruption layer (ACL), uma camada de proteção entre o domínio e o mundo externo. Dados que vêm de fora (neste caso, o YAML no cabeçalho dos arquivos markdown) precisam ser traduzidos e validados antes de virar objetos do domínio. Se algum dado estiver fora do padrão esperado, a ACL rejeita ali na borda, antes de o problema chegar nas camadas internas.

No blog, essa camada é o frontmatter-parser.ts. Ele pega um par de arquivos (pt-BR.md + en.md), usa a biblioteca gray-matter (um parser que separa o cabeçalho YAML do conteúdo markdown) pra extrair os metadados, e traduz cada campo pro value object correspondente. Se a categoria vier fora do enum aceito, a tag vier vazia, a data vier malformada, o parser falha imediatamente com uma mensagem clara, e nenhum objeto inválido chega no domínio.

O markdown-article-repository.ts implementa o contrato definido pelo domínio. Ele varre content/articles/YYYY/MM/{slug}/, lê os dois arquivos em paralelo com Promise.all, e devolve os artigos prontos. Quando algo dá errado, o erro sobe carregando o caminho do diretório que falhou, o que facilita descobrir qual arquivo quebrou o build.

Fase 4 — Casos de uso. Cinco use cases curtos: listArticles, getArticleBySlug, searchArticles, findRelatedArticles, listTopics. Todos recebem o repositório por injeção de dependência — ou seja, a camada de aplicação não instancia nada, apenas pede o que precisa. Cada teste usa um fake em memória em vez de tocar o filesystem, e a suite inteira, com 145 testes, roda em menos de dois segundos.

Fase 5 — i18n. A biblioteca next-intl cuida do roteamento localizado (/pt-BR/... e /en/...). A lista de locales suportados vem direto do domínio — o mesmo Locale que valida artigos é o que configura o routing. Assim, não existe a possibilidade de o roteamento estar desalinhado do resto da aplicação.

Fase 6 — Layout. Scaffold do Next App Router com provider de tradução, fontes Geist e Unbounded, header e footer. O primeiro next build gerou as rotas estáticas.

Fase 7 — Home funcional. Os componentes visuais do V0 foram portados em cima do domínio real. Um composition root (src/infrastructure/container.ts) instancia o repositório com o caminho raiz dos artigos e expõe os casos de uso prontos pra consumo. Um DTO (ArticleView) achata os objetos do domínio na fronteira servidor → cliente — classes do domínio não cruzam essa fronteira, apenas dados primitivos serializáveis.

Fases 8 a 13 — O resto. Página individual de artigo renderizando markdown via react-markdown + remark-gfm (extensão que habilita tabelas, listas de tarefas e outras conveniências do GitHub Flavored Markdown) e um plugin próprio (remark-highlight) que transforma ==texto== num <mark> com a cor da marca. Tags ganharam slug URL-safe (Clean Architectureclean-architecture) e viraram páginas próprias em /topics/{tag}. Sitemap e robots.txt com hreflang — as meta tags que avisam ao Google que as URLs em pt-BR e em inglês são versões da mesma página em idiomas diferentes, pra que nenhuma seja penalizada como conteúdo duplicado. Barra de busca promovida do componente da home pro layout global, aparecendo fixa em todas as páginas. Fundo animado de partículas em canvas reagindo ao cursor. GlassSurface com filtro SVG de displacement pra dar o efeito de vidro líquido real nos cards e na barra de busca. Confetti Lottie que dispara só na página deste artigo — a celebração é específica pro primeiro post. Metadata OpenGraph/Twitter por locale, metadataBase apontando pro domínio final. Deploy na Vercel. Domínio monneyworks.com apontado.

Na prática, isso significa que a página deste artigo é construída passando pelo domínio, pelo parser, pelo repositório, pelo caso de uso, pela página do Next e pelos componentes React — cada camada fazendo a sua parte.

O workflow de publicação que eu queria

O que me fez querer construir isso desse jeito foi a visão do fluxo de publicação. Funciona assim:

  1. Tenho uma ideia. Abro um arquivo em content/_drafts/ (um diretório git-ignored, privado, dentro do próprio repo). Jogo dentro as notas soltas, um rascunho de projeto, trechos de um MVP que estou desenhando — o que for.
  2. Quando está pronto, rodo /publish-article content/_drafts/foo.md no Claude Code.
  3. A skill lê o rascunho, sugere slug, category e tags, traduz para o outro idioma preservando code blocks e termos técnicos, calcula o tempo de leitura, encontra artigos relacionados por overlap de tags, e me mostra um preview completo.
  4. Eu aprovo. A skill move os arquivos para content/articles/2026/04/{slug}/pt-BR.md + en.md, roda npm run typecheck e npm test, e pergunta se quero commitar.
  5. git push. Vercel rebuilda. Artigo no ar.

Meu trabalho é o que eu sei fazer: ter ideias e rascunhá-las. A automação cuida do resto.

O que vai passar por aqui

Eu tenho muita ideia. MVPs de aplicação — o Split Reel, por exemplo, um projeto que sincroniza a gravação de tela do computador com a câmera do celular e exporta em formato de reel vertical, câmera embaixo, tela em cima. MVPs a partir de vagas de emprego reais — pego os requisitos técnicos de uma vaga concreta, arquiteto a aplicação completa, e deixo rodando pra quem quiser testar. Estratégia de negócio baseada na metodologia proprietária que venho desenvolvendo e chamo de Arquitetura de Escala — a estrutura de comunicação, oferta, captação e fidelização que eu uso pra estruturar negócios digitais do zero. Estudos sobre o que me desperta curiosidade — arquitetura, filosofia, persuasão, liderança, marketing, cinema.

O blog é o ativo central. Cada artigo que eu publicar aqui é matéria-prima pra dezenas de outros formatos de comunicação — recortes pra rede social, roteiro de vídeo, ponto de partida pra apresentação, argumento de venda. Uma peça densa, bem pensada, documentada, em dois idiomas indexáveis pelo Google no idioma nativo do leitor, se transforma em tudo o mais com uma fração do trabalho. Eu escrevo uma vez, e o resto é propagação.

Uma coisa que quero deixar clara: eu não tenho ambição de ser escritor. Eu tenho ambição de ter o que eu penso registrado. A ideia de cada artigo vem de mim, a curadoria vem de mim, a decisão do que publicar é minha. Se algo chegou ao ar neste domínio, é porque eu investiguei, aprendi, e concordo. A LLM é a ferramenta que me ajuda a transformar a ideia em texto — não a fonte do que eu penso.

Com o tempo isso vira um portfólio: projetos documentados, métodos explicados, decisões justificadas, ideias refinadas em público. É isso que eu quero construir.

Primeiro de muitos

Entre o momento em que baixei o código do V0 e o momento em que este artigo foi publicado, passaram menos de 4 horas. A coisa toda existe — monneyworks.com resolve, o SSG serve as páginas em pt-BR e em inglês, o sitemap lista cada artigo com alternates hreflang, e, se você está lendo isto, o confetti explodiu quando a página carregou.

Este é o primeiro artigo de muitos.

O próximo vem com o próximo projeto, ou com a próxima ideia maluca que minha cabeça inventar.