The QuickNews Odyssey: Lessons from Building a Startup

Original article can be found here (source): Artificial Intelligence on Medium


Now came the fun part for any technical founder: building the thing itself! First the scope: as every good startup founder, I had read The Lean Startup and consider it one of my favorite books. It’s replete with Wizard of Oz examples, and with startups adhering to Y Combinator’s “Do Things That Don’t Scale” dictum. And yet I broke those rules. Why?

My initial idea was that I’d start by manually selecting the news articles that I’d present to users. The thing is, that stops scaling immediately. Furthermore, developing the infrastructure for that would not take me significantly less than developing the real deal. So a heavyish MVP… This was important to keep in mind. We would offset the complexity of the infrastructure by starting with a very limited feature set, and would put that in front of users ASAP.

Onwards to coding. Language of choice: Python (speed of development, availability of libraries). Cloud provider: AWS (intimate familiarity). Some machines on Digital Ocean (a vague desire to give money to an alternative provider). The main components to develop:

  • A simple crawler (or scraper, I never know): On every run it takes a manifest with all the sites to crawl, does a pass through them and gets all the new articles. It has memoization, so it knows not to download articles multiple times. It stores batches of articles on S3.² Deployed on a cloud instance, runs as a cron job, taking approximately fifteen minutes.
  • Machine learning models: We covered before that a key thing was to run the article’s text through a Doc2Vec model, and getting a vector. The other part of the model is mapping the vector to one of the clusters (this was trained with K-means).
  • The main worker: This component is somewhat large and monolithic. But the gist of it is that it takes the articles caught by the crawler, does deduplication and elimination of junk and maps the articles to vectors and clusters. It then stores the relevant data for each article (metadata + vectors and clusters) into a database (DynamoDB, possible regret).
  • The API server: Has methods for generating the feed based on the user’s interest profile, as well as methods to register users’ clicks and update their interests. Keep in mind that QuickNews uses the click information to adjust interests but does not keep the clicks logged, so as not to be intrusive to the user’s privacy.

Altogether, a bit of a time investment. Still, better to have a working solution with some generality. Another point: the components were awkward and hacked together rapidly, but at least they were reasonably well separated. So if need be, they could be nuked and replaced one by one. The main problem now: no front-end.


Now things got interesting. Logistical matters first — I decided to take a two-month working vacation in Croatia. Business and pleasure indeed. I’d spend most of my time there on the island of Vis, where part of my family is from, and is known as one of the best tourist destination in that part of the Mediterranean.

That being said:

  • Hanging out with my family was good for business actually. Both my father and my uncle are experienced entrepreneurs, and my mother a former executive at the Croatian national television (hence good contacts, great for getting feedback from pros).
  • Hiring. The fact of the matter is that I couldn’t have afforded hiring engineers or designers in either Canada or the US. Croatia was excellent in that regard, and had amazing engineering talent. In addition, since I had gone to both high school and university there, my network was pretty strong.

Strong but imperfect, and not helped by my time as an émigré. Nevertheless, I reached out to a friend who had experience launching startups, and specifically mobile apps, to recommend people that he had worked with. After a bit of back-and-forth, I settled on a design agency to do the initial design. They had great experience and were enthusiastic about working with startups. A word of advice: when evaluating designers and front-end people, Behance is your friend.

Then a mobile developer. My friend had worked with a student from my alma mater, also named Marin³. Now I broke one of the more fundamental rules of hiring: I didn’t do a coding interview, a transgression I would have ridiculed other founders for. But for once, I was lucky, for Marin turned out exceptional: a great expert in mobile and, unusually, equally good at iOS and Android, as well as having startup projects under his belt. And in Amazon parlance, excellent “Ownership” and “Bias for action”. We ended up making a killer team.

An important point for the aspiring founder: both the designers and Marin would be working part-time. This, if not properly taken into account would lead to long development times. We “solved” this by reducing the scope — only the login, main feed, and a very basic search function.⁴


