The chat box I did not build
By Ari Hlynsson ·
Eight preset phrases, sent as an index rather than as text, so free chat is unrepresentable on the wire rather than merely refused.
Two people sit down at a card table on this site. They can see each other's seat, whose turn it is, and what was played. They cannot type anything to each other, because there is no message box and I do not plan to add one.
A text input and a WebSocket message would take about an hour. I left it out because I could not see how to moderate it responsibly.
The expectation that arrives with a text field
People who can type to each other expect to be able to report abuse and have somebody read the report. I am one person. I cannot answer reports at three in the morning, and I cannot promise a reply within a week. This site also has a children's section, six games at /kids, so the worst case is not two adults arguing about a card game.
I could not commit to handling any of that, so I left the box out.
What is there instead
Eight phrases:
Hello
Good luck
Nice one
Good game
Thanks
Oops
Sorry — slow connection
Have to goTap one and it appears at the other seat. A cooldown of four seconds stops people sending them in rapid succession.
The client sends each phrase as its index in that list, a number between 0 and 7, and the receiving client looks it up in its own copy. No field anywhere in the protocol carries a string that a player typed.
If chat were text with a filter over it, the filter could be wrong, and somebody would eventually find the gap. The protocol has no way to carry arbitrary text at all, so the restriction does not depend on me watching anything.
What it costs, and something it gave back
The list is short, and a short list cannot say what a person actually wants to say. Somebody who wants to point out a clever move has "Nice one" and nothing else. That is a genuine loss and I have not found a way around it.
It does make one thing possible that a text field does not. Because every possible message is known in advance, I can read the whole vocabulary as a set and ask what is missing.
I got round to doing that after launch, when the list was seven phrases. In order, they covered arriving, starting, a good move, a bad one, the end of the game, and a pause that the other seat would otherwise read as rudeness. What they could not do was tell the other player that you had to leave. Going without explanation often looks rude.
Somebody who had to go could vanish in the middle of a hand, or remain at a table where they were no longer playing. Both look like contempt and neither is. "Have to go" became the eighth phrase, and it is the only one I have added since.
The limitation I am not going to talk around
Any fixed list can be used sarcastically. Send "Nice one" after every mistake your opponent makes and nothing in the protocol knows the difference. Changing the phrases would not prevent that.
What the fixed list does is make the content of every message knowable in advance. Tone is a separate problem, and the answer to tone is the mute, which lives in the client and belongs to the player.
One practical note for anyone copying this
Because the wire carries indices, appending to the list is safe and reordering it is not. A message already in flight from a client running older code will land on whatever now sits at that index. Move "Good game" to the front and somebody, somewhere, says "Hello" when they meant to congratulate you.
Add to the end. There is a comment saying so directly above the array, because I will forget.
More on how it works
- One puzzle for the whole world, no database
Everybody gets the same daily board and nothing is stored anywhere. Two functions turn today's date into a seed, and each browser generates the puzzle for itself.
- The friend list my server never sees
A green dot telling you which friends are online, drawn by a server with no database connection and no way to learn who your friends are.