Update: Rendering Static Tweets
A few weeks ago, I wrote a post about rendering static tweets. I’ve made a few important improvements, worthy enough of a new post.
In my original post, I described using a proxy to inject Twitter API headers. This is hacky, and leads to flaky builds, because the build server needs to handle a NodeJS proxy running in the background1. I got this working on Vercel and Cloudflare Pages2, but there was no guarantee the build would pass, and I was constantly re-running failed builds. Neither fun nor productive. In the past few weeks I’ve wanted to remove this functionality from my blog because it’s made it more difficult to preview and deploy.
Last week I was reading Nicholas Whittaker’s blog, specifically a post he wrote about static embeds for tweets and videos (sounds familiar, right?). He’s using workers to handle some of the proxying, but notably, he’s not calling Twitter’s private API, which requires authentication, he’s calling a public one.
I had no idea https://cdn.syndication.twimg.com/
existed. It’s a completely open API you can use for fetching tweets, which means it’s perfect for static sites!
Try it out: curl "https://cdn.syndication.twimg.com/tweet?id=1406108535356678145"
Check out the updated shortcode here.
After some further sleuthing on Nicholas’ blog, I realised you can configure caches in Hugo. This means you can cache calls to getJson
, and push the cache to git. If a tweet ever gets deleted, as long as it exists in the cache3, I can continue rendering the tweet. Neat!
This sounds more complicated than it is. The Hugo shortcode makes a request to
localhost:8080/{tweetId}?auth={authToken}
, the proxy then callshttps://api.twitter.com/1.1/statuses/show?id=${tweetId}
with the same tweet ID and an authentication header. The proxy is on GitHub if you want to take a peek. ↩︎Here is what the build command looked like:
cd twitter-proxy && npm install && node index.js & sleep 5 && echo "Done" && hugo -t hello-friend --baseUrl=$BASE_URL --ignoreCache
↩︎Provided you’ve set
maxAge: -1
, so the cache is never purged. My config is here. ↩︎
On the web
📝 30 May 2025 at 21:25 - Going down a website rabbit hole is just the best...
Fri May 30 2025 by Kev QuirkVideogame Franchises 2
Thu May 29 2025 by joelchrono's websiteHow I Made Queuedle
Wed May 28 2025 by Andrew Healey's BlogConfiguring Jujutsu
Sat May 24 2025 by oppiliappan's μblogCommitting XML horrors to style my blogroll
Sat May 10 2025 by nicholas.cloud
Generated by openring