<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Figueirego Blog – Next.js</title><link>https://figueirego.com/pt/blog/tags/next.js/</link><description>Publicações recentes em Next.js no Figueirego Blog.</description><generator>Hugo -- gohugo.io</generator><language>pt-BR</language><lastBuildDate>Mon, 19 Oct 2026 04:33:15 -0300</lastBuildDate><atom:link href="https://figueirego.com/pt/blog/tags/next.js/index.xml" rel="self" type="application/rss+xml"/><item><title>Construindo meu blog, parte 3: do Markdown à publicação</title><link>https://figueirego.com/pt/blog/posts/construindo-o-blog-03-publicacao/</link><pubDate>Mon, 19 Oct 2026 04:15:50 -0300</pubDate><guid>https://figueirego.com/pt/blog/posts/construindo-o-blog-03-publicacao/</guid><description>&lt;p&gt;&lt;img src="https://figueirego-blog-images.s3.us-east-1.amazonaws.com/images/2026/10/building-blog-publishing/publicacao.webp" alt="Oficina de encadernação com prensa, folhas organizadas e cadernos prontos sobre a bancada."&gt;&lt;/p&gt;&lt;p&gt;Salvar um artigo no editor não significa que ele está publicado. O texto ainda precisa ser revisado, gerar uma página, passar pelas verificações e chegar à hospedagem. Depois disso, preciso abrir o endereço público e conferir o que o leitor recebeu.&lt;/p&gt;
&lt;p&gt;Essa distinção ficou importante ao integrar blog e portfólio. Na primeira versão, o blog tinha um fluxo separado. Hoje, as duas partes saem do mesmo repositório e são entregues pela aplicação Next.js na Hostinger. O subdomínio antigo deixou de ser o destino.&lt;/p&gt;
&lt;h2 data-hextra-search-id="o-artigo-começa-com-texto-e-metadados"&gt;O artigo começa com texto e metadados&lt;span class="hx:absolute hx:-mt-20" id="o-artigo-começa-com-texto-e-metadados"&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Escrevo em Markdown. Antes do corpo, um bloco de dados chamado &lt;em&gt;front matter&lt;/em&gt; informa como o artigo deve ser apresentado. Este é um exemplo reduzido, não um arquivo pronto para publicar:&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Como organizei meu blog&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ld"&gt;2026-10-19T09:00:00&lt;/span&gt;&lt;span class="m"&gt;-03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Matheus Figueirêdo&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;translationKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;how-i-organized-my-blog&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;As decisões para organizar conteúdo, navegação e publicação.&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Hugo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;publicação&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A data precisa corresponder à publicação real. &lt;code&gt;draft: true&lt;/code&gt; mantém o texto fora do build público. Na tradução, o título, a descrição, os temas e o corpo mudam; a &lt;code&gt;translationKey&lt;/code&gt; continua igual.&lt;/p&gt;
&lt;p&gt;Uma capa pode ser acrescentada depois. Quando existe, precisa de URL, descrição alternativa e dimensões correspondentes ao arquivo. O artigo deve continuar legível sem depender da imagem para informar seu assunto.&lt;/p&gt;
&lt;h2 data-hextra-search-id="duas-prévias-para-perguntas-diferentes"&gt;Duas prévias para perguntas diferentes&lt;span class="hx:absolute hx:-mt-20" id="duas-prévias-para-perguntas-diferentes"&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Para revisar apenas os textos, posso usar o servidor do Hugo. Estes comandos partem da raiz do repositório e pressupõem Hugo extended na versão fixada pelo projeto:&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo server --buildDrafts --bind 127.0.0.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A opção inclui rascunhos na prévia local. É útil para conferir texto, sumário e tradução. Para avaliar a integração com o portfólio, uso o projeto completo, em outro terminal:&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; client
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm ci
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm run dev&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Esse caminho pressupõe Node.js 24.12.0 ou superior e Hugo extended 0.167.0 no ambiente. O script de desenvolvimento monta o blog no início. Depois de editar Markdown, preciso reconstruir essa parte com &lt;code&gt;node scripts/build-blog.mjs --preview&lt;/code&gt; e recarregar a página. Ele não substitui o acompanhamento de arquivos do servidor Hugo dedicado, e o build integrado normal continua excluindo rascunhos.&lt;/p&gt;
&lt;p&gt;Os comandos dependem dos auxiliares deste repositório privado. Para outro projeto, a ideia reproduzível é manter uma prévia rápida do conteúdo e outra que exercite a integração completa.&lt;/p&gt;
&lt;h2 data-hextra-search-id="a-versão-que-passa-pelos-testes-é-a-que-segue-adiante"&gt;A versão que passa pelos testes é a que segue adiante&lt;span class="hx:absolute hx:-mt-20" id="a-versão-que-passa-pelos-testes-é-a-que-segue-adiante"&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;O fluxo atual é:&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;arquivos revisados → dev → main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; testes e build integrado
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SHA aprovado → production
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Hostinger
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; conferência do site público&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;SHA é o identificador de um commit. Usá-lo na promoção permite relacionar a versão testada à versão enviada para publicação. A CI não deve aprovar um commit e promover silenciosamente outro que chegou depois.&lt;/p&gt;
&lt;p&gt;O comando central de verificação, executado em &lt;code&gt;client/&lt;/code&gt;, é:&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;node scripts/verify-release.mjs --production&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Ele reúne checagem de tipos, lint, formatação, testes, build Next.js com Hugo e verificação dos arquivos gerados. Para conhecer as etapas sem executá-las, uso &lt;code&gt;--dry-run&lt;/code&gt;. Nenhuma dessas opções, sozinha, envia código ao GitHub.&lt;/p&gt;
&lt;p&gt;Depois dos checks da &lt;code&gt;main&lt;/code&gt;, a automação promove o commit aprovado para &lt;code&gt;production&lt;/code&gt;. A Hostinger acompanha essa branch. Se a &lt;code&gt;main&lt;/code&gt; avançou durante a execução, a versão nova precisa passar por sua própria verificação. A promoção não deve atropelar o histórico com um envio forçado.&lt;/p&gt;
&lt;figure class="reader-figure reader-figure-wide"&gt;
&lt;div class="post-cover cover-reader"&gt;
&lt;img class="cover-image" src="https://figueirego-blog-images.s3.us-east-1.amazonaws.com/images/2026/10/building-blog-publishing/publicacao-pt.webp" alt="Revisar, testar, publicar e conferir: as quatro etapas do fluxo de entrega deste site." width="1200" height="1000" loading="lazy" decoding="async"&gt;&lt;/div&gt;&lt;figcaption&gt;Revisar, testar, publicar e conferir: as quatro etapas do fluxo de entrega deste site.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href="https://figueirego-blog-images.s3.us-east-1.amazonaws.com/images/2026/10/building-blog-publishing/publicacao-pt.webp" target="_blank" rel="noopener"&gt;Abrir diagrama em tamanho original&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-hextra-search-id="conferir-três-resultados-separados"&gt;Conferir três resultados separados&lt;span class="hx:absolute hx:-mt-20" id="conferir-três-resultados-separados"&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Um check verde mostra o resultado da verificação. O deployment na Hostinger informa se a hospedagem conseguiu construir e iniciar a versão correspondente. Abrir as páginas públicas mostra o que está sendo entregue.&lt;/p&gt;
&lt;p&gt;Por isso, a conferência inclui os dois idiomas, os links do artigo, as imagens, o RSS e o caminho de volta ao restante do site. Também preciso olhar o SHA da implantação. Um código de resposta HTTP 200 não demonstra que todos os componentes da página funcionaram.&lt;/p&gt;
&lt;p&gt;Para conteúdo, há uma verificação adicional: confirmar que um rascunho não entrou na busca, no sitemap ou no feed. Uma prévia que inclui rascunhos não pode ser copiada para produção como se fosse o build público.&lt;/p&gt;
&lt;figure class="reader-figure reader-figure-wide"&gt;
&lt;div class="post-cover cover-reader"&gt;
&lt;img class="cover-image" src="https://figueirego-blog-images.s3.us-east-1.amazonaws.com/images/2026/10/building-blog-publishing/hostinger-deploy-real.webp" alt="Painel da Hostinger indicando implantação concluída da branch production, com Next.js e Node 24." width="1092" height="195" loading="lazy" decoding="async"&gt;&lt;/div&gt;&lt;figcaption&gt;Recorte real do deploy concluído em 19/10/2026, referente à publicação inicial desta série com as capas. A hospedagem identifica o commit que recebeu.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href="https://figueirego-blog-images.s3.us-east-1.amazonaws.com/images/2026/10/building-blog-publishing/hostinger-deploy-real.webp" target="_blank" rel="noopener"&gt;Ver captura em tamanho original&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-hextra-search-id="os-mais-lidos-também-passam-por-publicação"&gt;Os mais lidos também passam por publicação&lt;span class="hx:absolute hx:-mt-20" id="os-mais-lidos-também-passam-por-publicação"&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;O GoatCounter fornece estatísticas de visitas. Uma rotina no GitHub consulta esses dados e grava um snapshot em &lt;code&gt;blog/data/popular.json&lt;/code&gt;. O build incorpora esse resultado e entrega um arquivo público em &lt;code&gt;/blog/popular.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O navegador pode atualizar as listas a partir desse arquivo, sem receber o token de consulta ao GoatCounter. A rotina de coleta tem execução diária e tentativas de recuperação. Horários agendados dependem dos provedores; não são uma garantia de atualização no segundo marcado.&lt;/p&gt;
&lt;p&gt;Semana e mês representam os sete e trinta dias completos anteriores, em UTC. As versões de um mesmo artigo são agregadas pela identidade editorial. Isso conta visitas registradas, não pessoas únicas entre idiomas nem prova de leitura completa.&lt;/p&gt;
&lt;p&gt;Quando a coleta falha, o fluxo conserva o snapshot anterior em vez de publicar números inventados. Uma atualização válida ainda precisa passar pela verificação e chegar à hospedagem. Monitorar o JSON público ajuda a detectar a diferença entre ter coletado dados e ter publicado esses dados.&lt;/p&gt;
&lt;p&gt;Essa rotina faz parte do custo de manter o site. Automatizar ajuda, mas o resultado importante continua sendo o conteúdo correto no endereço que a pessoa abre.&lt;/p&gt;
&lt;nav id="series-navigation" class="series-navigation" aria-label="Construindo meu blog"&gt;
&lt;div class="series-heading"&gt;
&lt;h2&gt;Construindo meu blog&lt;/h2&gt;
&lt;p&gt;Explore as 5 partes da série.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="series-chapters" role="list"&gt;
&lt;li&gt;
&lt;a class="series-chapter" href="https://figueirego.com/pt/blog/posts/construindo-o-blog-01-arquitetura/"&gt;
&lt;span class="series-number" aria-hidden="true"&gt;01&lt;/span&gt;
&lt;span class="series-title"&gt;Ideia e arquitetura&lt;/span&gt;
&lt;svg width="20" height="20" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"&gt;&lt;path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a class="series-chapter" href="https://figueirego.com/pt/blog/posts/construindo-o-blog-02-leitura/"&gt;
&lt;span class="series-number" aria-hidden="true"&gt;02&lt;/span&gt;
&lt;span class="series-title"&gt;Design e leitura&lt;/span&gt;
&lt;svg width="20" height="20" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"&gt;&lt;path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span class="series-chapter" aria-current="page"&gt;
&lt;span class="series-number" aria-hidden="true"&gt;03&lt;/span&gt;
&lt;span class="series-title"&gt;Publicação&lt;/span&gt;
&lt;span class="series-current"&gt;Você está aqui&lt;/span&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a class="series-chapter" href="https://figueirego.com/pt/blog/posts/construindo-o-blog-04-imagens/"&gt;
&lt;span class="series-number" aria-hidden="true"&gt;04&lt;/span&gt;
&lt;span class="series-title"&gt;Imagens e automação&lt;/span&gt;
&lt;svg width="20" height="20" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"&gt;&lt;path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a class="series-chapter" href="https://figueirego.com/pt/blog/posts/construindo-o-blog-05-seo-rss/"&gt;
&lt;span class="series-number" aria-hidden="true"&gt;05&lt;/span&gt;
&lt;span class="series-title"&gt;SEO e RSS&lt;/span&gt;
&lt;svg width="20" height="20" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"&gt;&lt;path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/nav&gt;</description></item><item><title>Construindo meu blog, parte 1: da landing page ao site</title><link>https://figueirego.com/pt/blog/posts/construindo-o-blog-01-arquitetura/</link><pubDate>Mon, 19 Oct 2026 04:15:50 -0300</pubDate><guid>https://figueirego.com/pt/blog/posts/construindo-o-blog-01-arquitetura/</guid><description>&lt;p&gt;&lt;img src="https://figueirego-blog-images.s3.us-east-1.amazonaws.com/images/2026/10/building-blog-architecture/arquitetura.webp" alt="Maquete de três construções sobre uma mesa de madeira, com desenhos de arquitetura e um caderno aberto."&gt;&lt;/p&gt;&lt;p&gt;Eu já tinha um projeto de site. Era uma landing page, com uma ideia que eu ainda queria manter, mas que precisava de mais espaço. Resolvi reaproveitar essa base, subdividir o conteúdo e melhorar a forma de apresentar meu trabalho e as coisas sobre as quais queria escrever.&lt;/p&gt;
&lt;p&gt;Uma das mudanças mais visíveis foi transformar uma experiência de terminal em um desktop. O terminal tinha uma linguagem muito voltada para quem programa. Eu queria que uma pessoa pudesse explorar o site sem precisar conhecer comandos. Janelas e ícones me pareceram um ponto de partida mais familiar, embora isso ainda precisasse funcionar bem na prática e no celular.&lt;/p&gt;
&lt;p&gt;O blog entrou nessa mesma construção. Meu receio ao juntar os dois era confundir a navegação e não conseguir ser claro sobre o que cada área oferecia. Por isso, esta série começa pela organização do projeto. O código veio acompanhado de decisões sobre comunicação.&lt;/p&gt;
&lt;figure class="reader-figure reader-figure-wide"&gt;
&lt;div class="post-cover cover-reader"&gt;
&lt;img class="cover-image" src="https://figueirego-blog-images.s3.us-east-1.amazonaws.com/images/2026/10/building-blog-architecture/desktop-real-pt.webp" alt="Desktop do portfólio com explorador, pastas e dock de aplicativos." width="1512" height="893" loading="lazy" decoding="async"&gt;&lt;/div&gt;&lt;figcaption&gt;O desktop real do portfólio: janelas e pastas como alternativa de exploração, mantendo a navegação convencional disponível.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href="https://figueirego-blog-images.s3.us-east-1.amazonaws.com/images/2026/10/building-blog-architecture/desktop-real-pt.webp" target="_blank" rel="noopener"&gt;Ver captura em tamanho original&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-hextra-search-id="referências-com-papéis-diferentes"&gt;Referências com papéis diferentes&lt;span class="hx:absolute hx:-mt-20" id="referências-com-papéis-diferentes"&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;O &lt;a href="https://akitaonrails.com/2025/09/10/meu-novo-blog-como-eu-fiz/" target="_blank" rel="noopener"&gt;blog do Akita&lt;/a&gt; me ajudou com a construção do blog e com ideias para a rotina de publicação. Já o &lt;a href="https://zenorocha.com/" target="_blank" rel="noopener"&gt;site do Zeno Rocha&lt;/a&gt; foi uma referência de apresentação: como mostrar o próprio trabalho e deixar a exploração intuitiva.&lt;/p&gt;
&lt;p&gt;Usei essas referências para estudar o que poderia melhorar, reaproveitar ou descartar. Eu tinha uma ideia própria para preservar e precisava entender quais soluções ajudavam a expressá-la. A parte mais trabalhosa acabou sendo acertar o design para transmitir essa identidade.&lt;/p&gt;
&lt;p&gt;As IAs participaram desse estudo. Concentrei mais no Codex a busca de informação e a investigação do projeto; usei Claude e Antigravity principalmente no design. Depois voltei ao Codex com skills para separar e aprofundar cada conceito. Essa divisão descreve meu processo, não uma regra sobre qual ferramenta qualquer pessoa deveria usar.&lt;/p&gt;
&lt;h2 data-hextra-search-id="onde-termina-o-site-e-começa-o-blog"&gt;Onde termina o site e começa o blog&lt;span class="hx:absolute hx:-mt-20" id="onde-termina-o-site-e-começa-o-blog"&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Hoje, o portfólio usa Next.js, React e TypeScript. Os artigos ficam em Markdown e são gerados pelo Hugo. O Hextra serve como base do tema, com personalizações em arquivos do projeto.&lt;/p&gt;
&lt;p&gt;O Hugo é um gerador: lê o texto e seus metadados e produz HTML, CSS, JavaScript e índices. O Next.js reúne esse resultado com as páginas do portfólio. A Hostinger executa a aplicação Next.js e entrega o conjunto no mesmo domínio.&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blog/content/ → Hugo → páginas, busca e feeds do blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client/public/blog/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; client/public/pt/blog/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Next.js + páginas do portfólio → Hostinger&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Isso corrige uma descrição da primeira versão do projeto, quando o blog estava separado. O conjunto atual tem um servidor Next.js em produção; o Hugo só roda na geração dos arquivos. Os artigos não precisam de uma API própria de edição ou de um banco de dados para montar seu conteúdo a cada visita.&lt;/p&gt;
&lt;figure class="reader-figure reader-figure-wide"&gt;
&lt;div class="post-cover cover-reader"&gt;
&lt;img class="cover-image" src="https://figueirego-blog-images.s3.us-east-1.amazonaws.com/images/2026/10/building-blog-architecture/arquitetura-pt.webp" alt="Markdown passa pelo Hugo; arquivos gerados são integrados ao Next.js e entregues pela Hostinger." width="1200" height="1000" loading="lazy" decoding="async"&gt;&lt;/div&gt;&lt;figcaption&gt;Markdown passa pelo Hugo; arquivos gerados são integrados ao Next.js e entregues pela Hostinger.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href="https://figueirego-blog-images.s3.us-east-1.amazonaws.com/images/2026/10/building-blog-architecture/arquitetura-pt.webp" target="_blank" rel="noopener"&gt;Abrir diagrama em tamanho original&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-hextra-search-id="cada-tecnologia-precisa-ter-um-trabalho-claro"&gt;Cada tecnologia precisa ter um trabalho claro&lt;span class="hx:absolute hx:-mt-20" id="cada-tecnologia-precisa-ter-um-trabalho-claro"&gt;&lt;/span&gt;&lt;/h2&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Componente&lt;/th&gt;
&lt;th&gt;Responsabilidade neste projeto&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Markdown&lt;/td&gt;
&lt;td&gt;Texto, resumo, data, idioma e demais dados editoriais.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hugo e Hextra&lt;/td&gt;
&lt;td&gt;Geração do blog e base dos layouts.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next.js&lt;/td&gt;
&lt;td&gt;Páginas do portfólio e entrega integrada do site.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub e Actions&lt;/td&gt;
&lt;td&gt;Histórico do código e conteúdo, testes e preparação da publicação.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hostinger&lt;/td&gt;
&lt;td&gt;Build e execução da versão publicada.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amazon S3&lt;/td&gt;
&lt;td&gt;Armazenamento das imagens enviadas separadamente.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disqus&lt;/td&gt;
&lt;td&gt;Conversas e moderação dos comentários.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GoatCounter&lt;/td&gt;
&lt;td&gt;Estatísticas de visitas que alimentam os mais lidos.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Não acrescentei um banco de dados só para guardar os artigos. Também não coloquei o armazenamento das imagens dentro da responsabilidade do Hugo. Essa separação ajuda a encontrar problemas: uma imagem indisponível, um artigo ausente e um comentário que não carrega podem ter causas diferentes.&lt;/p&gt;
&lt;h2 data-hextra-search-id="organização-que-dá-para-enxergar-nos-arquivos"&gt;Organização que dá para enxergar nos arquivos&lt;span class="hx:absolute hx:-mt-20" id="organização-que-dá-para-enxergar-nos-arquivos"&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;A estrutura principal ficou assim:&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client/ aplicação Next.js
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blog/content/pt/ conteúdo em português
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blog/content/en/ conteúdo em inglês
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blog/layouts/ personalizações de layout
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blog/assets/ estilos e interações
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blog/themes/hextra/ tema de base
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blog/scripts/ auxiliares de publicação e imagens
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.github/workflows/ verificações e automações do conjunto&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As personalizações ficam fora da pasta do tema. Isso facilita revisar uma atualização sem misturar cada ajuste local ao código original do Hextra. Continua sendo necessário testar a atualização; a estrutura de pastas não garante compatibilidade.&lt;/p&gt;
&lt;p&gt;O repositório ativo é privado. O resultado publicado, incluindo artigos, imagens e scripts enviados ao navegador, é público. O leitor não precisa acessar o repositório para usar o site, mas os comandos desta série são exemplos do meu projeto, não um pacote público pronto para clonar.&lt;/p&gt;
&lt;h2 data-hextra-search-id="o-que-eu-organizaria-antes-de-começar"&gt;O que eu organizaria antes de começar&lt;span class="hx:absolute hx:-mt-20" id="o-que-eu-organizaria-antes-de-começar"&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Se começasse hoje, olharia melhor para o design e a arquitetura antes de implementar. Separaria cada responsabilidade, o propósito de cada área e o papel das tecnologias. Fui descobrindo parte dessa organização enquanto construía.&lt;/p&gt;
&lt;p&gt;Para um projeto parecido, eu começaria escrevendo o caminho do visitante: onde ele entende quem sou, onde encontra meus projetos e onde lê os textos. Depois desenharia o percurso de um artigo até a publicação. Esses dois mapas ajudam a perceber quais partes precisam conversar e quais podem continuar independentes.&lt;/p&gt;
&lt;p&gt;Na próxima parte, entro no ponto que mais exigiu tentativas: fazer essa organização aparecer na interface, sem obrigar quem chega a entender a arquitetura do projeto.&lt;/p&gt;
&lt;nav id="series-navigation" class="series-navigation" aria-label="Construindo meu blog"&gt;
&lt;div class="series-heading"&gt;
&lt;h2&gt;Construindo meu blog&lt;/h2&gt;
&lt;p&gt;Explore as 5 partes da série.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="series-chapters" role="list"&gt;
&lt;li&gt;
&lt;span class="series-chapter" aria-current="page"&gt;
&lt;span class="series-number" aria-hidden="true"&gt;01&lt;/span&gt;
&lt;span class="series-title"&gt;Ideia e arquitetura&lt;/span&gt;
&lt;span class="series-current"&gt;Você está aqui&lt;/span&gt;
&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a class="series-chapter" href="https://figueirego.com/pt/blog/posts/construindo-o-blog-02-leitura/"&gt;
&lt;span class="series-number" aria-hidden="true"&gt;02&lt;/span&gt;
&lt;span class="series-title"&gt;Design e leitura&lt;/span&gt;
&lt;svg width="20" height="20" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"&gt;&lt;path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a class="series-chapter" href="https://figueirego.com/pt/blog/posts/construindo-o-blog-03-publicacao/"&gt;
&lt;span class="series-number" aria-hidden="true"&gt;03&lt;/span&gt;
&lt;span class="series-title"&gt;Publicação&lt;/span&gt;
&lt;svg width="20" height="20" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"&gt;&lt;path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a class="series-chapter" href="https://figueirego.com/pt/blog/posts/construindo-o-blog-04-imagens/"&gt;
&lt;span class="series-number" aria-hidden="true"&gt;04&lt;/span&gt;
&lt;span class="series-title"&gt;Imagens e automação&lt;/span&gt;
&lt;svg width="20" height="20" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"&gt;&lt;path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a class="series-chapter" href="https://figueirego.com/pt/blog/posts/construindo-o-blog-05-seo-rss/"&gt;
&lt;span class="series-number" aria-hidden="true"&gt;05&lt;/span&gt;
&lt;span class="series-title"&gt;SEO e RSS&lt;/span&gt;
&lt;svg width="20" height="20" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true"&gt;&lt;path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/nav&gt;</description></item></channel></rss>