🌐 Hugo / Jekyll / Astro / Next — qual escolher
Um Static Site Generator (SSG) lê arquivos Markdown e cospe HTML pronto. Não tem banco, não tem PHP, não tem runtime no servidor — o site é uma pasta de .html servida por CDN. Os quatro líderes têm perfis bem diferentes:
| SSG | Linguagem | Build | Quando usar |
|---|---|---|---|
| Hugo | Go | Brutalmente rápido (ms) | Blog grande, muitos posts, zero JS. |
| Jekyll | Ruby | Lento, padrão GH Pages | Compatibilidade com GitHub Pages "puro". |
| Astro | JS/TS | Rápido, islands | Blog moderno com componentes React/Vue pontuais. |
| Next.js | JS/TS | Médio, SSG ou SSR | App híbrido com áreas dinâmicas (dashboard, auth). |
🎯 Recomendação para automação
Para publicação automatizada via API, Hugo e Astro ganham: build sub-segundo no Hugo, ergonomia moderna no Astro. Jekyll só vence pelo GitHub Pages servir build nativo sem Actions. Next é overkill se você só quer blog estático.
🔑 PAT do GitHub — Personal Access Token
Para escrever em um repositório via API, você precisa de um Personal Access Token (PAT). É uma string que substitui senha em chamadas HTTP. Existem dois tipos: Classic (escopos amplos, mais antigo) e Fine-grained (por repo, recomendado em 2026).
Caminho: github.com → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token. Defina expiração curta (30-90 dias), restrinja ao repo do blog e marque os escopos mínimos.
Escopos necessários (Fine-grained)
Permite criar/editar/deletar arquivos no repositório — o essencial.
Obrigatório por padrão. Lê info básica do repo.
Opcional. Permite consultar status de workflows após push.
Opcional. Necessário só se for trigger manual de rebuild.
⚠️ Token vazado é game over
Um PAT com Contents: write pode reescrever todo o histórico. Nunca commite, nunca cole em chat público, nunca use em frontend. Guarde em .env local ou em GitHub Actions Secrets. Se vazar: revogue na hora em Settings → Tokens.
📤 PUT /repos/.../contents
O endpoint PUT /repos/{owner}/{repo}/contents/{path} cria ou atualiza um arquivo. O corpo precisa do conteúdo codificado em Base64 (não Markdown puro) e uma mensagem de commit. Para atualizar, mande também o sha do arquivo atual.
# Criar arquivo content/posts/2026-05-24-meu-post.md
CONTENT_B64=$(printf '%s' '---
title: "Meu primeiro post via API"
date: 2026-05-24
tags: [api, automacao]
---
Conteúdo do post em **Markdown**.' | base64 -w0)
curl -X PUT \
-H "Authorization: Bearer ghp_SEU_TOKEN_AQUI" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/SEU_USER/meu-blog/contents/content/posts/2026-05-24-meu-post.md \
-d "{
\"message\": \"post: meu primeiro post via API\",
\"content\": \"$CONTENT_B64\",
\"branch\": \"main\"
}"
Resposta 201 Created com o commit.sha e o content.sha. Guarde esse sha — você precisa dele para editar o mesmo arquivo depois (manda no body como "sha": "...").
Campos do body
Mensagem do commit (obrigatório).
Conteúdo em Base64 (obrigatório).
Branch alvo. Default: branch padrão do repo.
Hash atual do arquivo — só para update.
📝 Markdown com frontmatter
Frontmatter é o cabeçalho YAML entre duas linhas --- no topo do .md. Hugo/Jekyll/Astro leem essas chaves como metadados do post: título, data, tags, autor, draft, capa.
---
title: "Como automatizei meu blog via GitHub API"
date: 2026-05-24T10:30:00-03:00
draft: false
author: "AutomationsAI"
tags:
- automacao
- github
- hugo
categories: ["devops"]
cover:
image: "/img/covers/api-blog.png"
alt: "Diagrama do pipeline"
summary: "Pipeline n8n → GitHub API → Hugo → Pages, em 30 minutos."
---
# Introdução
O fluxo que vou mostrar **não exige editor**: o post chega via webhook,
o n8n monta o Markdown, dá `PUT` na API e a Action faz o resto.
## Por que isso importa
- Zero atrito para publicar
- Histórico completo no git
- Custo zero de hospedagem
```bash
echo "código inline funciona normal"
```
📌 Convenções importantes
- Nome do arquivo:
YYYY-MM-DD-slug.mdordena cronologicamente no FS. - Data ISO 8601:
2026-05-24T10:30:00-03:00com timezone evita posts "do futuro". - draft: true: esconde o post até você mudar para
false. - YAML rígido: indentação por 2 espaços, sem tabs. Aspas em títulos com
:.
⚙️ GitHub Actions = deploy automático
Quando seu PUT cria o arquivo, o GitHub dispara o evento push. Um workflow em .github/workflows/deploy.yml escuta esse evento, builda o SSG e publica em Pages. Você não toca em nada — o site sai no ar em ~60s.
# .github/workflows/deploy.yml
name: pages-build-deployment
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Hugo precisa do histórico p/ lastmod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: "0.140.0"
extended: true
- name: Build
run: hugo --minify --baseURL "${{ steps.pages.outputs.base_url }}/"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./public
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
✓ Boas práticas
- ✓Pin de versão do SSG (
hugo-version: "0.140.0") — build reprodutível. - ✓Cache do
node_modules/resources/para builds rápidos. - ✓Job separado de
buildedeploypara retry isolado. - ✓
workflow_dispatchpara rebuild manual sem commit.
✗ Armadilhas
- ✗
@latestnas actions — quebra em update inesperado. - ✗Esquecer
fetch-depth: 0e quebrar lastmod. - ✗Permissões amplas — só conceda
contents: read. - ✗Build >10min no plano free — quota mensal estoura rápido.
✅ Vantagens vs CMS tradicional
WordPress, Ghost e similares são ótimos para quem edita post manualmente. Mas para um pipeline automatizado, o blog estático ganha em quatro frentes objetivas:
Performance brutal
HTML pronto + CDN = TTFB de 30ms global. CMS dinâmico precisa hit em PHP + MySQL a cada request — 10x mais lento sem cache agressivo.
Custo zero (ou quase)
GitHub Pages, Cloudflare Pages, Netlify free: 100GB/mês, domínio próprio, HTTPS automático. Compare com VPS + backup + atualizações de WordPress.
Versionamento nativo
Cada post é um commit. git blame mostra quem editou o quê, git revert desfaz erros. Em WordPress, "histórico" é um plugin que pode falhar.
Segurança por ausência
Sem PHP, sem DB, sem painel admin público = sem CVE de plugin, sem brute-force em /wp-login.php, sem SQL injection. A superfície de ataque é zero.
⚖️ Quando NÃO usar estático
Se o blog precisa de comentários nativos, busca dinâmica, contagem de views em tempo real ou paywall, estático complica. Soluções: Disqus/Giscus (comentários), Algolia/Pagefind (busca), Plausible (analytics). Cada uma é um serviço extra.
🎯 Resumo do Módulo
Contents: write, expiração curta.PUT /contents com body em Base64, sha para update.pages-build-deployment publica a cada push.🏁 Trilha 4 concluída!
Você dominou os caminhos de publicação em blogs. Hora de partir para a Trilha 5 — Do Zero: montar um blog estático completo, do git init ao primeiro deploy, sem depender de templates prontos.