2.4 KiB
X Bookmarks → RSS
A tiny Hono app on Cloudflare Workers that turns your X (Twitter) bookmarks into a live RSS 2.0 feed. Uses the official X API v2 (OAuth 2.0 user context). State lives in a single D1 database.
Personal/single-user: the feed is unguarded (/feed.xml, no key). Bookmarks are stored in
D1 and accumulate, so tweets stay in your feed even after they scroll out of X's 100-item
bookmarks API window.
How it works
- There is no login route. You seed one OAuth2 refresh token into D1 once; from then on the app refreshes the access token itself on every sync (refresh tokens rotate and the new one is written straight back to D1).
GET /feed.xml— if the last sync is older thanSYNC_TTL_SECONDS, it refreshes the access token, pages through your bookmarks, and upserts them into D1; then it renders RSS from all stored rows (newest first). Sync failures are swallowed — the feed still serves what's already stored.
Setup
1. Create the D1 database
npm install
wrangler d1 create x-bookmarks-db # paste the printed database_id into wrangler.jsonc
npm run db:init # applies schema.sql to the remote DB
2. Set secrets (used to refresh the token)
wrangler secret put X_CLIENT_ID
wrangler secret put X_CLIENT_SECRET
SYNC_TTL_SECONDS (default 900) and MAX_ITEMS (default 100, items pulled per sync) are
plain vars in wrangler.jsonc.
3. Seed your refresh token
You need one OAuth2 refresh token with the tweet.read users.read bookmark.read offline.access scopes (this is the only step that requires a one-time authorization — every
sync afterward is automatic). Once you have it:
export X_CLIENT_ID=... # same values as the secrets above
export X_CLIENT_SECRET=...
scripts/seed-token.sh "<your-refresh-token>"
The script validates the token, captures the rotated token, and writes refresh_token +
user_id into the D1 meta table.
4. Deploy & subscribe
wrangler deploy
Add https://<your-worker>.workers.dev/feed.xml to your RSS reader.
Notes
- Refresh tokens rotate on every use and are written back to D1 immediately.
- If syncs start failing (token revoked), re-run
scripts/seed-token.shwith a fresh token. - The feed is unguarded by design (personal use). Don't host it where you'd mind it being readable, or re-add a key check.