Aprimorando a renderização de imagens em slides Reveal.js com Codex
【Nota: primeira versão escrita por 冯宇; 胡键 complementou o contexto, reorganizou o texto e refinou a formatação.】
Primeira implementação com Claude Code
Nosso site técnico em inglês, Mona, oferece a funcionalidade de slides construída com Reveal.js para renderizar textos em Markdown. O resultado é assim:
- Slides mais recentes

- Um slide individual

A implementação não é complicada; basta seguir o fluxo típico do Astro:
- Criar um novo tipo de conteúdo.
- Criar a página Astro correspondente.
- Integrar o Reveal.js.
Slides naturalmente precisam de imagens. Como o Reveal.js faz a renderização no cliente, se simplesmente deixarmos as imagens dentro do diretório content, como fazemos com os blogs, e referenciarmos o caminho direto no Markdown, o Reveal.js não consegue exibi-las. Para esse novo tipo de conteúdo, o Astro não trata automaticamente os caminhos das imagens do Markdown como faz com o blog padrão.
A solução rápida era simples. Na época, usando Claude Code, recebemos uma abordagem “rápida e direta”: copiar as imagens para o diretório public/ no momento do build e substituir os caminhos dentro do Markdown. Claude até escreveu um plugin do Vite para isso.
Esse plano tinha vantagens:
- Autores dos slides não precisavam se preocupar com caminhos.
- Markdown e imagens podiam ficar juntos, facilitando a organização.
Assim colocamos a primeira versão no ar — não era perfeita, mas atendia ao básico.
Experimentando o Codex CLI para otimizar
Como um time que se importa com qualidade técnica, queríamos ir além da solução provisória.
O Astro já dispõe de um pipeline maduro de otimização de imagens (cache busting, conversão para WebP etc.), amplamente usado nos blogs. Queríamos que os slides também se beneficiassem disso — em outras palavras, torná-los verdadeiramente Astro native.
Conhecimento prévio essencial
Veja o processo de tratamento de imagens nos blogs. Suponha este Markdown:

Durante o build, o Astro gera algo como /_astro/imgs/example.abc123.webp. Se continuarmos usando o caminho original, a imagem deixará de aparecer.
Quando o Astro renderiza o Markdown por conta própria, ele já substitui os caminhos durante a compilação. Mas com o Reveal.js, não conseguimos usar a API de renderização do Astro, logo o problema reaparece.
Usando o Codex CLI para investigar
Na ocasião, o Codex CLI havia acabado de lançar uma versão elogiada pela comunidade, enquanto o Claude Code passava por restrições. Decidi experimentar o Codex para analisar e resolver o problema.
Já havíamos feito testes internos com o Codex. Um dos motivos para ele ser tão bem avaliado é a qualidade do código que gera, com pouca alucinação. Ele busca referências, inclusive dentro do repositório, lendo arquivos *.d.ts e fontes em node_modules/ para entender as bibliotecas — algo raro em outras ferramentas. Quando o orientamos a agir dessa forma, ele segue à risca, reduzindo drasticamente o risco de respostas fantasiosas.
Portanto, pedi explicitamente que analisasse o código-fonte e pesquisasse documentação e soluções na internet. O prompt foi, em essência:
... (trecho omitido descrevendo o estado atual do código e o problema) ...
Você precisa compreender bem o problema e detalhar possíveis soluções. Inclua, mas não se limite a:
- Analisar o código-fonte do Astro: como ele trata imagens? Há alguma API para obter a URL final?
- Consultar a documentação oficial em busca de pistas.
- Pesquisar na web por alguém que já tenha enfrentado e resolvido isso.
O Codex realmente fez uma investigação extensa e retornou, entre outros pontos, os seguintes destaques:
Conclusões principais
slide.body, emsrc/pages/slides/[...slug].astro, é passado como string paraSlideViewer, um componente React comclient:only="react". Assim, o Markdown é sempre processado no navegador, sem chance de o Astro/Vite substituir os caminhos das imagens (fonte indicada pelo Codex).- O
slideImagesPluginapenas copia as imagens parapublic/slides/**/imgs, conservando os caminhos originais e abrindo mão da otimização do Astro — exatamente a “solução provisória pouco elegante” (config/vite-plugin-slide-images.ts:1). - Nos blogs,
src/pages/blogs/[...slug].astro:27chamaconst { Content } = await render(post);, isto é, usa o pipeline do Astro, que reescreve os caminhos das imagens para/_astro/...(fonte indicada pelo Codex).
Três propostas apresentadas (trecho)
- A — Manter o pipeline do Astro: usar
import.meta.globcomeager: truepara carregar as instâncias de Markdown, chamarcompiledContent()e obter HTML já processado, dividindo em<section>antes de passar ao Reveal. Garante todo o benefício do Astro, mas exige dividir HTML em seções manualmente. - B — Gerar um mapa de imagens: com
import.meta.glob('/src/content/slides/**/imgs/*', { import: 'default', query: '?url', eager: true }), construir uma tabela “caminho original → URL final”, e substituir os caminhos no Markdown antes de entregá-lo ao Reveal. Menos intrusivo e respeita o fingerprinting do Astro. - C — Ajustar o pipeline de Markdown do Astro: criar um remark plugin que, ao encontrar imagens, use Vite para obter a URL final. É a abordagem mais próxima do “jeito Astro de ser”, porém a mais trabalhosa e com armadilhas em SSR.
A análise foi muito precisa e apontou bem as limitações da solução atual. Ainda assim, como todo bom usuário de IA, mantive meu senso crítico.
Minhas ponderações e testes
Nenhuma das três opções me agradou totalmente: ou eram pesadas demais, ou fugiam demais do que eu queria.
Pensei em trocar o SlideViewer (React) por um componente Astro para reaproveitar o pipeline nativo, mas o Codex argumentou que a migração seria complexa e não resolveria tudo.
Decidi então explorar por conta própria. Adicionei logs e descobri que o retorno de getEntry() traz metadados com os caminhos das imagens. Algo como:
{
headings: [
...
],
localImagePaths: [ './imgs/agents-md-ecosystem.png' ],
remoteImagePaths: [],
frontmatter: {
...
},
imagePaths: [ './imgs/agents-md-ecosystem.png' ]
}
Compartilhei esse achado com o Codex e pedi novas alternativas. Desta vez, ele sugeriu algo que me pareceu viável:
Solução 2: substituir os caminhos ainda no servidor
Usar importações eager do Vite para obter os caminhos finais das imagens e substituir os caminhos relativos do Markdown pelos URLs com hash antes de enviar o conteúdo ao Reveal. Assim, o Markdown já chega ao cliente referenciando /_astro/..., e as imagens são carregadas sem problema.
Essa proposta soou muito mais realista. Testei e funcionou; depois de ajustar o prompt, o Codex gerou código que obtém as URLs otimizadas pelo Astro (em WebP) e substitui apenas os caminhos necessários.
No total, foram cerca de duas horas de trabalho até chegar a uma solução elegante. O recurso de busca do Codex economizou um tempo enorme, evitando tentativas às cegas e me mantendo na direção certa.
Conclusão
O Codex é poderoso, mas sem alguém para direcionar e avaliar as respostas, é fácil acabar com algo simplista demais ou complicado demais. Com supervisão humana, porém, ele se mostrou um parceiro altamente eficiente — e o resultado final ficou “na medida certa”.