An MCP server for your agents, a content API and Next.js package for your site, a first-party attribution script, and webhooks for what happens in your repo and your product. Every door leads into the same loop, and the same review gate.
Ballad is an MCP server. Add it to Claude as a connector, sign in with Ballad, and choose on a consent screen what it may do. Then ask Claude for a draft, a launch week, a plan change or this week's numbers, and it happens inside the same loop, with the same review gate.
read See drafts, lanes, plan, eventsdraft Start generation and submit draftspropose Propose plan changes for you to approvedecide Approve one-tap drafts, undo, set cadencepublish Mark posts as postedsignals Record metrics for published piecesEverything long-form is served by a typed, read-only content API and rendered by your site, under your design and your URLs. For Next.js, @balladlabs/next does the pages, metadata, feed, sitemap and refresh-on-publish in a few lines; anything else can use REST or RSS.
import { createBallad } from "@balladlabs/next"; import { createBlogPages } from "@balladlabs/next/pages"; export const ballad = createBallad({ apiKey: process.env.BALLAD_CONTENT_KEY, }); // one lane per collection, each with its own path export const changelog = createBlogPages(ballad, { basePath: "/changelog", collection: "changelog", });
A small first-party script, as a tag or an npm package with a React component. It keeps how a visitor first arrived in their own browser, reports conversions with the properties and account you pass, and hands its record to your server when the signup happens there.
import { group, touches, track } from "@balladlabs/beacon"; track("signup", { email }, { plan: "trial" }); group(workspace.id, { name: workspace.name, seats: 4 }); // signing up on your server? send the touch along await fetch("/api/signup", { method: "POST", body: JSON.stringify({ email, touches: touches() }), });
Some of the best marketing inputs never pass through a browser. Point GitHub at Ballad and every release or push becomes changelog material; report product events and imports from your server, and they land on the same People record the script writes to.
# GitHub → Settings → Webhooks → release events POST /api/webhooks/releases/prod_9f2c… { "action": "published", "release": { "tag_name": "v2.4.0", "name": "Undo a pay run", "body": "- 24-hour undo window…" } } # → 202, a minor release; the changelog entry is drafted
Connect what you already use in Settings. Where Ballad doesn't post for you, it hands you the post ready to go and asks for the numbers afterwards.
The same loop, read through the job a marketing team would split it into. Each page covers the parts of Ballad that do that job.