Doc interna · /how-it-works

Como este portfólio é alimentado e atualizado

O site é um HTML estático, mas o conteúdo é dinâmico: todo texto vive em um JSON que pode vir de três fontes independentes — git, Notion, ou email processado por IA. Uma GitHub Action sincroniza tudo diariamente, e uma camada de segurança com gitleaks garante que nenhum segredo entre no repo.

Stack grátis GitHub Pages GitHub Actions Notion API Gitleaks

01 · Arquitetura

Dois repos, um pipeline, três entradas

Nada de servidor próprio. Tudo roda em runners do GitHub e em storage estático (Pages). Custo: zero.

 ┌─────────────────────┐     ┌─────────────────────┐     ┌──────────────────┐
 │  Gmail / IMAP       │     │  Notion workspace   │     │  Edição manual   │
 │  (caixa de entrada) │     │  (6 databases)      │     │  (GitHub web/CLI)│
 └─────────┬───────────┘     └─────────┬───────────┘     └────────┬─────────┘
           │                           │                          │
           ▼                           ▼                          │
 ┌─────────────────────┐     ┌─────────────────────┐              │
 │ email-to-notion-ai  │     │ portfolio           │              │
 │ (n8n ou standalone) │     │ Action sync-notion  │              │
 │  OpenAI → Notion    │     │  cron 03h UTC       │              │
 └─────────┬───────────┘     └─────────┬───────────┘              │
           │ escreve em              │ lê Notion                │
           ▼                         ▼                          │
 ┌──────────────────────────────────────────────────┐           │
 │   Notion DB "Portfólio" + 5 DBs de seção         │           │
 └─────────────────────┬────────────────────────────┘           │
                       │ query via REST API                    │
                       ▼                                       │
             ┌─────────────────────────┐      merge-update      │
             │  .github/scripts/       │◄───────────────────────┘
             │  sync-notion.mjs        │     commit direto se
             │  (gera site.json)       │     Notion não responder
             └─────────────┬───────────┘
                           │ commit + push
                           ▼
                ┌─────────────────────┐
                │  assets/data/       │
                │  site.json          │    ◄─── single source of truth
                │  posts.json         │
                └─────────────┬───────┘
                              │ fetch client-side
                              ▼
                   ┌─────────────────────┐
                   │  GitHub Pages       │
                   │  rodckdev.github.io │
                   │  /portfolio/        │
                   └─────────────────────┘

Por que JSON no meio

Poderia chamar o Notion direto do browser, mas a API key vazaria (JS roda no cliente) e teríamos problema de CORS. O JSON committado resolve os dois: token fica só no Action (server-side) e o site lê um arquivo estático no próprio domínio.

Por que commit no próprio repo

O Action escreve o JSON atualizado direto em main. Isso dá histórico versionado (dá pra reverter qualquer mudança com git revert) e faz o Pages redeployar sozinho — zero configuração de CDN.

02 · Três formas de editar

Escolha o canal que encaixa no contexto

Os três convergem no mesmo site.json. Nenhum exclui o outro; dá pra misturar.

A

Git direto

Quando: mudanças pontuais, mobile, sem internet no Notion.

  1. Abrir assets/data/site.json na interface web do GitHub
  2. Editar o campo → commit
  3. Pages redeploya em ~30s

Prós: instantâneo, sem dependência externa.

Contras: JSON puro, sem UI amigável.

B

Notion como CMS

Quando: você já está editando algo no Notion (mobile, rascunho, etc).

  1. Editar uma linha em qualquer um dos 5 DBs (Deliverables, Skills, Initiatives, Influence, Progress)
  2. Esperar o cron das 03h UTC ou rodar gh workflow run sync-notion.yml
  3. Action pega via API, gera site.json, commita, Pages redeploya

Prós: UI decente, edição colaborativa, edita do celular.

Contras: latência de até 24h se não rodar manual.

C

Email → IA → Notion

Quando: chegou um email sobre uma entrega/marco que vale registrar.

  1. Email chega no Gmail → email-to-notion-ai (n8n ou IMAP standalone) detecta
  2. OpenAI estrutura em 13 campos + classifica publicável?
  3. Escreve no DB Atividades e, se publicável, também em Portfólio
  4. No próximo sync, entra na seção 08 · Posts publicados do site

