ProDemos’ BinnenhofCheck app is a connected multiplayer quest for high school students around The Hague’s Binnenhof (the oldest House of Parliament in the world, still in use). While that doesn’t sound particularly extraordinary (ahem), the challenge this project encountered is. We built an interactive game with a crucial sidenote: players have no internet access for a considerable amount of time during the session. Meteor proved to be the perfect answer for a case like this.
Yup, no internet. Because, ProDemos’ WiFi reaches to the door of the Binnenhof, but no further. And, because of security regulations that restrict WiFi at the Binnenhof itself, extending the signal wasn’t an option. “What about 4G?”, I hear you thinking. Sure, there’s 4G coverage at the Binnenhof, but giving 30 tablets 4G subscriptions will cost you. Besides, why spend so much when internet connectivity isn’t really a necessity anyway, because the solution can be so simple?
Meteor’s ‘elevator pitch’
Meteor convinced us rather conclusively, during what you can call a literal elevator pitch. Before this app, we built another Meteor app for ProDemos. During that project, the question of whether the app would still function when connection was temporarily lost came up. Remco was kind of sure it would, and tested it by stepping into the elevator. Because of course: the world of elevators is an offline one. And it did! Without internet connectivity he could still use all the app’s functions. In fact, stepping out of the elevator, the app synced automatically with the server again. That is what makes Meteor so powerful in a case like the BinnenhofCheck. Packages like MiniMongo and autopublish make it so that an app fully runs on the client, even when it’s offline. And then it automatically syncs with the server again when connectivity is back — without you having to set it up to do so yourself. That’s valuable time saved to spend on user experience instead of trying to fix the problem of the lack of internet.
Writing your code for the client is clean and simple in Meteor. And because every Meteor client has an in-memory database cache, there is no need to manually cache data to dodge slowness in talking to the server, program detailed invalidation messages to every client when data changes or implement individual RPC endpoints.
The server publishes defined sets of data through publications, and the client subscribes to these sets through subscriptions. When the content of these sets change, the server updates them in the client’s cache too. The client code is extremely simplified, by using its cache as a fast local database. Therefore, for reading the subscribed sets of data, no connectivity to the server is needed. This saves time, and makes the app faster. You can easily make your client even snappier by turning subscriptions on and off to control the amount of data kept in cache and manage the network traffic. Turning one off means it will automatically delete all its data from your cache.
So the server automatically updates subscribed data on the client when data on the server changes. The client, as a MiniMongo, does something similar. When data is changed on the client, for example through an action of the user, it automatically sends a message to the server with a request to change it on the server too. The server checks its allow/deny rules, and when all those rules pass, it changes the data and updates the change to other clients with the same subscriptions too. No need for you to code this yourself.
In short, these methods realize latency compensation, which means you can still use the app locally in full function when connectivity is lost and it automatically updates the server when connectivity is back.
You can read about these techniques in more detail here.
Publications and subscriptions in the BinnenhofCheck
For the BinnenhofCheck app, built by Silvy, Jeroen and Remco, this means MongoDB is the database on the server at ProDemos. And the tablets (the clients) function as MiniMongo. At the start of the quest the supervisor creates a group and session in the dashboard of his or her tablet. This group then receives a code, and with this code the students can add themselves to it on their own tablets. Now the quest can begin. During the quest the tablets are offline, but still run the app in full function. Back at ProDemos, connectivity is back and automatically publishes all the changed data by the students to the server to see who has won the quest. After this, the supervisor presses ‘stop’ to end the session: this automatically archives the subscriptions and deletes the data from the caches of the tablets. Clean and ready to start with another group immediately.
Asset manager package
However, data like text is fine, but you don’t want to upload all the images and videos to the clients every single session. That would be a serious waste of time. So we weren’t there yet. We ended up fixing this by creating two different collections on the server. One for all the text, questions and locations (these types of data are small enough in size to quickly upload and delete every session through the publications and subscriptions) and the other one for the images and videos. For this collection we built an asset manager package. Through scheduled tasks, this collection synchronizes with the clients. You can find this asset manager package here.
We really enjoyed building this app in Meteor for ProDemos and are very proud of the result. If it’s up to us, this case proves building an app in Meteor is the simple solution when you’re facing a similar problem with connectivity in your projects.
PS We think a nice future addition would be to add GroundDB.
Check out our Engineering Blog for more in depth stories on pragmatic code for happy users!