Lazy Blogging with Telegram and Cloudflare Workers

  • 2 min read

I wanted to post to this blog from my phone without fighting a git workflow on Android. The solution I landed on was a Telegram bot that accepts a message and opens a GitHub draft PR containing the post, ready to merge from the GitHub mobile app.

Rationale

The standard Zola workflow — branch, write, commit, push, PR — is fine at a desk. On a phone it’s friction enough that posts don’t happen. The gap between thought and published needs to be close to zero, or the habit won’t stick.

The requirements were simple: no new third-party dependencies beyond what I already trusted, content lands in git immediately, and the publish step stays deliberate rather than automatic.

Tech choices

Telegram was the obvious input layer. Creating a bot takes about two minutes via BotFather, the Android app is excellent, and sending a message to a bot is as low-friction as it gets. The alternative was a secret-URL endpoint or email-to-draft, but Telegram felt more natural for the use case.

Cloudflare Workers handles the integration layer. I was already on Cloudflare for Pages, so a Worker is a natural extension — a small JS function that receives Telegram’s webhook POST, parses the message, calls the GitHub Contents API to create the file and branch, and opens a draft PR. No Actions required, no additional services.

The message format is minimal: first line is the title, subsequent lines are the body. The Worker slugifies the title, creates content/blog/{slug}/index.md with Zola front matter, and fires back a PR URL via Telegram.

Source is in the blog-bot repo.

Environment setup

Wrangler requires Node 16.17 or later. I used nvm to manage this:

nvm install 22
nvm use 22
npm install -g wrangler

Wrangler setup and deploy

Authenticate against your Cloudflare account:

wrangler login

Set the required secrets — Wrangler will prompt for each value:

wrangler secret put TELEGRAM_SECRET   # random string: openssl rand -hex 32
wrangler secret put TELEGRAM_TOKEN    # from BotFather
wrangler secret put GITHUB_TOKEN      # fine-grained PAT: contents + PRs write
wrangler secret put GITHUB_OWNER
wrangler secret put GITHUB_REPO

Deploy:

wrangler deploy

Then register the webhook with Telegram once, substituting your Worker URL and secrets:

curl "https://api.telegram.org/bot${TELEGRAM_TOKEN}/setWebhook" \
  -d "url=${WORKER_URL}/${TELEGRAM_SECRET}"

After that, messages sent to the bot create draft PRs. Merging from GitHub mobile or desktop triggers a Cloudflare Pages build in the usual way.