
The hardest part of building in public is not writing the update. It is remembering to write it. You ship something good, you mean to post about it, and three days later it is buried under the next thing.
So automate it. Make the act of shipping also be the act of announcing. Below are three setups, from the simplest to the most controlled. All of them use one OpenTweet API key, so there is no X developer account, no OAuth, and no per-post billing to deal with.
The whole trick: every setup ends in one HTTP request to OpenTweet, which posts to X for you. Connect X once, grab your key, and drop the call into whatever already runs when you deploy. Get your API key.
Setup 1: The deploy webhook (simplest)
If your host (Vercel, Netlify, Render, Railway, and most others) can fire a webhook or run a command on a successful deploy, you are one line away.
Add this to your post-deploy hook or script:
curl -X POST https://opentweet.io/api/v1/posts \
-H "Authorization: Bearer $OPENTWEET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Just shipped: faster search and a new dark mode. Live now.","publish_now":true}'
That is the entire integration. The deploy finishes, the hook fires, the tweet goes out. Store OPENTWEET_API_KEY as an environment variable so it never touches your repo.
Best for: solo devs and small teams who deploy from a host with hooks and want zero CI config.
Setup 2: The GitHub Actions step
If you want the tweet tied to your repo, run it from GitHub Actions on a tagged release or a push to main. Add your key as a repository secret (Settings > Secrets and variables > Actions), then add a step.
name: Tweet on release
on:
release:
types: [published]
jobs:
announce:
runs-on: ubuntu-latest
steps:
- name: Post release to X
run: |
curl -X POST https://opentweet.io/api/v1/posts \
-H "Authorization: Bearer ${{ secrets.OPENTWEET_API_KEY }}" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg t \"New release ${{ github.event.release.tag_name }}: ${{ github.event.release.name }}. ${{ github.event.release.html_url }}\" '{text:$t, publish_now:true}')"
Note that this runs on release: published, not on every commit, which keeps it from getting spammy. You can just as easily trigger on push to main and pull the message from the latest commit or your changelog.
Best for: teams who cut real releases and want the announcement to come straight from the tag and release notes. No Twitter-specific Action and no X API keys required.
Setup 3: The cron job (most control)
Sometimes you do not want to tweet the instant you ship. You want to collect what changed and post a clean summary at a good hour. Run a small script on a schedule (a cron job, a scheduled GitHub Action, or your backend) that reads your changelog and schedules the post.
# Runs daily. Reads today's changelog entry and schedules the announcement for 3pm.
SUMMARY=$(head -1 CHANGELOG_TODAY.md)
curl -X POST https://opentweet.io/api/v1/posts \
-H "Authorization: Bearer $OPENTWEET_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"text\":\"$SUMMARY\",\"scheduled_date\":\"$(date -u +%Y-%m-%d)T15:00:00Z\"}"
Using scheduled_date instead of publish_now lines the tweet up for when your audience is actually online, even if you shipped at 2am.
Best for: teams that ship often and want one considered daily update instead of a stream of deploy pings.
Which setup should you use?
| Setup | Effort | Fires on | Timing |
|---|---|---|---|
| Deploy webhook | One line | Every successful deploy | Immediate |
| GitHub Actions | One workflow step | Releases or merges to main | Immediate |
| Cron job | A small script | A schedule you set | Scheduled to a good hour |
You can also skip the code entirely. OpenTweet's connectors can watch a GitHub repo or an RSS feed and post updates automatically, no CI step to write.
Keep it from looking like a bot
Automation is only good if the output reads like a human wrote it:
- Gate the trigger. Tweet on tagged releases or merges to main, not every commit.
- Write from the release note, not the raw commit. "New release v2.1: faster search" beats "fix: bump deps."
- Let AI clean it up. OpenTweet can rewrite a terse changelog line into a proper build-in-public update that learns your voice.
The bottom line
Building in public compounds when it is consistent, and nothing is more consistent than a script. Pick the setup that matches how you ship: a webhook for one line, GitHub Actions to tie it to releases, or a cron job for a considered daily update. Each one is a single HTTP request, with no X developer account and a flat monthly price no matter how often you ship.
👉 Get your API key and add the call to your deploy step, or browse the connectors to do it with no code at all.
Start Scheduling Your X Posts Today
Join hundreds of creators using OpenTweet to stay consistent, save time, and grow their audience.