⚡ AutomationsAI|Portal de Cursos →

Verificando acesso...

MÓDULO 4.4

📂 Sites estáticos via GitHub API

Publicar posts num blog estático sem abrir editor: PUT na API do GitHub, frontmatter YAML e Actions rebuildando o site sozinho a cada commit.

6
Tópicos
30
Minutos
Básico
Nível
Prático
Tipo
1

🌐 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.

2

🔑 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)

Contents: Read & write

Permite criar/editar/deletar arquivos no repositório — o essencial.

Metadata: Read

Obrigatório por padrão. Lê info básica do repo.

Actions: Read

Opcional. Permite consultar status de workflows após push.

Pages: Read & write

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.

3

📤 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

message

Mensagem do commit (obrigatório).

content

Conteúdo em Base64 (obrigatório).

branch

Branch alvo. Default: branch padrão do repo.

sha

Hash atual do arquivo — só para update.

4

📝 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.md ordena cronologicamente no FS.
  • Data ISO 8601: 2026-05-24T10:30:00-03:00 com 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 :.
5

⚙️ 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 build e deploy para retry isolado.
  • workflow_dispatch para rebuild manual sem commit.

✗ Armadilhas

  • @latest nas actions — quebra em update inesperado.
  • Esquecer fetch-depth: 0 e quebrar lastmod.
  • Permissões amplas — só conceda contents: read.
  • Build >10min no plano free — quota mensal estoura rápido.
6

✅ 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

SSG escolhido — Hugo/Astro para automação, Jekyll para Pages puro, Next só com áreas dinâmicas.
PAT criado — token fine-grained, escopo Contents: write, expiração curta.
API dominadaPUT /contents com body em Base64, sha para update.
Frontmatter pronto — YAML válido com title, date ISO, tags e draft.
Action configurada — workflow pages-build-deployment publica a cada push.
Trade-offs claros — performance, custo, versionamento e segurança vs limites do estático.

🏁 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.