At the latest WebExpo conference we had a mini-game in our booth (or 2 mini-games to be precise – tests for designers and developers). The candidate selects one right answer per question and had only one attempt to pass the test. The ranking was done by the number of correct answers and by the time (in the case of a tie).
The designer test included 20 questions where you needed to select one of 2 images that presented "the right way" and "the wong way" from UX and UI points of view.
The developer test was more complicated. It consisted of 20 questions across all our technology stack with 4 options to choose from: C# for backend questions, JavaScript for frontend questions, Dart for mobile development, Python and SQL from Data department (if you're interested in our technology stack check out this repo).
I decided to write this game in Dart, so for the framework I had to choose between Flutter Web and AngularDart. While it would be great to use Flutter Web, as we're using it in our department to write iOS/Android app, it's still in technical preview, and I didn't know if there would be some blockers for our game (speaking ahead – there were, but more on this later). So I've decided to use AngularDart, though I had no experience with it (well, I used to code in AngularJS several years ago, but that's it).
Despite my lack of experience with AngularDart, the game was written within a couple of working days (the code was far from perfect though) – and btw it reminded me exactly why I wasn't a fan of Angular: too much magic under the hood comparing to e.g. React.
During the event I was asked if we were going to open source the game, and I've promised to raise this question intenrally. So we did discuss it, and the result of discussion was why not?.
I've started preparing the code and it occurred to me that this code wouldn't be very useful for the community: as I've already mentioned, my knowledge of AngularDart consisted of going through official tutorial, so the code probably would be good only as a how-not-to guide. Besides that I still wanted to experiment with Flutter Web, so I've decided to create another version of this app in Flutter.
So I've extracted the common code (models and services for communicating with Firebase) and created a Flutter Web project – that took roughly another working day.
Actually, it would be interesting to further maintain and update both these versions, so I have an offer for the community: let's work on this project together and come to some proper implementations for both frameworks. If you have any ideas feel free to create an issue or make a pull request: https://github.com/MewsSystems/mews-challenge.
But in the meantime let's dive into some technical details.
Backend
For the backend part I decided to use Firebase Firestore database + Firebase Functions. On the top level there are 3 collections: games, results and users.
Games
Basic information about the game:
{
"design": {
"id": "design",
"description": "Are you UIcasso or da UXinci? Let's see your eye...",
"title": "🖌 Design game"
},
"developer": {
"id": "developer",
"description": "Frontend, backend, data, applications… We know it all! How about you?",
"title": "💻 Developer game"
}
}
Each game contains a sub-collection questions. Here's an example developer question:
{
"cs_01": {
"id": "cs_01",
"title": "What will be printed in a console?",
"code": "Console.WriteLine(1 << 8);",
"tag": "C#",
"rightAnswer": "a",
"answers": [
{ "id": "a", "text": "256" },
{ "id": "b", "text": "128" },
{ "id": "c", "text": "64" },
{ "id": "d", "text": "512" }
]
}
}
And this is how it looks for a design question:
{
"design_01": {
"id": "design_01",
"title": "Which label of the button is better?",
"rightAnswer": "b",
"answers": [
{ "id": "a", "image": "q1_fail.jpg" },
{ "id": "b", "text": "q1_right.jpg" }
]
}
}
As you can see, the answer can contain either text or an image. Images are stored in Firebase Storage, in the questions folder.
Users
Contains information about the user. We're only keeping the email and display name that we get from Firebase Auth, so the data looks like this:
{
"fxXAEKGZJOaTVHzT6fbufm4MgVu1": {
"name": "Kirill Bubochkin",
"email": "kirill@mewssystems.com"
}
}
We also have here a sub-collection games with the information about the games this user played.
Results
This collection contains information that is displayed on the Results page:
{
"GAME_ID": {
"results": {
"USER_GAME_ID": {
"start": "DATE_TIME",
"end": "DATE_TIME",
"questionCount": 20,
"rightAnswerCount": 17,
"name": "Kirill B.",
"userId": "USER_ID"
}
}
}
}
All the data except top-level games collection are filled in automatically by Firebase Functions and you don't need to do anything with them.
Frontend
As I've already mentioned, the frontend part is written for both AngularDart and Flutter Web, so we have the following structure:
core
– common code with models and services reused by both frameworks.app_angular
– AngularDart app.app_flutter
– Flutter Web app.
Writing the app for Flutter Web was very similar to the mobile Flutter, but you need to keep in mind that for now Flutter plugins are not supported. Also instead of e.g. Flutter Firebase library you need to use the firebase
package for browser-based applications.
Also I've run into 2 major bugs, that currently prevent us from publishing our Flutter Web version to production:
- custom font rendering in Safari isn't working (so it affects Safari on macOS and all browsers on iOS): https://github.com/flutter/flutter/issues/41483
- links in
RichText
are not always working: https://github.com/flutter/flutter/issues/39226
Apart from that, the development process was pretty straightforward, widgets were pretty much the same as I would write for a mobile app. If you're interested, I can write a separate article about developing the Flutter part of the app with more technical details.
10,000 foot view: it's a pretty common app with
rxdart
andprovider
packages. Instead of BLoC pattern I've just re-used services from thecore
package: for such a simple app it's enough. I've also useduniversal_html
for processing external links, andflutter_html
for turning HTML code into Flutter widgets.
Verdict? While Flutter Web is definitely not yet ready for the production, it's still great to see the direction it is heading in, and I'm looking forward to the stable version. It would be the perfect choice for a true multi-platform app.
So without any further ado, go to the app repo, create issues, make pull requests, and let's work together to make this app a showcase for using Dart in web development.
Oh, and you can try the game here: https://mews-challenge.firebaseapp.com/