A theme in nature documentaries is that one creature’s death is new life for others.
I recently followed another dead-end Twitter link and realized anyone with a website could self-host their tweet archive and make them available however they want. I made a weekend project out of publishing mine.
They’re your words and they always were. Why not own where they live?
What if we all did?
I generated a Twitter account export in late 2022 just before I deleted it. I probably owe the ability to GDPR, and it was a convenient, simple thing to do. The archive is a ZIP file with a bunch of JavaScript, media assets, and a nice HTML page for browsing everything.
I opened the HTML page again and wondered what it would take to re-expose the internet to so many years of unnecessary thoughts.
It didn’t take much, and it was a great way to spend more time getting comfortable with TypeScript.1
I created a new .astro page on my site and used the twitter-archive-reader package to read the ZIP file and give back an archive class with everything parsed and ready to browse—including TypeScript definitions to make it fun.
You don’t need to use a library to do this, especially if you’re only after the tweets. (There’s much more in the archive!) Your ZIP file includes data/tweets.js, which is an almost a perfect JSON blob except for the very beginning:
Remove window.YTD.tweets.part0 = and you’ve got a stew going JSON you can import and play with.
It’s an array of objects that represent tweets. Here’s one I’ve purposefully selected because it has an image in it:
While the library was handy and simple to work with, it seemed excessive to commit the ZIP archive into my Astro project. I used the archive reader package temporarily to spit out JSON exactly how I wanted it.
Keeping a JSON blob around as a data source is better than a one-and-done HTML page because I can separate content from presentation with clean stylistic control, the ability to add stats or little features, and better odds of surviving a replatform or redesign.
The result for me is a directory of images and video attachments that came straight from the ZIP file (data/tweets_media/), along with my pared-down JSON where the same tweet looks like this:
I only a cheated a little bit with some in-between cleanup tasks:
Limited image and video references to those I actually have locally.
Pulled image and video references out of the tweet content and exclusively into a simpler media array.
Made up my own type property (tweet, retweet, or reply) for easier filtering.
Downloaded and replaced the handful of Twitpic images I had.
I’m loving TypeScript (with somebody else’s tsconfig.json), and my cleaned-up data uses these little types:
The page loads up the JSON, limits the data to tweets (no replies or retweets), and dumps out an obscenely-long pile of markup:
The Tweet component renders each random thought:
There’s plenty of room here to come back and add stuff like stats, filters, civilized lazyloading, and navigation. You could surely do something cooler!
That’s the point: you can do whatever you want when it’s your data.
Footnotes
I spent hours making a cleaned-up example repository for you, but couldn’t manage to configure TypeScript to run it with the handful of imports I used. If anybody can help me iron it out I’d be happy to publish a working example. (Everything ran in an Astro page just fine.) ↩