A WebSocket-based Buzzer App with Webclients.
Go to file
Oliver Rümpelein ed5716875f Update dependencies. 2023-04-08 21:57:38 +02:00
gradle/wrapper Update dependencies. 2023-04-08 21:57:38 +02:00
src/main Update dependencies. 2023-04-08 21:57:38 +02:00
.gitignore Initial MVP 2021-09-25 12:24:28 +02:00
README.md Update to ktor 2. 2022-05-26 11:26:31 +02:00
build.gradle.kts Update to ktor 2. 2022-05-26 11:26:31 +02:00
gradle.properties Update dependencies. 2023-04-08 21:57:38 +02:00
gradlew Initial MVP 2021-09-25 12:24:28 +02:00
gradlew.bat Initial MVP 2021-09-25 12:24:28 +02:00
settings.gradle.kts Update to ktor 2. 2022-05-26 11:26:31 +02:00



A simple buzzer implementation using web technologies.



You need a JDK, version 11 upwards.


Until artifact storage is provided, start the service using gradlew run from within the project directory.

Alternatively, you can create the artifact using gradlew shadowJar. The output will be written to <projectDir>/build/libs/. Then run it using java -jar <JarFile>.

After it successfully launched, you have access to two clients.


All participants should call http://<yourHost>:8888/ or http://<yourHost>:8888/clients/player.

Now, they only need to enter their name on top, and they're set.

To trigger the buzzer, they just need to push the large surface. After a short amount of time they will be notified whether they were the fastest players (button turns green) or not (it turns red).


You can access this client from http://<yourhost>:8888/clients/moderator/.

Your surface consists of three parts. After a game has started, and some player decided they want to do the turn, these have the following functions:

  • On top, there's a large surface showing you the fastest player if any.
  • Below, you will see the order of players who pushed the button within 500ms after the fastest player (including the initial push). This information is included solely for transparency reasons and might be used to resolve obvious "Whoops, my beer tipped, and I accidentally activated the button!"-like situations to some extent.
  • A "reset"-button is located at the bottom. Clicking this will prepare the app for the next round. It will forget about all buttons pushed, and re-enable the buttons on the player's clients.

Troubleshooting & Tips

  • Before starting the game, test that each of the player's client works properly, by letting each one put their button after each other, resetting after each turn.
  • If the players or clients can't connect to your game server, make sure it's not blocked by the firewall. The app requires access to port 8888 for tcp connections.
  • Make sure each player's clients are released after you reset the round. If this is not the case, wait a few seconds and try again (and also check the players network connection and power save settings).


This project contains a weird mixture of technologies that I wanted to play around with:

  • Currently, there is no check for uniqueness of player names, and the name is used as identifier (that's the simplest way to be consistent across reconnects). Make sure each player uses a different name!
  • The server-portion is based on the ktor framework, a rather lightweight, code-configured web servicing library.
  • The clients' HTML files are created on the fly using the domain specific HTML language provided by kotlinx-html.
  • Javascript and data binding in the clients is achieved by embedding alpine-js, in conjunction with a few extension functions to integrate it into kotlinx-html.
  • Client-side websockets are made resilient with robust-websocket. Honestly, it's a shame how much time you need to invest nowadays to find a plain JS utility library that can just be included without running it through a full npm build pipeline for even a small task like this…


  • Configure startup (IP and port)
  • Keep history of previous rounds.
  • Ship utility JS libs as asset, don't rely on CDN and internet connectivity.