Running Pokemon Red on my GitHub Profile
In this post, I’ll explain how I got Pokemon Red running on my GitHub profile a couple years ago. Check it out in action here!
Background
GitHub profiles display a README.md file that lives in a special repo on your GitHub account. This allows you to customize your profile with rich content including text, images, and links. There’s just one problem: these markdown files are static and therefore boring. You can’t run javascript for example, so you’re pretty limited in the experiences you can offer. How can we leverage these static primitives to emulate Pokemon in real time?
One way you can work around the static nature of a markdown file is to link to images that are hosted on a web server which will dynamically change the image it sends back for each request. This is how some GitHub profiles contain up-to-date information about “stars over time” and other account metrics. We’ll put a spin on this idea to create an illusion of an interactive Pokemon emulator.
Setup (in words)
The Pokemon README.md seen above contains only:
- A link to a gif hosted on an external server (
pokemon.farlow.dev/game
) - Some button emojis which are links to that same web server (
pokemon.farlow.dev/input/UP
)
When the profile is accessed, the gif will be fetched and will display the most up-to-date game state. When a button is pressed, it will redirect the browser to the web server, advancing the game to create a new gif, then the browser will be redirected back to the GitHub profile, causing the gif to be re-fetched, now displaying the updated game state.
All these redirects sound pretty disruptive in theory, but in practice, somehow it all works with only a slight flicker of the page. This setup does imply that everyone views and plays the same instance of Pokemon. That’s a feature, not a bug, of course.
Setup (diagram)
Proxying and Caching
Something to be aware of is that GitHub will proxy the traffic to your web
server when fetching images. I wonder if this has to do with protecting privacy
of GitHub users so as to not leak their IPs when they visit profiles?
Thankfully, the proxy respects the Cache-Control
header that we set in our gif
response and will happily re-fetch the image on every profile load. I didn’t
look into it, but it would be interesting to find out if you could identify
unique sessions in order to serve users separate game instances.
Conclusion
Full source can be found here. Thanks arxenix for writing the initial implementation! I think this trick is best suited to turn based games, but at this point, there’s nothing stopping us from running Doom on a GitHub profile :) I hope this was interesting; thanks for reading!