7min read

“Walking the Dark Valley” - An iOS Developer’s journey into Web programming

The story

My platform of choice is iOS and I don’t hide it. If you, dear reader, had the opportunity to talk with me about this, you already should know that I have my reasons. Performance, control and stability are only the beginning of the list of arguments for going native. But at times, one needs to step out of his preconceived opinions. And lately I find myself developing apps more and more based on web-technologies. Let’s start from the beginning, shall we?

In early 2014 I had the pleasure to co-organise Mobile Central Europe conference. A conference made by developers for developers, like no other. Just like with our Mobile Warsaw events, we put a lot of emphasis on networking. This left us with a problem to solve. How to make people stay in touch after the conference is over, and make it fun in the process? So the idea of a networking game was born.

Finding a story idea matching the theme of the conference wasn’t hard. Take a dark desolate planet (Poland during winter), add a crew (the conference attendees) of a crash-landed ship (the saucers seen in much of the material), and you have a perfect fit for a game. The target would be to “recruit” other players by means of a identifier found from their conference badges. “Recruiting” being a nice coverup for sharing social media contacts.

picture picture

The requirements

We had an initial idea. It was time to write down some requirements:

  • “Recruitment” needs to be as easy and fast as possible: In the beginning we wanted to use QR codes. But after visiting WebSummit we picked the idea of badge ids. It turns out typing three letters is faster than taking a QR scan.
  • Users must have fun while playing the game: They must see the progress they make. Comparing the progress with peers is also fun. Points are perfect for that. And achievements. Everybody loves achievements!
  • The game needs to handle low quality internet connections: We all know how hard it’s sometimes to get a decent Wi-fi access in a public space and a “big” conference tends to be even trickier.
  • We need to protect the privacy of the users: Simply put, it should be impossible to extract the full details of all participants without some kind of consent from the players. To balance between UX and security we decided that only the first name, and Gravatar URL would be accessible publicly. More information (surname, social media contacts, etc) of a user would only be available to its recruits.
  • The game should cover as much devices as possible: Android and iOS may have dominated the smartphone market. But then there are those who want to stand out of the crowd (or simply enjoy a longer battery life). Who are we to condemn them?
  • Anticipate we will be hacked: Let’s face it, our attendees are mostly software developers. It was obvious from the beginning they will try to cheat the system just for fun. And so we needed to make it a little bit harder (more fun) for them.

The sad reality

It was mid-November, MCE was nearing with big steps. We had a nice concept, and a huge dilemma. Can we really afford to allocate enough developers to write the game natively for the three main smartphone platforms? We were already out of time. Application reviews for iOS tend to take around 3-4 weeks at the end of the year. To make it until the conference we would had needed to submit almost immediately.

The dilemma was the ages old native vs hybrid vs mobile web app discussion. At Polidea we strongly support the native way. It is our belief that under normal circumstances, native implementation delivers a far better experience to the users. But this time we wanted to do something very simple, and at low cost. We decided to give mobile web a try. A single developer would be able to write it and with no review times to hold us back. And thanks to some newer web-technologies it should be possible to fulfil most (if not all) of the requirements. That was promising at the very least.

The implementation

And we had a winner! I took the responsibility of development work. That’s why the app was architected in a very iOS-ish way. A variation of MVC of sorts. All the actual “code” gets downloaded by means of HTML offline cache on the first run of the application. Then, all the necessary data gets fetched, placed into offline storage and rendered using a JavaScript client-side template engine. In such a way the application is able to work for prolonged time periods without internet access. It turned out to work just fine. With an important exception of Internet Explorer up to version 9 (including the one running on Windows Phone 7).

“Recruiting” was performed in a similar fashion. A badge id is first stored in the local database, for later submission to the backend at the first possibility (e.g. when Internet access is available). Points and achievements were awarded afterwards. Functionally, this is an ideal solution. But from a UX perspective, there is a possible delay between entering a badge id, and receiving any feedback (e.g. typing mistakes do happen). To mitigate this, the game performs an initial verification on the client side. This requires data and so a slimmed down (only first name, avatar and badge id) version of the user database is stored into the client.

Player connection graph

The ugly parts

