How we built the new Buycoins apps — Hybrid + “core” web technologies

Timi Ajiboye
Helicarrier
7 min readJun 16, 2021

--

Buycoins and Buycoins Pro

At Buycoins, we don’t have “loyalty” to any particular technology stack. We think that technical decisions should be made based on goals & constraints.

Goals — what are we trying to achieve?

Generally, the answer to the first question is:

  • We’d like to be able to get a new experience to our users as fast as possible so that we can immediately start learning from them.
  • Similarly, we want to be able to push updates to our users as fast as possible for the same reason — to learn more, quickly!

Constraints

The first Buycoins

We had to switch from our first P2P exchange (Bitkoin) to a platform where users didn’t have to care who they were buying cryptocurrency from. They just wanted to tap “buy” & get Bitcoin. In 2018, very much unlike today, that experience pretty much didn’t exist for Nigerians.

It also had to be built very quickly, we were getting close to Demo Day at YC’s Summer Batch and we needed to test our thesis immediately.

The development team was much smaller back then — no more than 3 active engineers at a time & we were still super new to building “crypto/blockchain stuff”. There had to be mobile apps too this time around, simply because users wanted them. Native apps were ruled out as we definitely couldn’t maintain three separate codebases (iOS, Android & Web).

Bitkoin’s client side app was built in Angular and we’d read that ionic let you build cross platform apps with Angular. At the time, the only core native device functionality we needed was access to a device’s camera, for scanning QR codes and ionic let us do this relatively easily.

Ionic isn’t the most popular choice, but it was a good trade off. It had advantages that really fit well with our goals:

  • We got to continue building with the web technologies that we were accustomed to.
  • It has a pretty good first party UI component library. Elements, for the most part, looked like their native counterparts on each mobile platform. To optimise for launching earlier, we decided to build the entire application using only these UI components. It didn’t make for the most aesthetically pleasing app, but at least — there was an app, with traction, in time for Demo Day.

As we grew & features piled on, we hit another set of constraints sometime last year and decided that it was time for a rebuild.

Why were new Buycoins apps necessary?

We needed to ship faster

We like to ship things as fast as possible. Cryptocurrency is still extremely uncharted territory, especially in Africa. We think it’s important to be able to learn, adapt, and iterate very quickly.

  • With most mobile app architectures, fast iteration requires making users download an app update every single time there’s a change to the content or UI. Even the process of getting a new build to users featured longer than necessary QA & compilation times.
  • Server ↔ Client backward compatibility is something you always have to consider, as a lot of users don’t [automatically] update their apps, especially in this market. Having to continually support previous interfaces & business logic that no longer serve you or your users is a time sink. While it’s important to always build with backward compatibility in mind, there will always come breaking changes & we wanted to stop worrying about that entirely.

Buycoins stopped being simple

As Buycoins grew, we found that a significant amount of users (who we refer to as professional traders) wanted more than just the ability to buy & sell at the prices we provide. They wanted to be able trade within a marketplace — set their own prices, have access to more assets etc.

So we brought what we thought was an improved P2P experience back into the app. However, this became overwhelming for people who just wanted to tap “buy” and keep it moving. A dilemma ensues:

  • Adding more “pro” features to the existing app made it difficult for “retail” users to understand what was going on.
  • Holding back “pro” features from the existing app wasn’t an option either. That would make us less appealing for the professional traders.

Furthermore, there’s actually a good amount of “liquidity symbiosis” between these user categories and the core functionality they wanted from Buycoins was the same — to buy, sell & store digital currencies — they just require different methods of delivery.

It became clear that we had to separate the experiences — and that, is a tricky problem to solve, because it meant two new applications.

Ionic had some snags

For one, it was becoming increasingly difficult for us at the time to find other Angular + ionic developers. This didn’t matter for a while, as we prioritise hiring front-end engineers who deeply understand HTML, CSS & JS, and as such, can pick up a new framework if necessary.

However, frameworks (especially Angular + Ionic) still take time to learn & we eventually had to do something about drastically shortening that barrier to first commit.

