Pivoting to Gemini: A Journey in Automating Blog Updates with AI

By Arrhen Knight | Published on

Hey there, welcome back to arrhen.me! After sharing my experiences with a sci-fi game and a data management experiment, I’m diving into another chapter of my AI-assisted journey—this time focusing on a personal script I wrote to automate blog updates for this site. Initially, I tried using my xAI API key with Windsurf IDE, but I ran into constant roadblocks. After much trial and error, I pivoted to using Google’s Gemini API with Cursor and autogen, and the difference was night and day. Let’s explore how this script came together as a hobby project, the challenges I faced, and why Gemini became my go-to for this task.

The Goal: Streamlining Blog Updates

As my personal site grows, manually updating blog posts has become a chore. I wanted a script that could take a plain text file from my docs/posts_input/ folder, generate a new blog post HTML file (e.g., post3.html), and update my blog.html landing page—all with minimal effort. The script needed to:

  • Find the latest post content.
  • Generate a new post number based on existing files.
  • Use a template (post1.html) to create the new post.
  • Update the blog index with a new entry.
  • Move the processed input file to a posts_processed/ folder.

I initially thought xAI’s Grok API, paired with Windsurf IDE, would be the perfect fit—after all, I’d used Grok successfully for a previous hobby project. But things didn’t go as planned.

The xAI/Windsurf Struggle

I started by trying to integrate xAI’s Grok API with Windsurf IDE, hoping its seamless VS Code integration would make prompt engineering a breeze for this personal experiment. I set up my API key (which I’d previously configured using export XAI_API_KEY="your-api-key-here" in my macOS Terminal, as I’d done for other projects). But every time I ran the script, I hit a wall—either a 404 error for an incorrect endpoint or a 401 Unauthorized error. I spent hours debugging, checking my key with printenv XAI_API_KEY, and even testing the endpoint directly with curl, but nothing worked consistently.

The frustration peaked when Windsurf’s prompt suggestions kept generating incompatible code for Grok’s API. I’d ask for a simple chat completions call, but the generated code would either use the wrong endpoint or fail to handle the response format. It felt like I was fighting the tool more than building with it. After countless retries, I decided to pivot.

Pivoting to Gemini with Cursor and Autogen

I’d had success with Google’s Gemini API in a previous personal project, and I remembered how Cursor and autogen made prompt engineering much smoother. So, I rewrote the script to use Gemini’s API instead, leveraging the google-generativeai package. The difference was immediate—Cursor’s interface made it easier to craft precise prompts, and autogen helped manage the API interactions seamlessly for this hobby script.

Here’s how the script works now:

  • Find the Latest Post: It scans docs/posts_input/ for the most recent .txt file, using glob and os.path.getmtime to sort by modification time.
  • Generate a Post Number: It checks existing files in arrhendotme/blog/ to determine the next post number (e.g., if post1.html and post2.html exist, the next is post3.html).
  • Call Gemini API: It sends the post content and templates (post1.html, blog.html) to Gemini, asking for updated HTML in a JSON response with post_html and blog_html keys.
  • Validate and Write: It validates the HTML using lxml, writes the new post to arrhendotme/blog/, updates blog.html, and moves the input file to posts_processed/.

The script’s prompt for Gemini is detailed, ensuring the response is a valid JSON object with escaped HTML content. I even added retry logic with exponential backoff to handle API hiccups, a trick I learned from past hobby projects.

Switching to Gemini and Cursor was like flipping a switch—everything just clicked. The API calls worked on the first try, and I could focus on building instead of debugging.

Challenges and Lessons Learned

The pivot wasn’t without its hurdles. Gemini’s safety settings occasionally blocked requests if the content seemed too complex, so I had to fine-tune the safety_settings to balance reliability and flexibility. Also, parsing Gemini’s response required careful handling—sometimes it wrapped the JSON in Markdown code fences (```json), which I had to strip out to avoid JSON parsing errors.

One big lesson was the importance of prompt engineering. With Cursor, I could iterate quickly, using prompts like: “Generate a JSON object with ‘post_html’ and ‘blog_html’ keys, ensuring all HTML newlines are escaped as ‘\\n’.” This precision was harder to achieve in Windsurf, where I often got generic or incorrect code.

Looking Ahead

This script has streamlined my personal blogging process, and I’m thrilled with how Gemini, Cursor, and autogen came together to make it happen as a hobby project. My next step is to add image generation for blog headers, similar to what I did for a previous experiment—I’ll likely use Gemini’s image generation capabilities for that. For now, I’m just happy to have a reliable way to keep arrhen.me updated with fresh content. Stay tuned for more adventures in AI-driven personal projects!