In the beginning I thought the ugliest part would be JavaScript. It quickly turned out that it was CSS. Full control of layout is something I’m used to in iOS. To my great surprise I discovered that achieving even basic constructs (e.g. vertically centred text) in CSS is a pain. For more complex approach, there are “templates” like the Holy Grail ( The word “hack” is on my lips when I think about them. Tools like Foundation ease the pain a little bit, but at cost of polluting your HTML with additional wrapper ‘divs’ and similar: something CSS was supposed to prevent in the first place. On the bright side there are modern tools like SASS (Syntactically Awesome Style Sheets). They compile CSS out of a more expressive language. Variables, functions, inheritance and embedding, all suddenly are possible.

And then there is fragmentation. Each platform has some (even iOS). But what happens in the mobile web space is just madness. It’s like the sum of all fragmentations for each platform multiplied by the choice of browsers. For example: one, rather funny bug was caused by a difference in behaviour between IE and WebKit based browsers. In zepto.js (a hipster remake of jQuery) that we use, there is a flag for ajax cache control $.ajaxSettings[‘cache’], which is true by default. From what I understand on WebKit based browsers, this adds automatic cache-buster flags to the url. As our backend didn’t implement a cache for API calls, this was working fine. On IE it actually uses some kind of built-in request cache, and so it didn’t sync the state of the game. The blame was on me for not testing on Windows Phone during development.

Hacked by design

As already mentioned, we anticipated there would be attempts to hack us. We even predicted the standard attack. It’s enough to take the identifiers from the local database and send them to the right endpoint. That’s actually the way most of the 20+ users that tried to hack us. I think only one person tried to brute-force on all of the 18k+ combinations. But a hack is worth of nothing, if you get caught. And we have plenty ways of knowing.

Our first line of defence was rate-limiting on the backend for the recruitment endpoint. Reasoning here: there is a limit on how many recruitments a normal person can do in a given time. Let’s say 2 per minute. Recruiting all the 400+ conference attendees would easily take 3+ hours of constantly hitting the backend. By tracking the number of times a person hit the limit, we get most of the cheaters on a silver platter.

Second, there are statistics! A normal user is expected to have recruits evenly distributed among all conference participants. If someone has too many users recruited in a row (following badge ordering) then we can be sure he is just going over the user set without giving any thought about it. Similarly we can look at the timestamps of recruitment events, and search for more evidence there. In the end, a clever hacker would take the included database, and slowly, with random delays and in random order, go over it one user at a time and stopping at a reasonable amount of recruits.

It is a completely different matter how to handle the users caught of cheating. Instead of banning them (standard response in most games) we simply changed the way the game treats them:

  • They are not counted in the statistics: There are some achievements that are based only on the amount of recruited users.

  • Re-recruit function is disabled: There is a feature in the game allowing users to re-recruit a user who has recruited them before. To protect the data of users simply doing this for everyone, we had to do something. If a user is caught of cheating, he can’t be re-recruited in this way. The normal recruitment method by entering the code manually stays unchanged.

The conclusion

The web world is finally catching up. Some important new HTML5 technologies have been proposed to solve current headaches (CSS flex layout, anybody?) and the example of Internet Explorer 10 sparks hope that cross browser compatibility is also improving. But how long will it take to be finally usable? I fear it will be another 3 years. Or am I too sceptic? Even then, I fear the performance and quality won’t stand on equal ground with the native implementation.

One last question remains. Was it a good decision to go with web? I think yes. The game worked, more or less for all the attendees. Those devices the game didn’t work were mostly rather obsolete Android and Windows Phones. I think for next year’s (it’s almost sure there will be MCE 2.0) game, if we decide to have one, will also be web based.


AntoniPrincipal Software Engineer


Sign in and expect sharp insights, recommendations, ebooks and fascinating project stories delivered to your inbox

The controller of the personal data that you are about to provide in the above form will be Polidea sp. z o.o. with its registered office in Warsaw at ul. Przeskok 2, 00-032 Warsaw, KRS number: 0000330954, tel.: 0048 795 536 436, email: (“Polidea”). We will process your personal data based on our legitimate interest and/or your consent. Providing your personal data is not obligatory, but necessary for Polidea to respond to you in relation to your question and/or request. If you gave us consent to call you on the telephone, you may revoke the consent at any time by contacting Polidea via telephone or email. You can find detailed information about the processing of your personal data in relation to the above contact form, including your rights relating to the processing, HERE.

Data controller:

The controller of your personal data is Polidea sp. z o.o. with its registered office in Warsaw at ul. Przeskok 2, 00-032 Warsaw, KRS number: 0000330954, tel.: [0048795536436], email: [] (“Polidea”)

Purpose and legal bases for processing:


Used abbreviations:

GDPR – Regulation (EU) 2016/679 of the European Parliament and of the Council of 27 April 2016
on the protection of natural persons with regard to the processing of personal data and on the free movement
of such data, and repealing Directive 95/46/EC (General Data Protection Regulation)

ARES – Polish Act on Rendering Electronic Services dated 18 July 2002

TL – Polish Telecommunications Law dated 16 July 2004

1)        sending to the given email address a newsletter including information on Polidea’s new projects, products, services, organised events and/or general insights from the mobile app business world |art. 6.1 a) GDPR, art. 10.2 ARES and art. 172.1 TL (upon your consent)

