Building Vibecaster: AI Social Media Automation in Public

I built a thing. It's called Vibecaster, and it automatically generates and posts content to X/Twitter and LinkedIn using AI. But this post isn't really about the product—it's about the process. Building in public means showing the messy parts, so here's how it actually came together.

The Problem I Was Solving

I have opinions about observability, OpenTelemetry, and building things. I should probably share them more. But writing social media posts is tedious. Writing good social media posts that sound like me, reference current events, and include relevant images? That's a time sink I don't have.

So I did what any reasonable engineer would do: I spent way more time building automation than I would have spent just writing the posts manually.

The Architecture

Vibecaster runs on a simple stack:

  • Backend: Python/FastAPI running on a Hetzner VPS
  • Frontend: Next.js with a cyberpunk aesthetic (because why not)
  • AI: Google Gemini 3 Pro for everything—content generation, search grounding, image generation
  • Auth: OAuth 1.0a for Twitter, OAuth 2.0 for LinkedIn
  • Database: SQLite, because I'm not running a startup here

The core idea is simple: you write a prompt describing who you are and what you want to post about. The AI analyzes it, creates a "refined persona," and then uses that persona to generate content daily. It searches the web for recent news in your domain, writes posts in your voice, generates images to match, and posts them automatically.

Four Ways to Create Content

The app evolved into four distinct modes, each solving a different use case:

1. Campaign Mode (Fully Automatic)

Define your persona, set a schedule, Vibecaster posts daily. It uses Gemini's search grounding to find recent news, then generates posts that reference real, current content. No hallucinated URLs—everything gets verified.

2. URL Post Mode

Found an interesting article? Paste the URL, and Vibecaster generates platform-specific posts (280 chars for X, longer for LinkedIn) plus a matching image. Review, edit if needed, post with one click.

3. Post Builder (Chat Interface)

A multi-agent chat system. Have a conversation about what you want to post. The AI searches the web, proposes drafts, iterates based on feedback, generates images.

4. Transcribe Mode (New)

Upload an audio or video file. Gemini transcribes it, generates a summary, writes a blog post. No file storage—everything processes in memory and gets discarded. Built in a single session.

The Interesting Technical Bits

Search Grounding Without Hallucination

LLMs love to hallucinate URLs. They'll generate something that looks plausible—correct domain, reasonable path structure—but points to a 404. Vibecaster solves this by using Gemini's native search grounding, which returns actual search results with real URLs. Every link gets verified before posting.

Streaming Everything

Nobody wants to stare at a spinner for 30 seconds. All generation endpoints use Server-Sent Events (SSE) to stream progress in real-time. You see "Searching web... Found 5 results... Generating X post... Generating LinkedIn post... Creating image..." as it happens. Makes the AI feel responsive instead of mysterious.

Image Generation That Actually Works

Gemini 3's image generation is surprisingly good at creating social media graphics. The trick is giving it a consistent "visual style" prompt that matches your brand. Mine generates cyberpunk-themed images because that's the Vibecaster aesthetic. You can set your own style—"watercolor illustrations" or "minimalist line art" or whatever fits your brand.

Multi-User from Day One

Even though I built this for myself, I architected it for multiple users from the start. JWT auth, user-scoped database queries, isolated OAuth tokens. Partly because it's good practice, partly because I might let others use it someday.

What I Learned

Gemini 3 is multimodal. When I added video transcription, I expected it to extract the audio track. Instead, it understood the video—music, sound effects, visual context. It transcribed "[Angelic choir music plays]" for a test video. Whisper would have returned nothing.

OAuth is still painful. Twitter's OAuth 1.0a implementation requires cryptographic signatures that make you question your life choices. LinkedIn's OAuth 2.0 is cleaner but has its own quirks around token refresh. I spent more time debugging auth than building features.

SQLite is underrated. For a single-server application, SQLite is perfect. No connection pooling, no separate database server, instant backups (just copy the file). I'll migrate to Postgres if I ever need to scale horizontally, but that day isn't today.

Streaming UX matters. The gap between "wait 20 seconds" and "watch progress in real-time" is large. SSE is simple to implement and makes AI applications feel responsive.

What's Next

Vibecaster is running at vibecaster.ai. I use it daily for my own posting. The code lives on my server, not GitHub—not because it's secret, but because it's messy and I haven't cleaned it up for public consumption.

Future ideas floating around:

  • Analytics dashboard showing post performance
  • Multiple personas per account
  • Scheduled posts instead of just daily automation
  • Support for more platforms (Bluesky, Threads, Mastodon)

But honestly? It solves my problem. I have opinions about observability, and now they get shared without me having to context-switch into "social media mode" every day. That's the whole point.

Building in public means admitting that most projects exist to scratch a personal itch. This one scratches mine. If it scratches yours too, maybe I'll open it up someday. For now, it's just a thing I built because I could.