Note: Ionic now lets you build apps with React, Vue & vanilla JavaScript. Back then it was just Angular.

The main issue we had with Ionic was that the abstraction the framework provided from native web, iOS, and Android code started to become more of a hinderance than a help.

We would often come across issues with the generated, lower-level “native” that we just didn’t have the ability/developer resources to resolve because we could really only [easily] interface with Ionic itself.

This made debugging quite difficult, and meant that we resisted certain upgrades/changes that were available, for fear of unknown issues arising.

All this considered, Ionic was a great first step, and it enabled us to build quickly and efficiently but it couldn’t serve us long term.

In summary:

  • We needed to ship faster.
  • We needed a tech stack that appealed to a much broader subset of engineers or at the very least, was even easier to learn.
  • We needed flexibility & granular control of the UI.

Faster shipping with Hybrid Architecture

“Hybrid apps” come in many forms and “configurations”. The general idea is that with hybrid applications, a large part of the content is built with and possibly rendered using web technology.

Mobile apps like Notion & Amazon have always piqued our interest — they are able to push fixes & updates to a significant portion of their applications’ content without requiring users to download a new updates. This is because this content is being rendered by the web. They’re not “just websites” though, as they use native functionality and UI elements in varying degrees & as is required. You can read more about Basecamp’s approach here.

As with any rebuild, the first version will be largely imperfect & it’s important to be able to course correct rapidly. Furthermore, we wanted to have greater control of the UI and the ability to use native platform UI + device APIs wherever we desired.

React Native

For our hybrid approach, we needed a native “container” for the entire app. This was supposed to be the portion of the app that lets us build screens (entirely or partially) with native platform UI. It is also meant to house & communicate with every other part of the app that is to be rendered “over-the-wire” via the web.

React Native was a fantastic fit for this for the following reasons:

  • Using Kotlin/Java [for Android] & Swift [for iOS] would require us to manage 3 different codebases on the client side. With React Native, we get to manage just 2 — the “container” & the web application. Even with the existence of Buycoins Pro as a separate mobile application, we only have to deal with two repositories as the same container codebase can be used for both apps.
  • React Native has grown into a relatively very mature cross platform technology over the years. It possesses a thriving community with very many third party libraries. You’d be hard pressed to find something you can’t do with React Native.
  • Also, React is a wildly popular framework. According to the React Native docs: “React Native is like React, but it uses native components instead of web components as building blocks”. This makes it significantly easier to find & hire developers. And for existing web developers with strong JS, HTML & CSS backgrounds, it’s far less time consuming to learn.
  • Lastly, we wanted to render web content via platform specific WebViews. react-native-webview is a very well maintained & supported cross-platform WebView for React Native.

Server Side Rendering (SSR)

In a lot of scenarios, SSR results in faster load times. A major contributor to what slows down page load is JavaScript files. As such we try to serve only HTML & CSS as much as possible — a good percentage of pages in the new Buycoins apps have zero JavaScript.

Avoiding JavaScript entirely, however, is quite difficult to do if you desire to deliver a modern user experience — some UI components within a page need to be dynamic.

To reduce the deleterious effects of JavaScript on load times, we try to:

  • Have HTML & CSS as fallback where possible. This means that more (or even all) of the page loads as fast as possible.
  • Download the JavaScript asynchronously.

SSR is also beneficial [for performance] in a few other ways:

  • Older [Android] devices might struggle with data processing on the client side. Offloading such processing (usually looping through data) to the server solves this problem.
  • Focusing on delivering less JS & more HTML + CSS via SSR reduces browser incompatibility issues.

We accomplish this “SSR as much as possible” strategy with the following tools:

  • The server-side rendered web application is a Node.js + Express server.
  • EJS is used for templating.
  • React is used for wherever we need dynamic UI components.

That’s all folks!

Buycoins

Buycoins Pro

--

--

Timi Ajiboye
Helicarrier

I make stuff, mostly things that work on computers. CEO at Helicarrier (https://helicarrier.studio).