Expo 101: Building mobile apps in weeks, not years
Tags: reactnative, expo, mobile, development
Published: 2022-02-17 11:11:55

---
title: Expo 101: Building mobile apps in weeks, not years
published: true
description: Mobile app development used to be painful. In this post, I talk about how Expo changed that forever.
tags: reactnative, expo, mobile, development
cover_image: https://i.imgur.com/3NGZLDt.png
canonical_url: https://blog.spirokit.com/expo-101-building-mobile-apps-in-weeks-not-years
---

Mobile app development used to be painful. 
In this post, I talk about how Expo changed that forever. 

At the end of this post, you'll get a solid understanding of the entire Expo ecosystem, and you'll be able to create your first app, add some features, build it in the cloud, and submit it for review in the stores.

- [A little bit of history](#a-little-bit-of-history)
  - [Working on mobile was a pain](#working-on-mobile-was-a-pain)
    - [Code reusability](#code-reusability)
    - [Signing and certificates](#signing-and-certificates)
    - [iOS development: a luxury for a few](#ios-development-a-luxury-for-a-few)
    - [Slow feedback loop](#slow-feedback-loop)
  - [Hybrid app development](#hybrid-app-development)
- [What is Expo?](#what-is-expo)
  - [Workflows](#workflows)
    - [Bare workflow](#bare-workflow)
    - [Managed workflow](#managed-workflow)
  - [Expo ecosystem](#expo-ecosystem)
    - [Expo CLI](#expo-cli)
    - [Expo Dev Tools](#expo-dev-tools)
    - [Expo Snack](#expo-snack)
    - [Expo Application Services (EAS)](#expo-application-services-eas)
    - [Over the air updates](#over-the-air-updates)
    - [Expo SDK](#expo-sdk)
- [I'm sold! Where should I start?](#im-sold-where-should-i-start)
  - [Bootstrapping a new project](#bootstrapping-a-new-project)
  - [Running your project on a real device](#running-your-project-on-a-real-device)
  - [Making changes in real-time with Expo Go](#making-changes-in-real-time-with-expo-go)
  - [Adding new functionality using the Expo SDK](#adding-new-functionality-using-the-expo-sdk)
  - [Building an app with Expo Application Services](#building-an-app-with-expo-application-services)
  - [Submitting your app to the store](#submitting-your-app-to-the-store)
- [Conclusions](#conclusions)
- [Shameless plug](#shameless-plug)
  
# A little bit of history
At the beginning of time, Mobile app development used to be quite complex. 

It required you to learn how to use new tools and programming languages and deal with a whole new range of problems (don't let me start on publishing and signing).

Documentation was scarce (and I'm being generous), and if you got stuck with an issue, your previous knowledge about web development was not instantly transferable. 

In other words, it was an entirely new world to discover (and tame)

---

## Working on mobile was a pain
The development experience used to be awful. Here are the main reasons that come to mind:

### Code reusability
Before hybrid app development was a thing, you needed to build two entirely different apps to support Android and iOS. 

In other words, zero code reusability, and it was twice as challenging to maintain your app.

### Signing and certificates
The signing process was tedious and entirely different for each platform.

If you were unlucky enough to have to deal with certificates in iOS, you would know it is a nightmare. Furthermore, certificates expire, meaning that you had to manually keep an eye on them to prevent issues.

### iOS development: a luxury for a few
If you wanted to build an iOS app, you needed a mac before starting. 

You could think this is not a big deal, especially if you live in a developed country. However, here in Argentina, the story is quite different. I can tell you I didn't know anyone with a mac in my entire childhood. 

Nowadays, it's way more common to see developers using a mac, but 10 years ago, it wasn't that common. So, iOS development was something restricted for those who could afford it.

### Slow feedback loop
With modern web development, we have instant feedback of our changes thanks to things like "hot reload": You make a change, and you immediately know if you screw something or if your change introduced a new bug.

Moreover, web apps are easy to test in different scenarios.

On native mobile development, you had to recompile the entire app after each change, and if you wanted to test your app on different devices, you had to publish it through the Store (at least in iOS). 

As an alternative, you could use emulators, but it was slow as hell, and sometimes it didn't reflect reality.

---

## Hybrid app development
Frameworks like Xamarin, Ionic, Apache Cordova, and PhoneGap appeared in 2011 (Xamarin was the first one). React Native came later in 2015.

It was a big thing, and those new frameworks helped improve the development experience a lot. Now, you could reuse part of your previous knowledge as a web developer to work on mobile, and, in some cases, you could build an entire app without dealing with native specific code at all.

Yet, compiling and publishing still was a pain, and you needed a mac for iOS. In addition, documentation was still poor, and performance comparison between a native app and a hybrid app was always discussed.

As an evolution for hybrid frameworks, Expo appeared a few years ago.

---
# What is Expo?
Expo is a Framework that allows you to build a React Native project that runs natively on any platform or device.

What is fantastic about Expo is that it allows you to instantly run your app using Expo Go, an app you can install on your Android or iOS device. 

In other words, you don't need to have a mac or to install anything on your PC besides Node. In fact, my primary workstation is running Linux, and I've been working with Expo for years without problems.

You have instant feedback thanks to Expo Go, which includes hot reload and keeps track of your current screen state.

Expo is also an ecosystem that includes a set of tools and services that drastically improves your development experience by taking care of annoying things like building, signing, and publishing your apps.

---
## Workflows
When building an app with Expo, you can use two different workflows. Both provide a very different experience and cover two totally different requirements.
![A brief summary of the key differences between the managed workflow and the bare workflow](https://i.imgur.com/YML6jEw.png)
### Bare workflow
This workflow is only recommended when you need absolute control over the native code of your app.

I can only recommend using it if you know you'll need to work with native packages not included in the Expo SDK or have a config plugin to work with Expo.

Keep in mind that, by using this workflow, you will need to handle all the complexity associated with the native code for each platform.
<br/>
### Managed workflow
- You build your app only using JavaScript or Typescript.
- You don't have to deal with native code at all.
- Expo handles building, signing, and publishing using different tools and services like Expo CLI or Expo Application Services (EAS)

This mode has its own limitations: Only packages included in the Expo SDK or native packages that include a config plugin will work with this workflow. 

This could sound like a huge roadblock, but most packages work with this workflow nowadays. 

Furthermore, Expo has been working on new features like [custom development clients](https://blog.expo.dev/introducing-custom-development-clients-5a2c79a9ddf8) and [config plugins](https://docs.expo.dev/guides/config-plugins/) to allow developers to adapt more and more libraries so you can use them with Expo.

If you are starting to work on a new project today, I highly recommend using the managed workflow. The Expo team is using all their energy to improve this workflow every day, and I've been using it for almost two years now, and I didn't find any significant limitations yet.

---
## Expo ecosystem

### Expo CLI
The Expo CLI is the interface between you (the developer) and the Expo ecosystem. You can use it for many different things, but if I had to mention the most important ones, I would say:
- Bootstrap new projects
- Run your expo project using Expo Go or Emulators.
- Install new packages from the expo SDK (More about this below)
- Upgrade your project SDK version.
- Build and sign your app (Only managed workflow). This service is known as the classic build service.
- Send Over-the-air updates (More about this below)

If you want to install the Expo CLI tool, just run the following command
```bash
npm install -g expo-cli
```

### Expo Dev Tools
Expo Dev Tools is a web browser-based control panel included in Expo CLI. With Expo Dev tools, you can:
- View logs from supporting services (Metro and Webpack bundlers)
- View logs from your device
- Scan a QR Code from Expo Go to quickly launch your app.
- Debug connectivity

This control panel will be opened every time you run the `expo start` command.

### Expo Snack
Expo Snack is an open-source platform for running React Native apps in the browser.
It handles compilation and bundling for you and allows you to run your app with Expo Go or in a web simulator.
You can easily save a piece of code as a "Snack" and share it with others.

Here's [an example of a Snack](https://snack.expo.dev/@maurogarcia0209/ed6411) a created for this post

### Expo Application Services (EAS)

Expo Application Services (EAS) is a set of cloud services that allows you to quickly build, sign and publish your app in the stores. 

I can't recommend it enough! Since day one, I've been using this service when it was in beta, and it has saved me hundreds of hours of pain.

It's divided into three different features:
- **EAS Build**: Compile and sign Android/iOS apps with custom native code in the cloud. [Learn more](https://docs.expo.dev/build/introduction/)
- **EAS Submit**: Upload your app to the Apple App Store or Google Play Store from the cloud with one CLI command. [Learn more](https://docs.expo.dev/submit/introduction/)
- **EAS Update** (preview): Address small bugs and push quick fixes directly to end-users without dealing with the tedious process of submitting your app for review. [Learn more](https://docs.expo.dev/eas-update/introduction/)

### Over the air updates
Over-the-air updates allow your app to receive updates without submitting and waiting for ages until Apple and Google review each change you made. These updates include your app's JavaScript and assets.

This feature has a few limitations: If you need to add new native packages or update your SDK version, you will need to rebuild and submit.

But for the daily patches and hotfixes, it will save you tons of hours, and more importantly, allow you to instantly respond to bugs in production.

### Expo SDK
The Expo SDK works like an extension of the React Native core package, and when I say extension, I'm not talking about only a few additional features. 

At the moment of this writing, the Expo SDK includes at least 100 packages. I would like to share a few examples of packages I use every day and save me tons of hours of work:
- [expo-firebase-analytics](https://docs.expo.dev/versions/latest/sdk/firebase-analytics/): Enables the use of native Google Analytics for Firebase.
- [expo-file-system](https://docs.expo.dev/versions/latest/sdk/filesystem/):  Provides access to a file system stored locally on the device. It also allows you to download and upload files from network URLs.
- [expo-document-picker](https://docs.expo.dev/versions/latest/sdk/document-picker/) and [expo-image-picker](https://docs.expo.dev/versions/latest/sdk/imagepicker/): Provide access to the system's UI for selecting images, videos and documents.
- [expo-localization](https://docs.expo.dev/versions/latest/sdk/localization/): Allows you to localize your app, customizing the experience for specific regions or languages.
- [expo-linking](https://docs.expo.dev/guides/linking/): Easily setup deep linking both with a custom scheme or using HTTPS.
- [expo-device](https://docs.expo.dev/versions/latest/sdk/device/): Provides access to system information about the physical device, such as its manufacturer and model.
- [expo-font](https://docs.expo.dev/versions/v44.0.0/sdk/font/): Allows loading fonts from the web and using them in React Native components. See more detailed usage information in the [Fonts](https://docs.expo.dev/guides/using-custom-fonts/) guide.
  
---

# I'm sold! Where should I start?
I already mentioned a lot of different tools and services, and it could be a little bit daunting at first. 

I'll show you how to combine all these tools in a project.
![The Expo ecosystem in action. 6 steps from bootstrapping your project to submitting your app for review](https://i.imgur.com/Y2uf9Qj.png)
<br/>
## Bootstrapping a new project

Let's start by installing the Expo CLI globally on your machine by running the following command on your terminal
```shell
npm install -g expo-cli
```

Now, we can create a new Expo project like this
```shell
expo init
```

> You can use the optional flag --yarn if you prefer yarn over npm

The Expo CLI will ask you your project's name, which template you want to use, and a few more preferences.
<br/>
## Running your project on a real device

After the `expo init` finished, cd into your new project and run the `npm start` command. This will run `expo start` behind the scenes.

This will start a local server for your app, opening your web browser with the control panel.

Go to your Android or iOS device, and **install Expo Go from the store**.

Open Expo Go on your phone, and **scan the QR code** available in the web control panel.

Wait until your phone finishes downloading all the js files, and that's it! Your first app is already running on your phone.
<br/>
## Making changes in real-time with Expo Go

With your app still running on your phone, go to your `App.js` or `App.tsx` file and make a small change like this one:
```diff
import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View } from "react-native";

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.tsx to start working on your app!</Text>
+     <Text style={{ backgroundColor: "red", color: "white" }}>
+       This is a custom text with red background!
+     </Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});
```

Not hit save, and take a look at your phone.

![mind blown meme](https://media.giphy.com/media/V0IdVIIW1y5d6/giphy.gif)

Your changes are instantly available on your phone. Magic.
<br/>
## Adding new functionality using the Expo SDK

Let's say we want to grab a few details about the user device and show this data on a screen.

We will leverage the Expo SDK for that, and more specifically, we'll use the [expo-device](https://docs.expo.dev/versions/latest/sdk/device/) package mentioned above.

Using the Expo CLI again, run the following command on your terminal:

```bash
expo install expo-device
```

Now, go to your `App.js` or `App.tsx` file and add the following lines:

```diff
import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View } from "react-native";
+ import * as Device from "expo-device";

export default function App() {
  return (
    <View style={styles.container}>
-     <Text>Open up App.tsx to start working on your app!</Text>
+     <Text>Brand: {Device.brand}</Text>
+     <Text>Manufacturer: {Device.manufacturer}</Text>
+     <Text>Model name: {Device.modelName}</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});
```

If everything went as expected, you should see something like this on your phone:
![Minimal example of expo-device package working on an iOS device](https://i.imgur.com/x2smkZj.jpg)
Congrats! You integrated your first package from the Expo SDK into your project.

As I mentioned above, there are 100+ packages available in the Expo SDK, which means you can unlock unlimited potential for your next project in minutes.
<br/>
## Building an app with Expo Application Services
Our handy app that shows information about your device is ready. 
The next step is to generate a build and try our app without Expo Go.

We are going to leverage Expo Application Services for that.


1. To use EAS, you will need to install the `eas-cli` package globally. Go to your terminal and run the following command.
```shell
npm install -g eas-cli
```
2. Visit [https://expo.dev](https://expo.dev) and Sign up to start using EAS. The free plan already includes everything you need if you are an indie hacker working on your own apps.
3. Once you have created your account, go to the terminal and login using the `eas login` command.
4. Still in the terminal, navigate to your project's directory and run the `eas build:configure` command to configure your project to run on EAS build. Please follow [this link](https://docs.expo.dev/build-reference/build-configuration/) if you want to learn more about this. After finishing this configuration. You will get a new `eas.json` file in the root directory of your current project.
5. Go to your `app.json` file and configure your `android.package` and `ios.bundleIdentifier` props. EAS will prompt you to specify them.
6. If you are using iOS, you will need to register your iPhone device first. This will only take you a minute. Run the `eas device:create` command and follow the instructions. You will get a link to open on your phone and install a required certificate.
7. Run the `eas build --profile development --platform android` or `eas build --profile development --platform ios` to generate your first build in the cloud. Expo will handle all the heavy lifting for you by creating the required certificates, signing your app for you, and starting building your app in the cloud. You'll get a link where you can follow the progress of your build.
8. After finishing building, you can download the apk (if you targeted Android) or copy the link to install your app on iOS.
<br/>
## Submitting your app to the store
After building and testing your app to check that everything is working as expected, we are ready to submit.

Again, EAS will handle this for you. Just run the `eas submit --platform [Your platform]`.

EAS will use your latest build for the submission by default, but you can manually specify a previous build if you want. To learn more about the available options, run the `eas submit --help` command. 

---

# Conclusions
Congrats! If everything went as expected, your app was already submitted 🥳️ .
What I love about the Expo ecosystem is that you get a tool for each stage of your project:
- Do you need to create a new project or add Expo to an existing React Native app? You can use Expo-CLI for that.
- Do you need to add new features to your app? You have 100+ packages already included in the Expo SDK.
- Do you need to build and sign your app? Use EAS Build
- Ready to submit? EAS Submit got your back.
- Do you need to quickly fix an error in production? EAS Update allows you to push your js changes without submitting your app again.
  
---

# Shameless plug
![SpiroKit design system](https://i.imgur.com/Ott9Jm6.png)
Last year I released my own design system. It's called [SpiroKit](https://spirokit.com)
If you need a UI kit to prototype your next app, you can use SpiroKit's Figma template.

I'm currently building the React Native UI library for SpiroKit, so If you want to learn more about it, [follow me on Twitter](https://twitter.com/mauro_codes), when I'm building everything in public, sharing weekly updates about the project.