BaitJar
BaitJar helps B2B marketing teams generate lead magnets and one-time offer products for their campaigns — it analyses trending topics in their niche and produces professional, brand-matched PDFs ready to download in under 15 minutes.
It takes days or even weeks for marketing teams to build products for their campaigns; research what the audience wants, write something worth gating, design it to match the brand, and render a final PDF.
The pipeline analyzes the brand from a URL, researches trending topics, generates strategic angles, produces chapter content, renders into a branded template, and exports as PDF. Every LLM call returns structured output (Vercel AI SDK + Zod) — each step feeds typed JSON into the next, no parsing, no guessing. It batches chapters 3-4 at a time for speed and routes between LLM for analysis and LLM for content to keep costs tight.
I split the deployment across Vercel and Cloudflare, and that was a deliberate choice. Next.js runs on Vercel for the UI and auth, but the generation pipeline lives on Cloudflare Workers, because it gives durable, resumable execution with per-step retries. If the LLM call succeeds but PDF rendering fails, the workflow picks up from the rendering step instead of re-running everything.
Browser → Vercel (Next.js) → Supabase (auth, data)
→ CF Worker (generation)
CF Worker → Supabase (results)
→ R2 (PDFs, assets)
→ Browser Rendering (PDF gen)
→ AI SDK → OpenAI / OpenRouter
The hardest part was templates. I collaborated with a graphic designer on four document styles — and then had to make the same HTML templates render as cover thumbnails in the direction picker, live previews in the editor, and final PDFs via headless Chromium, all with live brand customization (colors, logo, fonts). Great collaboration, tricky engineering.
Built on Next.js 16, Cloudflare Workers + Hono, Supabase (auth + DB), Cloudflare R2 + Browser Rendering, Vercel AI SDK, Zod, and Paddle for payments.
What I keep thinking about is where this goes next. Until now, we’ve been building apps for users — people clicking through dashboards, filling out forms. But increasingly, we should be building for agents acting on behalf of those users. BaitJar should have an MCP server so any AI agent can just call “generate a lead magnet about X for this audience” — no dashboard, no clicks, just a tool call. That shift is already starting, and I think it’s going to change how we build everything.