
Show HN: My GitHub Readme Is Interactive - eat_veggies
https://github.com/veggiedefender/typing
======
eat_veggies
Also check out my GitHub webring! Building the markdown widget for it [0]
inspired this project.

[https://octo-ring.com/](https://octo-ring.com/)

[0] [https://github.com/veggiedefender](https://github.com/veggiedefender)

~~~
searchableguy
I love the style of the site. It doesn't look prehistoric but also doesn't
have that modern corporate feel to it. Just balanced! Lovely illustrations,
did you make them yourself?

~~~
eat_veggies
Yes, I made them in MS Paint!

~~~
timwis
Hahaha that made my day

------
jkeat
With so many people entering characters right now, it’s only a matter of time
til we get some Shakespeare

~~~
why-el
I suppose this is an ode to the famous "enough monkeys will write Hamlet?"[1]
:p

[1]
[https://en.wikipedia.org/wiki/Infinite_monkey_theorem](https://en.wikipedia.org/wiki/Infinite_monkey_theorem)

~~~
lioeters
There's a section in the linked Wikipedia article that describes Jorge Luis
Borges tracing the origin of the concept back to Aristotle's Metaphysics.

That's the best thing I've read today. I've often heard the monkeys-on-
typewriters imagery, but never related it to an idea of a "total library"
which contains everything that can ever be written, probably even itself. I
suppose the digits of Pi may be considered such a "library".

"Strictly speaking, one immortal monkey would suffice."

~~~
srtjstjsj
The "total" library (which is mathematically paradoxical) can't contain itself
because it has higher cardinality than any of its contents.

~~~
lioeters
When I wrote that a total library would contain "probably even itself", I had
a nagging feeling that may lead to a contradiction.

Here is the essay "Total Library" by Borges:

[https://www.gwern.net/docs/borges/1939-borges-
thetotallibrar...](https://www.gwern.net/docs/borges/1939-borges-
thetotallibrary.pdf) (PDF)

It mentions "abnormal transfinite numbers (whose parts are no smaller than the
whole)". This seems to be a reference to Russell's Paradox:

[https://en.wikipedia.org/wiki/Russell's_paradox](https://en.wikipedia.org/wiki/Russell's_paradox)

> Let us call a set "normal" if it is not a member of itself, and "abnormal"
> if it is a member of itself.

> Now we consider the set of all normal sets, R, and try to determine whether
> R is normal or abnormal. If R were normal, it would be contained in the set
> of all normal sets (itself), and therefore be abnormal; on the other hand if
> R were abnormal, it would not be contained in the set of all normal sets
> (itself), and therefore be normal.

> This leads to the conclusion that R is neither normal nor abnormal:
> Russell's paradox.

That proves your point, that it's a mathematical impossibility.

Borges calls it "the vast, _contradictory_ Library", so clearly he was aware
of this fact.

~~~
gwern
Borges's library can't contain itself because it is of a strictly finite size:
the books are only 410 pages, or whatever, and so while astronomically large,
the total number of sequences is finite. His point was that for any sub-book-
sized claim, there would be another book contradicting it, if only through
prefixing "it is not true that" or something.

His Book of Sand would, however, appear to be vulnerable to diagonalization.

------
can16358p
It doesn't appear to work for me. I tap a letter but it refreshes the page,
goes to top, with no letter appended. Cool idea though, would love to see it
working.

~~~
eat_veggies
Sorry about that. I misconfigured a caching header some time last night before
I went to bed. Should hopefully be working normally again

~~~
dominotw
still not working for me. It refreshes the page with some random word appended
when i click on a letteer.

------
hombre_fatal
How can this work on Github when Github's image proxy has a 4-hour cache?

It's frozen in time and can never be updated as fast as this
([https://kbd.jse.li/screen.gif](https://kbd.jse.li/screen.gif)), afaict,
without making commits that repeatedly update the readme image url to bust
cache.

So how is it working for people ITT?

~~~
srtjstjsj
Apparently it's possible to bust the cache.

[https://github.com/veggiedefender/typing/blob/master/handler...](https://github.com/veggiedefender/typing/blob/master/handler.go)

------
judge2020
OP: You might want to add some basic rate limiting in the range of 3+ clicks
per second. Currently you can flood the http endpoints to spam a single action
(like backspace). Given GitHub's TTFB of 700ms for this page, I don't see how
a regular person could type anything quicker than that, unless they had
multiple tabs open.

~~~
eat_veggies
It's alright! If I see worse backspace abuse I'll disable it, but scripting is
part of the fun :)

~~~
searchableguy
I am curious how many requests are you receiving at the moment. I can't even
see the text because it seems to be moving too fast.

~~~
eat_veggies
About 20 button presses per second, which honestly is not that bad.

~~~
kang
It's a script pressing the buttons cause the text has a pattern. Humans cannot
use this demo at this moment.

------
eat_veggies
apologies, my seriously unoptimized rendering routine is choking under the
load. I'm restarting every few seconds to clear the screen...

edit: renders PNG instead of GIF (no more fancy blinking animation) to lighten
the load a little. This thing is running on a $5 digitalocean droplet and
performing admirably!

------
aaronjanse
Oh wow, this is quite clever. This is hacking in its pure, positive form. I
love it.

I wonder what the README will say once the firehose of Hacker News slows down.

~~~
cogburnd02
[https://i.redd.it/agcbmqgjn14z.png](https://i.redd.it/agcbmqgjn14z.png)

~~~
newyorker2
ahh yes, theplace! IMHO the last bastion of reddit's old school leanings
before they adopted the path to please investers over users.

------
Tade0
Reminds me of Twitch Plays Pokémon[0].

[0]
[https://en.wikipedia.org/wiki/Twitch_Plays_Pok%C3%A9mon](https://en.wikipedia.org/wiki/Twitch_Plays_Pok%C3%A9mon)

~~~
mrosett
"HN writes a Readme"

------
tombert
I love this. I think there's something beautiful about making software just
because it's a fun to do; not trying to change the world, but just thinking it
would be funny to have a publicly interactive readme.

You have my respect!

------
colordrops
Doesn't work on mobile if you've got the GitHub app installed.

------
djsumdog
Interesting that it's implemented via a table with all the image keys and
individual links.

Seems like a better implementation for this would be an image map, although
I'm not sure how well those are supported in modern browsers, or if you could
implement them in a github readme.

~~~
eat_veggies
That would definitely be better, but GitHub has an extremely aggressive
allowlist of tags and attributes which preclude styles, image maps, and
regular buttons

~~~
saagarjha
You can do some very basic styling.

------
buffington
While you added rate limiting, it looks like you might have only done it for
`RemoteAddr`. If I set random `X-Forwarded-For` and `X-Real-IP` I seems to let
me post as quickly as I'd like.

That allowed me to send 200 backspaces, then fill the page with "i like
turtles" or just the letter "o".

That said, there's a backup rate limiter working for you. Github.

Github has blocked my IP because of my shenanigans, which I suppose is fair.
I'd have created an issue there if not for that.

------
echelon
Way back when forums were a thing and all the kids had obnoxious photoshop
"signatures" with their favorite anime characters and video games, I made a
dynamic forum signature image that let people type messages.

I used to use variations of that "interactive" signature theme. Random
redirects that showed different anime images. IP addresses. (Which was later a
service that someone built and provided to everyone.)

I remember using this on Warp Pipe, the GameCube online tunnelling software
forums.

[https://web.archive.org/web/20041231055055/http://www.warppi...](https://web.archive.org/web/20041231055055/http://www.warppipe.com/)

[https://web.archive.org/web/20060204011647/http://forums.war...](https://web.archive.org/web/20060204011647/http://forums.warppipe.com/viewforum.php?f=23&sid=07fb74a9ac47c4d800e8dd034c9e789b)

Remember these things?

I then made a Nintendo DS match making service for friend codes and advertised
it on Mario Kart DS by setting it as my username (I chose the domain
"DSmeet.com" to be juuust short enough to fit), then raced backwards the
entire game so people would see me. (And it worked!)

[https://web.archive.org/web/20060208013613/http://dsmeet.com...](https://web.archive.org/web/20060208013613/http://dsmeet.com/)

[https://web.archive.org/web/20060216171807/http://dsmeet.com...](https://web.archive.org/web/20060216171807/http://dsmeet.com/f/2/)

I was so happy with myself because I wrote the forum software by hand. (Of
course I had to do everything hard-mode back then...)

Here are some examples of the "signatures" I'm talking about, if you've never
seen one before:

[https://web.archive.org/web/20060418010950/http://dsmeet.com...](https://web.archive.org/web/20060418010950/http://dsmeet.com/u/booyou2/)

[https://web.archive.org/web/20060429153550/http://dsmeet.com...](https://web.archive.org/web/20060429153550/http://dsmeet.com/u/Mega_Mario)

Those were some fun times...

Really neat interactive project. You sent me on a trip down memory lane. :)

~~~
lovehashbrowns
Ahhh, I used to love those signatures! I remember when everyone used to post
their computer specs on their signatures. And I loved your DSmeet project! Did
you happen to get into any of the communities that popped up for Animal
Crossing New Horizons? They brought me back to the olden days of finding a
community on a forum and making friends that way.

------
searchableguy
I have been thinking of coding myself something fun for readme. I like how few
people have built poor man's chess:
[https://github.com/timburgan/timburgan](https://github.com/timburgan/timburgan)

Any ideas HN?

~~~
eat_veggies
Try 2048, or render GIFs in realtime to do Tetris!

------
Uptrenda
I think I can see what you're trying to do but every user seems to share the
same view? Or is that a bug? If it's a bug I'm sure you could fix it with
something like sessions to have individual state per 'user.'

Overall: very clever

~~~
eat_veggies
Someone is spamming it from a lot of different IPs.

~~~
Uptrenda
Damn. Well, it's still really cool. Made me think of software a little
differently

------
Hitton
Frankly I have no idea why are people acting so impressed. ~15 years ago were
extremely common images which showed user's IP address, it was usually done in
PHP using imagemagicks. This is basically same, just with added cache of text
which is then showed. I even remember POC html/server only chat which sent
clients new gif frames as they posted new messages (found it [0], it's over 20
years old). That was much more impressive.

[0]: [http://zesty.ca/chat/chat.cgi](http://zesty.ca/chat/chat.cgi)

~~~
eat_veggies
Thanks, those types of sites were a huge inspiration for this. Actually the
zesty.ca site you linked was created before I was born :O

------
jvgrootveld
This is fun typing with hundreds (or more?) of people!

I tried to type a sentence by scripting the api calls in the console. But even
after requesting all the characters too many people interfere to create a good
sentence.

------
swyx
on a related topic of interactive READMEs, I decided to recreate the
Endorsements feature of LinkedIn on the new Github Profile feature:
[https://github.com/sw-yx#skills--endorsements](https://github.com/sw-
yx#skills--endorsements)

uses github actions and octokit to map issue reactions to Readme output - many
people dont know you can set github actions on a cronjob

~~~
eat_veggies
That's clever! Nice job!

------
SSchick
Aaaand we got the n word, didn't take long.

~~~
eat_veggies
it's what finally got me to implement IP-based rate limiting, but it appears
to be a coordinated effort. At least we made it to two full hours before
running into this :((

------
marvin8
Related: [https://codegolf.stackexchange.com/questions/5933/create-
a-u...](https://codegolf.stackexchange.com/questions/5933/create-a-user-
profile-mini-game)

------
jasonjayr
If you play with this and script it; be careful that you don't follow
redirects or reload github.com too much; you'll trigger github's rate limiter.

Oops. Sorry Github.

Coulden't get my full message out, but got a few "japh"s there :)

------
judge2020
You can continuously refresh the screen image here to watch what's being
typed: [https://kbd.jse.li/screen.gif](https://kbd.jse.li/screen.gif)

------
happppy
not updating for me

------
srtjstjsj
You've reinvented "open proxy" spam. Well done!

------
cjhanks
Question. From my experience, GitHub uses the `github-amo` bot to fetch the
data when the page is rendered. How did you prevent it from cacheing on
GitHub's servers?

~~~
maybevain
I was wondering the same. Seems like returning a no-cache value for the Cache-
Control header prevents the Camo service from caching the image [0].

My browser did however cache the latest image (which is why I thought the
system was not working for a second), and I'm not sure how to get around that.

[0] [https://docs.github.com/en/github/authenticating-to-
github/a...](https://docs.github.com/en/github/authenticating-to-github/about-
anonymized-image-urls#an-image-that-changed-recently-is-not-updating)

EDIT: I see. The no-cache causes the Camo service to refetch the image every
time it is requested, but it still applies a 4 hour cache time to the response
to the browser so it is anyway cached on the client side.

------
lma21
You can open the image directly here:
[https://kbd.jse.li/screen.gif](https://kbd.jse.li/screen.gif)

------
elviswolcott
If you're having problems, kbd.jse.li is currently blocked by OpenDNS
seemingly.

------
angrygoat
Commit two hours ago: "Implement rate limit" :-)

------
lirazel
Any stats for which keys are pressed the most frequently?

~~~
eat_veggies
I'm not currently saving logged output, but that's a good idea!

------
marmada
How does this work?

~~~
eat_veggies
Each button is a separate image that links to my website, which records the
letter, and then redirects you back to GitHub. The top part of the screen is
dynamically generated, and you can view it directly here:
[https://kbd.jse.li/screen.gif](https://kbd.jse.li/screen.gif)

~~~
uzyn
Doesn't GitHub cache fetched images? Any tricks required to get GitHub to
refresh the image?

~~~
eat_veggies
For most use cases, like for CI badges, setting cache-control and etag headers
will suffice, but GitHub still caches it (just for a shorter time? I don't
know the specifics). Luckily, you can request that they purge their cache for
a specific file [0] so I've got a goroutine that calls it once per second [1]

[0] [https://docs.github.com/en/github/authenticating-to-
github/a...](https://docs.github.com/en/github/authenticating-to-github/about-
anonymized-image-urls#removing-an-image-from-camos-cache)

[1]
[https://github.com/veggiedefender/typing/blob/0ed7c9c17970d6...](https://github.com/veggiedefender/typing/blob/0ed7c9c17970d6c1b2a7f16ec9acd20fb3bffd2b/handler.go#L86-L103)

------
epse
The api it uses is 404'ing for me now... Sad

------
Algomancer
Clever, you could use branches to add sessions.

~~~
capableweb
Base the session on the IP for the request to
[https://kbd.jse.li/type/:letter](https://kbd.jse.li/type/:letter), would be
good enough for a hack

Go to [https://kbd.jse.li/screen.gif](https://kbd.jse.li/screen.gif) and
refresh for a bit to see what people are typing!

~~~
lunixbochs
Could slowly stream the gif to show other people typing?

~~~
eat_veggies
I tried that at first, but GitHub's CDN will take the first few seconds of the
streamed GIF and loop it :(

------
runxel
Hugged to death – but neat idea nontheless!

------
spcebar
This is extremely clever. Many kudos.

------
boddu
Its not working on my chrome mobile version. It just takes me back to the top
of the screen, when I click on the letters.

------
Ceezy
it s not working on my laptop

------
pwrplus1
To the person typing "trump2020" it specifically says type something nice, not
something horrible.

------
stackzero
is this like twitch plays pokemon?

------
tetris11
SVG?

~~~
bawolff
Its not an svg. However that might be an idea for OP - rendering an svg is
probably easier on the server, and you can have a blinking cursor with SMIL
animations (full interactivity of course does not work when included as an
<img> tag)

~~~
kristopolous
SVG also has hyperlinking although I've never actually tried it in the browser
but if it worked then you could do a very strange but functional imagemap
vector implementation.

~~~
bawolff
Hyperlinks don't work in <img> tags though, they only work if you are allowed
to embed the svg elements directly in the page.

Basically if you include an svg as an image (via <img>, or via css, etc) it
can only be an animated image but you can't do anything interactive.

~~~
kristopolous
Ah interesting. It's probably a pretty clean implementation then. No immediate
workarounds come to mind.

There's ways you can obscure things, such as using an object tag, leaving it
up to the browser to decide via a mime type header which you specify then as
svg, buuut that won't work here.

Things are fairly locked down these days. Maybe there's something I'm not
thinking of using a similar pattern (confuse the browser, tell it the answer
and then have it generate the restricted type) ... Maybe something dealing
with lang or codepages... There's still plenty of shenanigans there.

Back in the day I used to upload full-blown servers I wrote in postscript as
my "profile image" and then they were blindly executed when trying to
"convert" the file - imagemagick locked that down about 10 years ago though.
Even back then usually some max execution timer would kill it after a minute
or so. But it was fun.

------
avipars
Looks like 90s style

Crappydesign on reddit will have a laugh

