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, usingglob
andos.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., ifpost1.html
andpost2.html
exist, the next ispost3.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 withpost_html
andblog_html
keys. - Validate and Write: It validates the HTML using
lxml
, writes the new post toarrhendotme/blog/
, updatesblog.html
, and moves the input file toposts_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!