Now a brief comment on our decision-making about the front-end. The first, easier, question was whether to go with a mobile app or a regular page? On this I had a strong opinion: mobile rather than desktop would be the main platform for our users, and everything should be optimized to give mobile users the best possible experience. Besides, at least on Android, we could iterate fast. Mobile it was.⁵

The second question gave me nightmares: iOS/Android or Flutter/React Native. I have yet to meet a single experienced mobile developer who would go on the record saying that they feel even a modicum of affinity towards Flutter/React Native, and I’d almost always hear comments along the lines of “Now your app is going to look ugly on both platforms”. But on the other hand we had the downside of duplicating work if we took the other route. We’d be deeply in “heavy MVP” territory.

We decided to go with native Android/iOS. We had considered skipping iOS, but decided against that since North America was our initial market, and there Apple’s market share hovers around 50%. We did, however, make a shrewd decision: we’d start with Android (trivial to ship, unlike iOS), get it in front of users, iterate on the feature set, and then follow up with iOS. Since then we’ve stuck to this strategy, and we iterate on Android first and observe the results. We follow up with iOS once we’re out of other feature ideas.⁶

Launch and user acquisition

Now back in Canada, I experienced something peculiar that would make Gary Vee spasm: I had no idea what to do. Marin was working on the Android app, which meant that we still had nothing to show users. At the same time, the back-end was done for the time being, and despite pending tweaks there was nothing major.

I tried to make the most of it. A clever scheme congealed: just on the corner by my old Amazon office was a café where many of my former brethren went, people I’d known from the office. I figured that I’d go work from the café, and whenever I encountered one of my old colleagues I’d say hi and give an elevator pitch. Then once we had a product, I’d start signing them up in the same way and get their feedback.

And then, with characteristic effectiveness, Marin finished the app. The first steps seemed clear enough: sign up family and friends. In addition, I persevered with the previously outlined café strategy and recruited plenty of old coworkers. The most prominent person to succumb: a VP/Distinguished Engineer on AWS and industry demigod. He graciously agreed to serve as a beta tester. I also recruited users in the meetups I attended.

The initial feedback was lackluster, to put it mildly. We tried to be clever and infer users’ preferences from their social media accounts. This produced underwhelming effects since there usually isn’t enough data to infer anything. In addition, dealing with social media accounts in today’s world is a disaster waiting to happen. So we nuked this logic and added a simple topic selection screen. The app would still learn as you go, but at least the initial profile would not be useless.

In the meantime, our design agency finished the design and the copy, for our landing page (, virtually unchanged since the first iteration) and we found a developer on Upwork to do the slicing. He produced the HTML and CSS, which we summarily hosted on AWS (S3 + Cloudfront + Route53).

Retention and notifications

Most people are familiar with Dave McClure’s famous AARRR metrics: acquisition, activation, retention, referral, revenue. And for the most part, all of them are treated with similar reverence. We put a slight twist on it, for which I was to a great degree inspired by one of my skip-level managers at Amazon, a startup veteran — that retention is the critical one, especially for consumer apps, and should therefore take precedence over the others.

The view has been espoused in YC as well: a great lecture by partner Gustaf Alströmer, a former growth team lead at Airbnb, mentions retention as the best proxy for the elusive quality of product/market fit.⁷ And indeed, it’s not particularly worth focusing on acquisition before this is nailed down: you’re pouring new users into a leaky bucket. In any case, the best way to visualize retention is through the now well-known “waterfall” graphs, available in vanilla Firebase.

We focused on this with vehemence. Part of it was simply making the feed better and less random, which we achieved through the topic screen. The larger part, however, was in fact one of our core tenets: notifications. I allow myself a certain degree of smugness regarding this hunch. Indeed, notifications are the thing that brings users back to the app. But too often they’re mere annoying reminders. We threw considerable algorithmic firepower at the problem: figuring out which articles are important or breaking (enough to warrant a notification), matching them to users’ interests, figuring out what the right frequency of notifications is, as well as determining the ordering. With this, our retention increased significantly.