Personal data:name, email address

2)       statistical, analytical and reporting purposes |art. 6. 1 f) GDPR (based on legitimate interests pursued by Polidea, consisting in analysing the way our services are used and adjusting them to our clients’ needs, as well as developing new services)

Personal data:name, email address

Withdrawal of consent:

You may withdraw your consent to process your personal data at any time.

Withdrawal of the consent is possible solely in the scope of processing performed based on the consent. Polidea is authorised to process your personal data after you withdraw your consent if it has another legal basis for the processing, for the purposes covered by that legal basis.

Categories of recipients:

Your personal data may be shared with:

1)       authorised employees and/or contractors of Polidea

2)       persons or entities providing particular services to Polidea (accounting, legal, IT, marketing and advertising services) – in the scope required for those persons or entities to provide those services to Polidea


Retention period:

1)       For the purpose of sending newsletter to the given email address – for as long as the relevant consent is not withdrawn

2)       For statistical, analytical and reporting purposes – for as long as the relevant consent is not withdrawn

Your rights:


Used abbreviation:

GDPR – Regulation (EU) 2016/679 of the European Parliament and of the Council of 27 April 2016
on the protection of natural persons with regard to the processing of personal data and on the free movement
of such data, and repealing Directive 95/46/EC (General Data Protection Regulation)

According to GDPR, you have the following rights relating to the processing of your personal data, exercised by contacting Polidea via [e-mail, phone].

1)       to access to your personal data (art. 15 GDPR) by requesting sharing and/or sending a copy of all your personal data processed by Polidea

2)       to request rectification of inaccurate personal data
(art. 16 GDPR) by indicating the data requiring rectification

3)       to request erasure of your persona data (art. 17 GDPR); Polidea has the rights to refuse erasing the personal data in specific circumstances provided by law

4)       to request restriction of processing of your personal data (art. 18 GDPR) by indicating the data which should be restricted

5)       to move your personal data (art. 20 GDPR) by requesting preparation and transfer by Polidea of the personal data that you provided to Polidea to you or another controller in a structured, commonly used machine-readable format

6)       to object to processing your personal data conducted based on art. 6.1 e) or f) GDPR, on grounds relating to your particular situation (art. 21 GDPR)

7)       to lodge a complaint with a supervisory authority,
in particular in the EU member state of your habitual residence, place of work or place of the alleged infringement if you consider that the processing
of personal data relating to you infringes the GDPR
(art. 77.1 GDPR)

No obligation to provide data:

Providing your personal data is not obligatory, but necessary for Polidea to provide you the newsletter service

Refusal to provide the above data will result in inability to receive the newsletter service.


In the process of providing the newsletter service, we make decisions in an automated way, including profiling, based on the data you provide.


“Profiling” means automated processing of personal data consisting of the use of your personal data to evaluate certain personal aspects relating to you, in particular to analyze or predict aspects concerning your personal preferences and interests.


The automated decisions are taken based on the analysis of clicked and viewed content. They affect the targeting of specific newsletter content to selected users registered to receive the newsletter service, based on the anticipated interests of the recipient.