Prós: zero trabalho manual, fecha o loop "trabalho real → portfólio público".

Contras: depende de filtro de relevância bem calibrado.

03 · Notion como CMS

Mapa DB → seção do site

Cada DB é independente. Ausente ou vazio = sync preserva o que já está em site.json (merge-update).

Notion DB Secret (ID) Seção renderizada O que colocar lá
Site Deliverables NOTION_DELIVERABLES_DB_ID 02 · Entregas principais E1–E5: descritivo, impacto técnico, financeiro, stakeholders, KPIs
Site Influence NOTION_INFLUENCE_DB_ID 03 · Influência cross-team Teams que adotaram padrões seus, impacto replicado
Site Progress NOTION_PROGRESS_DB_ID 04 · Dashboard de progresso Dimensão / status / target 2025 / evidência
Site Skills NOTION_SKILLS_DB_ID 05 · Skill matrix Skill, nível atual, esperado para Staff, gap, plano
Site Initiatives NOTION_INITIATIVES_DB_ID 06 · Próximas iniciativas O que, por que, impacto, timeline, métrica
Portfólio (do email-to-notion-ai) NOTION_PORTFOLIO_DB_ID 08 · Posts publicados Entradas com Publicable = true (via IA)

Regra de merge

O sync-notion.mjs faz shallow-merge por id — campos vindos do Notion sobrescrevem, mas qualquer campo que só exista no site.json é preservado. Isso permite enriquecer itens no JSON (ex.: tabela de breakdown financeiro do E2) sem risco de o próximo sync apagar.

04 · Camada de segurança

Defesa em profundidade contra vazamento de segredos

Quatro barreiras, independentes entre si. Falhou uma, as outras seguram.

1

.gitignore endurecido

Bloqueia .env*, *.pem, *.key, credentials.json, service-account*.json, *.tfvars. Exceto os .example.

2

Gitleaks em CI

Escaneia cada PR, cada push em main, e varredura semanal do histórico inteiro (pega vazamento em branches velhos). Regras extras para Notion (secret_.../ntn_...), OpenAI (sk-...) e GitHub PATs.

3

Secrets isolados por repo

GitHub Actions secrets em portfolio e email-to-notion-ai são separados. Comprometimento de um não cascata para o outro. Valores mascarados como *** nos logs.

4

Runbook de rotação

SECURITY.md tem passo-a-passo para rotacionar NOTION_API_KEY / OPENAI_API_KEY / GMAIL_APP_PASSWORD e checklist de resposta a incidente.

O que NÃO é segredo (e por quê)

O email de contato (rckosai81@gmail.com) é conteúdo público — está no CV. DB IDs do Notion sozinhos não abrem nada (exigem o token + integration conectada à página), mas ainda ficam em secrets por defesa em profundidade. UUIDs de nós do n8n no workflow JSON são internos do n8n, não credenciais.

05 · Releases

Histórico de mudanças do CMS

Cada item linka para o PR original. Ordem cronológica inversa.

  1. seg

    Camada de segurança (gitleaks + SECURITY.md)

    Scanner de segredos em CI (PR, push, cron semanal), regras para Notion/OpenAI/GitHub, .gitignore endurecido, runbook de rotação. PR #5 · email-to-notion-ai PR #3

  2. fix

    Bugfix Windows path + shallow-merge

    setup-site-dbs.mjs usando fileURLToPath (estava falhando silenciosamente em Windows por causa do /C:/...). Sync agora faz merge por id em vez de replace — preserva campos locais como a tabela de breakdown do E2. PR #4

  3. feat

    Notion como CMS do site inteiro

    Todo conteúdo sai do HTML e vai pro site.json. 5 DBs novos no Notion alimentam as seções 02–06. Bootstrap via setup-site-dbs.mjs (seed do site.json atual). Merge-update preserva seção se DB estiver ausente. PR #3

  4. feat

    Feeds dinâmicos (GitHub topics + Notion Portfólio)

    Seção 07 lê repos com topic portfolio via API pública do GitHub. Seção 08 lê o DB Portfólio via Action diária. PR #2

  5. init

    Portfólio inicial + CV imprimível

    Site estático com hero, 5 entregas, influência, dashboard, skills, próximas iniciativas, observações. CV snapshot com CSS @media print → PDF A4 pronto para candidaturas. PR #1