Today, I would like to share with you some thoughts and code on a topic I have been dabbling in – hopefully to entertain a bit and maybe even to spark some interest. I will talk about a collaborative web app that works without a server on the internet; and the philosophy that motivates this.
The Web app
The web app is here: https://mroemer.pages.inovex.de/schnucki (view source if you are curious). It can be used to track the results of a tournament of the game rock-paper-scissors.
So, let’s assume Mario, Luigi, and Peach come together to see who the champion is. They all play against each other, Luigi enters the results into the web app and then they know who’s the best.
Word gets around and the next time a lot more characters show up for the tournament. They even have to play multiple matches in parallel in order to be done in time for dinner. Poor Luigi can barely keep up with entering the results, not to mention playing his own matches.
It’s a mess!
It would be super convenient if multiple characters could enter results from their own devices but so far all the data is stored inside Luigi’s browser’s local storage.
One solution to this conundrum and the idea I have been toying with is this:
Luigi installs a native app on his mobile. Inside it, we start an http-server. Now, several characters can open the web app on their device and connect to this server in order to access the data.
All devices must be able to talk directly to the mobile running the native app. This is probably fine if everyone is connected to the same Wi-Fi network. But you might run into trouble when NATs get involved and you start punching holes into firewalls.
Also, the in-app HTTP-server generates its own self-signed certificate. You will have to convince your browser to trust it. This is not something we should teach people to do willy-nilly!
But … why?
The web app is super rudimentary and the use case of the rock-paper-scissors tournament is a bit contrived. Yes.
They serve as a springboard for exploring ideas.
Imagine Wario: He has some web-dev skillz. He programs this web app for himself and his gang, just for fun.
And then, through the magic of zero marginal costs on the internet, this web app can be gifted to the rest of the mushroom kingdom.
Compare it to knitting a sweater and gifting it to a friend. When the next friend inevitably asks for their own sweater, Wario would have to start knitting again. With software, he can “write once, gift anywhere“.
I think that is just awesome!
This already works for web apps that require only one device. However, some use cases benefit from using multiple devices. The usual way to have multiple devices collaborate on the same data is to have a central server, running somewhere on the internet.
That would work, of course.
But this server needs to be operated and maintained. Wario would have to do this himself, pay somebody else to do it, or hope that the free tier of some as-a-service service will survive indefinitely. None of these options look appealing. They come with a lot of commitment; be it time-wise, financial, or stress-inducing.
Wario prefers to just code and gift.
So, I am exploring this space. Looking for the sweet spot between “local-only single-device“ and “full-blown internet-hosted services“. Which brings us to the title of this blog post: Bring your own backend.
Bring your own Backend for a web app
Luigi and his gang want to use Wario’s web app. The web app needs a backend. Luigi should be empowered to run this backend by himself. But Luigi is not a techie. You cannot tell him to “just sign in to the registry and deploy this container-image to your Kubernetes cluster“.
Installing an app on your mobile on the other hand might be a reasonable ask.
So this is where I am at the moment.
Previously, I tried to use WebRTC to enable two browsers to talk directly to each other. That kinda worked, but got messy with my “no internet“-constraint.
Instead of using signaling-servers on the internet to establish the WebRTC connection, the browsers each had to scan QR-codes generated on the other device. It technically worked, but I couldn’t get the UX to be tolerable.
Would have been awesome, though. Serving only static files, no backend, no app store… chef’s kiss!
Instead, I wrote an android-app 😅
I convinced myself to write the native app by saying that it could provide a generic interface for accessing data. So that it can be used not only for Wario’s web app but for others as well. Bowser could write some other collaborative webapp and the users could use the same native-app to bring their own backend.
Another idea would be to write a Nextcloud app that serves the same purpose as the native app.
That would require a bit more from the user, though. They need to have access to a Nextcloud instance and be able to install apps.
But it would alleviate the two limitations from above. We could avoid the ssl-warning-override with a „real“ ssl-certificate. And users from outside the local network could reach the server.
The trick here is, that the nextcloud would still be operated by Luigi (the user), not by Wario (the webapp-developer).
The general thoughts and ideas undergirding this are not new. Search the web for “unhosted“ or “nobackend“ and you will find blog posts from 10 years ago, focusing on different facets of this wider topic.
I just think it’s fascinating and wanted to share my view.