Recentemente, decidi que era hora de trazer meus artigos do LinkedIn para o meu blog pessoal, construído com Hugo. A ideia era simples: centralizar meu conteúdo e ter mais controle sobre ele. O que eu não esperava era o tamanho do desafio: 31 artigos para migrar, cada um com suas particularidades.
Neste artigo, vou compartilhar como enfrentei essa migração, as dificuldades que encontrei e como o gemini-cli
foi uma ferramenta fundamental para automatizar o processo e me poupar horas de trabalho manual.
Por que migrei do LinkedIn para o blog?#
A decisão de mover meus artigos do LinkedIn para o meu blog pessoal não foi por acaso. A comparação abaixo ilustra as principais razões para essa mudança:
Característica | LinkedIn Articles | Hugo + Blowfish (Blog Pessoal) |
---|---|---|
Formatação de Código | Desafiadora, frequentemente exige imagens. | Fácil, com destaque de sintaxe e importação de código. |
Organização de Artigos | Limitada (agrupamento, tags). | Robusta, com categorias, tags e séries. |
Controle de Aparência | Restrito. | Total, personalização completa do layout e estilo. |
Recursos Adicionais | Básico (likes, comentários). | Flexível (diagramas, gráficos, likes, comentários, etc.). |
Base Tecnológica | Plataforma proprietária. | Markdown, estático, leve e rápido. |
O desafio: 31 Artigos em HTML#
O primeiro grande obstáculo era o formato: artigos em HTML para um blog em Markdown. Além disso, enfrentei os seguintes problemas:
- Código como Imagem: Snippets de código estavam em imagens (via carbon), precisando ser extraídos, hospedados no GitHub e importados no Markdown para serem copiáveis.
- Download de Imagens: Imagens precisavam ser baixadas e organizadas na estrutura do Hugo, evitando dependência do LinkedIn.
- Metadados: Extração de título, data de criação e publicação para o front matter do Hugo.
Fazer tudo isso manualmente para 31 artigos seria um trabalho tedioso e propenso a erros. Foi aí que decidi criar um plano e pedir a ajuda do gemini-cli
.
Como criei o plano de migração#
Para garantir um processo consistente e automatizado, resolvi detalhar os passos no GEMINI.md
.
Este arquivo é utilizado pelo gemini-cli
como parte do próprio contexto.
E para detalhar o plano, primeiro fiz duas migrações de artigos, passo a passo com gemini-cli
.
Para cada passo feito com sucesso, eu pedia para o gemini-cli
documentar o passo feito no arquivo GEMINI.md
.
O plano resultante foi este:
- Ler o Conteúdo HTML
- Extrair Metadados
- Construir o Front Matter
- Converter HTML para Markdown
- Baixar as Imagens: Se a imagem continha código, extrair o código e inserir o código em um projeto separado.
- Gerenciar Contexto de Diretórios: Utilizar a capacidade do
gemini-cli
de adicionar diretórios ao contexto para gerenciar o projeto de exemplos de código (code-examples
) separadamente.
O Desafio Especial: Código em Imagens#
A parte mais interessante do processo foi lidar com os snippets de código que estavam em formato de imagem. Para resolver isso, fui atrás de uma ferramenta que realizava OCR.
E a partir desta ferramenta, pedi simplesmente pro gemini-cli
utilizá-lo para extrair textos de imagens.
O passo a passo desta etapa ficou assim:
- OCR (Reconhecimento Óptico de Caracteres): Usar o Tesseract OCR para extrair o texto de cada imagem de código.
- Limpeza e Formatação: O texto extraído pelo OCR nem sempre é perfeito. Era preciso revisar, corrigir erros e formatar o código corretamente.
- Hospedagem do Código: Para manter o código organizado e reutilizável, criei um projeto separado no GitHub (
code-examples
) para hospedar todos os snippets de código. - Usar o
codeimporter
: Finalmente, no arquivo Markdown do post, em vez de um bloco de código, eu usaria o shortcodecodeimporter
do tema Blowfish para importar o código diretamente do repositório no GitHub.
Resultado final do GEMINI.md#
Esse arquivo foi gerado pelo gemini-cli
iterativamente:
## Use shortcode where possible
- **Available Shortcode** https://blowfish.page/docs/shortcodes/
## Agent Instructions
- **Check URLs:** Always check any URLs provided within this `GEMINI.md` file for additional context, documentation, or specific instructions relevant to the task.
- **Delete after review:** After the user reviews and approves an article migration, delete the original HTML file.
### Article Migration Process
To migrate an article from an HTML file (e.g., from `linkedin-articles/Articles/`) to a Hugo Markdown post (`content/posts/`):
1. **Read Full HTML Content:** Use `run_shell_command` with `cat` to read the _entire_ HTML file content.
- Example: `cat /path/to/article.html`
2. **Extract Metadata:**
- **Title:** From `<title>` tag or `<h1>` tag.
- **Created Date:** From `<p class="created">` (format `YYYY-MM-DD`).
- **Published Date (lastmod):** From `<p class="published">` (format `YYYY-MM-DD`). If not available, use the created date.
- **Categories/Tags:** Infer from the article content.
3. **Construct Front Matter:** Create a minimal YAML front matter block:
```yaml
---
title: "Extracted Title"
date: YYYY-MM-DD (Created Date)
lastmod: YYYY-MM-DD (Published Date or Created Date)
categories: ["Category1", "Category2"]
draft: false
---
```
4. **Download Images:** For each `<img>` tag, download the image to the post folder. **Do not download the featured image.**
- Example: `curl -o /path/to/post/image1.png "image_url"`
5. **Convert HTML Body to Markdown:**
- Exclude any "Axuda-me DEV!" or "Axuda-me QA!" series logos/descriptions.
- Convert `<h1>` to `#`, `<h2>` to `##`, `<h3>` to `###`.
- Convert `<p>` to paragraphs.
- Convert `<ul>`, `<li>` to Markdown lists.
- Convert `<blockquote>` to Markdown blockquotes.
- Convert `<hr>` to `---`.
- Convert `<a>` to `[link text](url)`.
- Handle `<pre>` tags: If they contain code, wrap them in ` ```language` (e.g., ` ```gherkin`). If empty, remove them.
- Images: Convert `<img>` tags to `< figure src="image.png" alt="Alt text" caption="Caption text" >`. If an image contains code, follow the process in the **Code Snippet Management for Articles** section.
6. **Create New Post File:**
- Determine a slugified folder name from the title (e.g., "My Article Title" -> `my-article-title`).
- Create the file at `content/posts/slugified-title/index.md`.
7. **Write Content:** Write the constructed front matter followed by the converted Markdown content to the new file.
8. **Review and Refine:** Manually review the generated Markdown for any conversion errors or formatting issues.
### Code Snippet Management for Articles
When an article contains code snippets embedded in images, follow these steps to extract, organize, and display them using the `codeimporter` shortcode:
0. **Detect if the image is a code snippet**
1. **Extract Code from Images (OCR):**
- Use Tesseract OCR to extract text from the image files.
- Example: `tesseract /path/to/image.png stdout`
2. **Clean and Format Extracted Code:**
- Review the Tesseract output and manually clean any artifacts (e.g., line numbers, OCR errors, incorrect characters).
- Correct syntax, add necessary imports, and ensure proper indentation.
3. **Organize Code in a Separate Project:**
- Create a dedicated project (e.g., `code-examples`) to host the code snippets.
- Within this project, create a package structure that reflects the article's date and the image number for each code snippet.
- Example package structure: `br.com.youready.article.d_YYYY_MM_DD.imageN`
- Ensure the package declaration in each Java/Groovy file matches its directory structure.
- Set class visibility: The main class (e.g., `OrderProcessor`, `OrderSpec`) that will be directly imported should be `public`. Helper classes (e.g., `Order`, `Item`) used only within that specific snippet's context should be package-private (remove the `public` keyword).
4. **Host the Code:**
- Push the `code-examples` project to a public repository (e.g., GitHub).
- Obtain the raw URL for each code file.
5. **Update Hugo Article (`index.md`):**
- In the `content/posts/your-article/index.md` file, replace the `figure` shortcode (or any direct code block) with the Blowfish `codeimporter` shortcode.
- Use the raw URL of the hosted code file and specify the language type.
Minha opinião sincera sobre o uso do gemini-cli#
Com o plano detalhado no GEMINI.md
, eu pude instruir o gemini-cli
a executar cada uma dessas etapas.
Mesmo que eu perdesse o contexto após horas de uso, era fácil de recomeçar.
Ele leu o arquivo de instruções e começou a trabalhar, migrando um artigo de cada vez.
O gemini-cli
foi capaz de ler os arquivos HTML, extrair os metadados, baixar as imagens, converter o conteúdo para Markdown e até mesmo orquestrar o processo de OCR para os snippets de código.
Claro, o processo não foi 100% automático. Eu precisei revisar cada artigo migrado para garantir que a formatação estivesse correta e que o código extraído pelo OCR estivesse limpo. Mas a maior parte do trabalho pesado foi feita pelo gemini-cli
, o que me economizou um tempo enorme.
Algumas das falhas que encontrei na migração:
- Depois de um tempo, o
gemini-cli
não realizava as etapas com eficiência. - Algumas vezes, mesmo com o passo a passo detalhado, o
gemini-cli
realizava ações diferenciadas. Por exemplo, algumas imagens com código foram ignoradas completamente. - Algumas vezes, o
gemini-cli
travava. Não sei a razão. - Algumas vezes, o
gemini-cli
achava que estava em looping e parava de realizar a tarefa. Isso é legal por um lado, pois tem uma detecção de looping, mas ruim por outro lado quando você sabe que a tarefa é demorada.
Algumas dicas que funcionaram bem:
- Sempre passar um exemplo! Elimina um pouco da ambiguidade que surge em comunicação com linguagem natural.
- A cada nova alteração de sucesso, criar um commit no git! Pois é muito mais fácil e garantido reverter em um cenário anterior com git do que pedir para o
gemini-cli
reverter as alterações. - Zerar o contexto. Contexto poluído ou que está em uso por um bom tempo, gera comportamentos inesperados nesta minha experiência.
Para migrar 31 artigos, levei +- 7h!
- 1 hora para migrar dois artigos passo a passo. (Sem imagem com código)
- 1 hora para migrar dois artigos passo a passo. (Imagem com código)
- 1 hora para instruir a criação do código, limpeza e commit em um projeto novo.
- 2 horas para o gemini-cli migrar 31 artigos. (Com erros e com alguns problemas de travamento)
- 2 horas para revisar e arrumar os pequenos problemas. (Os 31 artigos e códigos que não foram extraídos de forma correta)
Ferramentas Utilizadas#
- Hugo: https://gohugo.io/
- Blowfish Theme: https://blowfish.page/
- Gemini CLI: https://ai.google.dev/docs/gemini_api_overview
- Tesseract OCR: https://github.com/tesseract-ocr/tessdoc
Conclusão#
Migrar 31 artigos do LinkedIn para o meu blog foi uma oportunidade incrível para aprender a automatizar tarefas complexas com a ajuda de uma ferramenta como o gemini-cli
.
Ao criar um plano detalhado e delegar a execução, consegui transformar um trabalho que poderia levar dias em um processo gerenciável, muito mais rápido e principalmente divertido!
Agora, todos os meus artigos estão centralizados, em um formato que eu controlo e que é muito mais flexível para o futuro.
🥒🥒 Espero que tenham curtido e até o próximo artigo! 🥒🥒