Tequila-powered X-Platform development with Expo

July 12, 2019 - 8 min

What happens when you mix a bit of Tequila with Expo and Next.js? You obtain a nice Margarita, a subtle cocktail of cross-platform goodness!

Sorry what?

Margarita cocktail, Photo by DESIGNbyJA from Pexels An instance of Margarita, a wild cocktail.
Photo by DESIGNbyJA from Pexels

This is an account of my experience working on Margarita with Expo at Kiwi.com. I will first provide some context for this project and will then explain in more details what I loved about Expo and what could still be improved/expanded.

Tequila + Expo + Next.js = Margarita

Tequila is Kiwi.com’s online B2B platform which launched in November, 2018. Among its features comes the Tequila API. It is a free API allowing us developers to search and book flights on Kiwi.com. What’s more, you get a comission on each booking coming from your API calls.

You could essentially start your own online travel agency.

Since Tequila is based off Kiwi.com’s infrastructure, your OTA venture is just API calls away:

Let us deal with all the upstream complexity, the content aggregation from multiple sources, the ticketing fulfilment, and the first- and second-level customer support. This is all carried out through fast, accurate, powerful and comprehensive APIs that are just a few clicks away for the partner-to-be.

~ Kiwi.com’s Tequila presentation

You just need to set up a front-end to get going.

To help you do that, we decided to create an open-source front-end example of how to use and consume the Tequila API. Margarita was born.

It is a cross-platform application, available on iOS, Android and the web. This is achieved in the same codebase and most of the code is shared. For example, that’s how you could use the Search scene:

import { Search } from '@kiwicom/margarita-core';

Importing Search scene from @kiwicom/margarita-core package Importing Search scene from @kiwicom/margarita-core package

This application allows users to search for one-way or return flights and book their trips for the whole family. There is an account system for the users to manage their bookings.

Note however that not all these features are totally complete and production-ready: it’s up to you to remix Margarita to suit your needs!
In addition, not all features of the Tequila API are available on the GraphQL proxy, e.g. Multi-city search and traveling salesman (NOMAD) search are missing.


This project was made possible thanks to Expo and Next.js (even though you could do everything with Expo now that SDK 33 is out!) To delve a bit more into details, here is Margarita’s tech stack:

  • React Native (through Expo) for Android and iOS,
  • React Native Web and Next.js for the web version,
  • GraphQL with the Relay client to access the Tequila API,
  • Firebase SDK to handle accounts.

Gracefully transition from React to React Native with Expo

We really loved how easy it was to get started with Expo; unlike react-native init which exposes the ios/ and android/ folders with scary Objective C/Swift and Java/Kotlin code, expo init keeps you in the known realms of JavaScript.

That meant that React developers who joined us on Margarita could be on-boarded very quickly.

In addition, they could test the platform and their ideas painlessly through Expo’s online code editor, Snack, and see the results on their devices in no time!

I sure do remember my first time testing Expo through Snack: I made my phone vibrate in less than one minute, and I could not be more excited!

The Workspace challenge

It was however challenging to set up Expo with Yarn Workspaces. After a lot of Googling around, we came up with some solution but it feels a bit hacky and not future-proof.

This setup imposes some strict constraints on your dependencies too: if you have several React Native apps in your workspaces, they must all have the same versions imposed by the Expo SDK.

Similarly, a new version of Next.js required a newer version of React, while Expo SDK 32 preferred the older one. That means upgrading dependencies can be painful at times and tools like Dependabot end up not being useful.

This pinning of versions of dependencies meant as well that we could not surf the React Hooks hype… our FOMO was real! 😜 Luckily for all of us, SDK 33 is finally out!

Man carrying white surfboard, Photo by Maria Perez from Pexels No hype surfing, all the sadness.
Photo by Maria Perez from Pexels

Sharing is caring

Since we wanted to share our progress with stakeholders and whoever else was interested in the project, we easily automated releasing the iOS and Android apps through expo publish, and Netlify, carefully watching our repo, took care of the web version.

To support our project and experiment with bringing Kiwi.com’s design system to React Native (while also being usable in React!), we also created Universal Components. It’s a component library implementing that design system, written with React Native’s primitives, and usable on the web thanks to React Native Web.

As for Margarita’s deployment, the component library’s React Native Storybook is published to Expo (also through CircleCI) and the web version of the Storybook is also taken care of by Netlify. This was great to ask for feedback from designers and UX designers: they could install the Storybook on their device and play with the components.

Menu group component on web and mobile Storybook Menu group component on web and mobile Storybook

One downside to effectively share the React Native Storybook was that iPhone users had to sign in on Expo through a shared account to get the app running as the QR code scanning functionality does not work otherwise (looking at you, Apple!).

It would have been great to have some kind of team account functionality so that sharing credentials would not be necessary and the published app would be available to all team members, even iPhone users. In addition, this could support a private app section for the given team, though you could use turtle-cli to build your apps privately.

Font family dramas

Out of the extensive list of APIs Expo offers, we used MapView, Google and Font. They worked great but we struggled a little bit with custom fonts. Our design system requires to use a paid font on Kiwi.com’s domains and Roboto otherwise. Luckily for us, Expo’s documentation covered this case.

However, we did not anticipate at the time that React Native works slightly differently and we had to add specific logic to our Text wrapper to select the right font family so that our component library would work as expected on both React Native and Expo projects.

Font problem in button: bold on web but not on mobile Button component not bold on mobile because it’s missing expo prop in rendered Text used.

For example, we needed to specify font families such as RobotoItalicBold in Expo, whereas React Native would expect font family Roboto with fontWeight: "bold" and fontStyle: "italic".

The future is bright for Expo

Despite these few limitations, we had a great time building Margarita and Expo is amazing to kickstart projects! Even more so now that the Expo specific APIs are available in React Native apps through react-native-unimodules. That means that there’s no vendor lock-in anymore: if you ever need to add native dependencies, you can eject your project at a later time without too much trouble to get everything working the same.

With the web being an officially supported platform since the release of SDK 33, it looks like it’s going to be the default for cross-platform development!

It is definitely challenging:

  • checking your changes on all three platforms,
  • setting up a proper testing environment,
  • dealing in a “universal” way with platform or library quirks,
  • and more…

It’s also very rewarding:

  • one codebase to maintain,
  • a great opportunity to learn each platform through its differences with other platforms,
  • you’re an early hype surfer!

Grinning man carrying white surfboard, Photo by Daria Shevtsova from Pexels That smile will never leave your face, pinky promise.
Photo by Daria Shevtsova from Pexels

If you’d like some inspiration, I highly recommend you check out Evan Bacon (@baconbrix) on Twitter; he regularly posts his newest experiments and they look amazing!

Where to go from here?

To learn more about the stack and play with cross-platform development, I encourage you to either clone Margarita (you don’t need to open your own travel agency for that!) or you could follow the steps of a workshop that my colleague Josef Duda and I gave in Budapest, Hungary at the end of May 2019.

Either way, thank you for reading this far! If you have any questions or feedback, feel free to reach out to me on Twitter or create issues in the different repositories.


Robin Cussol

Personal blog written by Robin Cussol
I like math and I like code. Oh, and writing too.