cd /news/developer-tools/i-just-wanted-a-whatsapp-channel-tha… · home topics developer-tools article
[ARTICLE · art-98465] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

I Just Wanted a WhatsApp Channel That Teaches Me One German Word a Day. It Took a Week and a Git History Rewrite.

A developer spent a week building a WhatsApp Channel that posts one German word daily, encountering deployment hurdles with session management and hosting platform restrictions. The project ultimately switched to the Baileys library, which uses WhatsApp's multi-device protocol over WebSocket, reducing session size and enabling a GitHub Actions cron job for free hosting. The developer also had to rewrite git history to remove accidentally committed session credentials.

read5 min views1 publishedAug 16, 2026

I wanted something dumb simple - a WhatsApp Channel that posts one German word every morning, A1 level, with an example sentence and a mnemonic. Gemini can write that in a second. The actual project turned out to be an argument with WhatsApp's session model, two hosting platforms, and, at one point, my own repo's git history.

whatsapp-web.js

is the library most people reach for first. It drives a real headless Chrome instance that logs into web.whatsapp.com like your browser would, and it works - locally. The moment you try to deploy it, you hit the same wall everyone hits: the session it needs to stay logged in is a full Chromium profile. Cookies, IndexedDB, cache, the works. Mine was 43MB.

GitHub Secrets cap out in the kilobytes. So the "obvious" fix - the one a dozen tutorials suggest - is: tar it, base64-encode it, shove it into a secret anyway, decode it back into place on every CI run. I actually did this. I had a script called setup.ts

whose entire job was printing a giant base64 blob for me to paste into GitHub's secret editor by hand.

It's exactly as bad as it sounds, and it doesn't even solve the real problem, because that session expires. Not on a schedule you control — whenever WhatsApp feels like it. Phone offline too long, and it's gone. Which means eventually you're back to scanning a QR code, except now you're doing it on a server that has no screen.

This is the question I actually came in asking, because I genuinely didn't know. Turns out there are two real answers:

Neither needs a screen physically attached to the server. I'd been overcomplicating this in my head for no reason.

I had this deployed in three places at once - Railway, Render, GitHub — and none of them worked, and I couldn't figure out why. Turns out Railway's fair-use policy explicitly bans "userbots": anything that logs into a personal account via an unofficial, reverse-engineered protocol instead of a real bot API. whatsapp-web.js

is precisely that. It's not a bug I could fix. It's a platform I had to stop using for this.

Render fared a little better, but I kept hitting a different, more annoying issue: RemoteAuth

with a Mongo-backed session store has open, unresolved GitHub issues where the session saves fine but doesn't reliably restore — silently forcing a fresh QR scan on restart. Not something I broke. Just a library with rough edges.

The fix that actually stuck was switching libraries entirely, to Baileys. It speaks WhatsApp's multi-device protocol directly over a WebSocket. No Chromium, no Puppeteer, nothing to render. The session is a handful of small JSON credential files — kilobytes, not tens of megabytes.

That one change collapsed two separate problems at once. The session fits anywhere now — I put it in a free MongoDB Atlas cluster instead of a secret. And without a browser to spin up, the whole thing runs fine on a constrained free-tier box instead of choking on headless-Chrome memory pressure.

It also made the hosting question moot. My actual requirement was "post one message a day," which doesn't need an always-on server at all — it needs about sixty seconds of compute, once every 24 hours. That's a GitHub Actions cron job, for free. I deleted the Dockerfile, deleted Render, deleted Railway, and the whole deployment surface became one YAML file with a cron:

line in it.

Somewhere in the earlier, messier phase, I had committed a full .wwebjs_auth

session folder straight into git — 204 files - plus a couple of standalone tar/base64 dumps of the same thing, at 27MB and 41MB. That's not hypothetical risk. That folder is an active login session. Anyone who could read that repo could have hijacked my WhatsApp account with it.

Deleting the files from the working tree isn't enough — they're still sitting in every earlier commit, recoverable by anyone who clones the repo. Fixing it for real meant git filter-repo

to strip those paths out of the entire history, followed by a force-push. My .git

folder went from 84MB to 284KB in about a second. If you've ever committed something you regret, this is the actual fix — not git rm

, the history itself has to go.

I only caught this because I asked for a full audit before making the repo public. Worth doing that even if you're sure you didn't leak anything. I was sure. I was wrong.

Google deprecates old models and its numbers so fast the issue isn't "use the newest model," it's "never hardcode one." I wrote a small fallback chain — try the latest Flash model, and on a 404, 429, or 503, fall through to the next one down the list automatically. I know it works because I watched it happen live: the newest model 3.7 hit a genuine 503 Service Unavailable

mid-run, fell through to the one behind it, and posted anyway without me touching anything.

One GitHub Actions workflow, triggered on a cron schedule. It pulls a WhatsApp session out of a free MongoDB cluster, asks Gemini for a word it hasn't used yet, posts it to the channel, and writes the updated state back to Mongo. No server. No Docker image. No monthly bill. The entire compute cost is about a minute of free CI time a day.

The message itself ended up plainer than I expected too — I started with a version stuffed with emoji and flag icons and a line advertising DM commands, and once I actually deleted the interactive bot half of the project, that line was just false advertising to a channel with nobody listening on the other end. It reads like a dictionary entry now. Word, pronunciation, meaning, an example sentence, a note. That turned out to be the right call anyway — it's a vocabulary channel, not a chat app.

If you're building anything that automates a personal WhatsApp account: expect the session/auth layer to be the actual project, and the thing you originally wanted to build to be the easy 10%.

Checkout the [WhatsApp channel](https://whatsapp.com/channel/0029VbDR5d3LNSaB3gXAaI3V) and my [Github repo](https://github.com/btkcodedev/whatsapp-german)

Thanks for reading!

── more in #developer-tools 4 stories · sorted by recency
── more on @whatsapp 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-just-wanted-a-what…] indexed:0 read:5min 2026-08-16 ·