Refactor: Blog
Análise do repositório notion-blog
Meu blog pessoal estava cheio de bugs pois eu só não fiz a devida manutenção que precisava ao longo do período desde que criei — talvez 2 anos. Agora a ideia é corrigir bugs e funcionalidades que eu gostaria de adicionar.

Paginação com erros, demora no carregamento, conteúdo centralizado em ferramenta.
O que gostaria de melhorar: descentralizar o conteúdo, organizar o backup rotineiro (por versão), fazer o deploy em dev (não somente em main).
1. Visão geral
É um blog estático em Next.js que usa o Notion como CMS/backend. É um fork do template original de ijjk/notion-blog, personalizado por mim. O conteúdo dos posts vive em uma tabela do Notion e o site é gerado via SSG (Static Site Generation) com revalidação incremental, hospedado na Vercel.
- Deploy atual:
https://notion-blog-lake-two.vercel.app/ - Branch atual:
claude/repository-analysis-ieglo6(idêntica adevelop— sem diferenças) - Licença: presente (
license)
2. Stack e dependências
| Camada | Tecnologia |
|---|---|
| Framework | Next.js ^11.1.2 (Pages Router) |
| UI | React 17, CSS Modules |
| Linguagem | TypeScript 5.8 (com strict: false) |
| Conteúdo | API privada não-oficial do Notion (www.notion.so/api/v3) |
| Extras | katex (equações), prismjs (syntax highlight), @zeit/react-jsx-parser, async-sema (rate limit), github-slugger |
| Qualidade | Prettier + lint-staged + pre-commit |
| Deploy | Vercel |
3. Estrutura
src/
├── pages/
│ ├── index.tsx # Home
│ ├── contact.tsx # Contato (GitHub/LinkedIn)
│ ├── blog/index.tsx # Lista de posts (getStaticProps)
│ ├── blog/[slug].tsx # Renderiza 1 post (getStaticProps/Paths + fallback)
│ └── api/ # asset.ts, preview.ts, preview-post.ts, clear-preview.ts
├── lib/notion/ # Integração com o Notion (rpc, getBlogIndex, getPageData…)
├── lib/build-rss.ts # Gera feed Atom em /public/atom no build
├── components/ # Header, Footer, Code, Equation, Counter, SVGs, SpotifyPlayer…
└── styles/ # CSS Modules + global.css
scripts/create-table.js # Cria a tabela-modelo no Notion via API privada4. Como funciona (fluxo de dados)
rpc.tsfaz POST autenticado no endpoint privado do Notion usando o cookietoken_v2=$NOTION_TOKEN.getBlogIndexcarrega a tabela (BLOG_INDEX_ID), monta o mapa de posts viagetTableData(que interpreta o schema da collection do Notion) e busca previews dos 10 posts mais recentes com concorrência limitada a 3 (async-sema). Usa cache em disco (.blog_index_data*) durante o build (USE_CACHE).blog/index.tsxfiltra rascunhos em produção (Published === 'Yes') e lista os posts.blog/[slug].tsxbusca o conteúdo do post (getPageData→loadPageChunkpaginado), resolve embeds de tweets, e faz um switch gigante convertendo cada tipo de bloco do Notion (text, header, image, code, quote, callout, equation, bookmark, tweet…) em JSX.api/asset.tsfunciona como proxy: pega a URL assinada do arquivo no Notion (getSignedFileUrls) e redireciona (307) para servir imagens/vídeos.build-rss.tsroda no build e gera o feed Atom empublic/atom.- Preview mode:
api/preview.tsepreview-post.tshabilitam o modo rascunho do Next.
5. Pontos fortes
- Arquitetura enxuta e bem separada (lib/pages/components).
- Uso correto de SSG +
revalidate(ISR) efallback: true. - Rate-limiting no fetch de previews e cache de build.
- Suporte rico a blocos do Notion (equações KaTeX, código com Prism, callouts, bookmarks, vídeo, tweets).
- Ferramentas de formatação já configuradas (Prettier/lint-staged).
6. Problemas e riscos que encontrei
Segurança / prático
NOTION_TOKENusado como senha de preview:preview.tsepreview-post.tscomparamreq.query.token === process.env.NOTION_TOKEN. Isso coloca o token secreto do Notion na URL (fica em logs, histórico, referrers). Deveria ser um segredo separado (NEXT_PREVIEW_SECRET).- API privada do Notion (
token_v2+/api/v3): não é oficial, pode quebrar a qualquer momento e o token é a sua sessão pessoal. O ideal moderno é migrar para a API oficial do Notion (@notionhq/client). api/asset.tsé um proxy aberto (Access-Control-Allow-Origin: *) que assina URLs para qualquerassetUrl/blockIdrecebido — vale restringir.
Dependências não declaradas
node-fetch,@next/enveshell-quotesão importados mas não constam nopackage.json(funcionam só por dependência transitiva/hoisting). Isso é frágil e pode quebrar o build com um lockfile limpo. Devem ser adicionados como dependências explícitas.
Restos do template original (branding inconsistente)
header.tsx: link “Source Code” e OG image apontam paraijjk/notion-blogenotion-blog.now.sh(domínionow.shdesativado), twitter@_ijjk.footer.tsx: link para o repo doijjk.index.tsx: ainda usa a imagem/branding “Vercel + Notion”.- Metadados/
<title>genéricos (“My Notion Blog”, “An example Next.js site…”). - Idiomas misturados (PT + EN) na interface.
Código potencialmente quebrado/frágil
- Embed de tweets usa
api.twitter.com/1/statuses/oembed.json(API v1, descontinuada) — provavelmente já não funciona. [slug].tsxusaunstable_revalidate(API antiga, ignorada no Next 11) junto comrevalidate.equation.tsx:render()pode retornarundefinedse o erro não forParseError(a variávelresultnunca é atribuída).getPageDataremove blocos de tabela comsplice(0, 3)fixo — quebradiço.- Incoerência de versão de Node: o
readmepede Node>=18, masgetBlogIndex.tsusaArray.prototype.toSorted()que exige Node 20+. Jávercel.jsonforça-openssl-legacy-provider(workaround de build antigo). Recomendo fixar Node 20 explicitamente.
Qualidade / manutenção
tsconfigcomstrict: false(perde segurança de tipos; muitoany).- Sem testes e sem CI (
.github/ausente). - README com pequenos erros (crases
´´´em vez de```).
7. Recomendações priorizadas
- Trocar o segredo de preview por uma variável dedicada (não reusar
NOTION_TOKENna URL). - Declarar
node-fetch,@next/env,shell-quotenopackage.json. - Atualizar o branding: links, OG image, título e twitter para os meus (remover resíduos do
ijjk/now.sh). - Corrigir/remover o embed de tweets (API v1 morta) e o
unstable_revalidate. - Alinhar a versão do Node (fixar
engines: node >=20) por causa dotoSorted(). - (Médio prazo) Migrar para a API oficial do Notion e considerar atualizar o Next.js (11 → recente) para segurança e performance.
Correções no Blog

Primeiro foi solicitado para realizar uma análise utilizando o claude.ai, seguindo foi escrito o seguinte script.
📚 claude/repository-analysis-ieglo6? Posso começar pelas de baixo risco e alto impacto (dependências no package.json, branding, segredo de preview e os bugs pequenos). Como esta foi uma tarefa de análise, não fiz nenhuma alteração ainda.
Faça as implementações da seguinte forma.
- Corrija os pontos, sempre realizando os testes necessários, não deve implementar sem testar.
- Após testes de validação, abra PRs
- Quando tiver uma atualização delicada, deve ter atenção aos pontos para não quebrar em produção.
- Deve documentar as alterações somente no meu repositório kellen-xavier
- Deve criar a pasta /docs para uso de documentação
- Não deve compartilhar chaves e dados sensíveis - isso inclui documentações, README.md
- Criar um setup .agents no repositório, para adicionar informações persistentes
- Deve incluir no setup o arquivo .AGENTS.md
Para cada step dado aqui, tenha atenção e testes.
| Etapa | Mudança | Validação |
|---|---|---|
| Dependências | Declarei node-fetch@2.6.1, @next/env@11.1.2, shell-quote@1.7.2 (dev) e @types/node-fetch; adicionei engines.node >=20 e scripts typecheck/test | tsc verde |
| Segurança (delicado) | PREVIEW_TOKEN dedicado em src/lib/preview-auth.ts, com fallback para NOTION_TOKEN para não quebrar produção | 4 testes (401/404/ok/fallback) |
| Branding | Removidos resíduos ijjk/now.sh de header/footer/server-constants | teste de regressão |
| Bugs | equation.render nunca retorna undefined; unstable_revalidate → revalidate; oembed de tweet v1 morto → publish.twitter.com | teste do render + build |
| Docs | /docs (SETUP, ARCHITECTURE, SECURITY, CHANGELOG) — só no meu repo | — |
| Agentes | AGENTS.md na raiz + .agents/ (contexto + convenções persistentes) | — |
.AGENTS.md(com ponto): usei a convenção padrãoAGENTS.mdna raiz (é o nome que as ferramentas de agente reconhecem) + a pasta.agents/para o setup persistente.- O PR foi aberto contra
develop(branch padrão do repo), em 4 commits temáticos.