My journey from simple MVP to the full stack mobile app with payments, subscriptions and daily premium content. On the way I tried more than 50 different tools and technologies (all listed below). Plus a few remarks on AWS Cloud, React Native and iOS deployment flow, enjoy!
- 🗄 Category: full stack mobile app (iOS and Android)
- 💰 Size: 50,000 - 200,000 PLN
- 🗓 Term: 05/2020 - 12/2021
- 🖥 Frontend: React Native, Ignite, Metro, Expo, TypeScript
- 🤖 Backend: Express, NodeJS, Serverless, AWS Lambda, Cognito, DynamoDB
MVP as hackathon
When I was invited to the Toba project it was at the conceptual stage. There was no team, no product or funding. A blank white sheet with a hazy vision of a business model. To facilitate fundraising and first usability tests, I conducted a two-day hackathon during which we managed to build a clickable prototype.
The app was created with a mobile-first approach. We decided to use React on the frontend and Material UI, which came along with ready-made components. Working on Safari enabled us to save the webpage as an app icon, which imitated native experience and made it possible to perform corridor tests and to show a working prototype to our initial investors.
On the backend we used Airtable, which is a spreadsheet on steroids. Thanks to that, admins could create and edit the content without touching the code. We deployed the whole stack to Netlify, which handled both hosting and communication with the API.
This informal hackathon resulted in the creation of a fully functional app with dynamic content and zero infrastructure cost. The app is publicly available at the following links:
Native Android and iOS
After about a year, the time had come to create a native app for Android and iOS. I decided to use React Native with Ignite boilerplate (to speed up development). Thanks to Ignite I had core components, state management and navigation out of the box. Ignite is written in a very clear way and aligned with the best practices of TypeScript. That saved me about two weeks of work.
After creating all visual components, I moved to the data layer. I quickly got into MobX State Tree and wrote models. Then, I moved to the API part. I used AWS Amplify from Amazon for authentication (nice UI lib) and API communication (not so nice, but still ok). Having most of the frontend ready, I started working on the backend…
AWS and Serverless Framework
My first approach to AWS was very promising. Thanks to Amplify I was able to create full registration and login flow in half a day. The complications began with implementing special requirements from business, such as an additional checkbox for marketing consent and guest accounts. Managing the user database was also a little inconvenient due to the low flexibility of Amplify.
After a few consultations with experienced Senior AWS Developers, I decided to switch from Amplify to Serverless Framework, which is perfect for small projects that need some flexibility. I still used Amplify UI on the frontend and I converted the backend configuration to the simplified version of CloudFormation - serverless.yml. Despite the use of serverless architecture, I had to do a lot of additional configuration, such as creating a local environment, database seeders and a simple app for testing endpoints. Each of these elements required digging through piles of documentation and often using some creative hacks (e.g. passing custom fields to the Authorizer or seeding the local database at startup).
Working with DynamoDB turned out to be problematic as well. I needed to upload CSV files to the database quite often, which was impossible through both the GUI and CLI. Eventually, I succeeded in writing custom scripts to automate my work with DynamoDB.
While facing so many challenges with the AWS stack, I had serious thoughts about dropping the serverless approach and simply writing the entire API myself and wrapping it in Docker. A few more consultations reassured me in my decision to stick with AWS. Ultimately, the cloud's biggest advantage is very low input costs and virtually infinite scalability.
Apple Store & Google Play
The final step in delivering the app was to upload it to the Apple Store and Google Play. Both of these platforms offer different ways to test and review your application and you need to spend some time reviewing the terms, dashboards, and test environments. Special attention must also be given to in-app payments which require appropriate permissions during account registration.
Although most of my work was concentrated on creating an iOS app, I was pleasantly surprised that the Android bundle worked from the first run. Thus I can give a seal of approval to React Native with their motto: "learn once, write anywhere". After passing the formal review, my application was published on both platforms proving my conviction that React Native is still a great choice for native applications, despite the growing popularity of other frameworks like Flutter or NativeScript.
What I used / what I learned
At the end I can recommend some tutorials I used during the development:
- Manage application state with MobX State Tree
- AWS Amplify and React Native tutorial
- Serverless, AWS Lambda, Amazon API Gateway, DynamoDB and Cognito
- Managing network connection in React Native
While working on this project, I used many different tools and technologies. List below shows a pretty wide scope of things you need to know, to create a simple subscription app with backend.
- React
- React Router
- Material UI
- Airtable
- Airtable REST API
- Netlify Deploy
- Netlify Site
- Netlify Functions
- TypeScript
- React Native
- Ignite (Infinite Red)
- React Animated
- React Navigation 6
- MobX-State-Tree
- MobX-React-Lite
- AsyncStorage
- InAppPurchase
- Amplify UI
- Amplify API
- Amplify Auth
- Reactotron
- Expo CLI
- Expo Go
- Expo Managed
- Expo Bare
- Metro
- Xcode
- Android Studio
- iPhone 11 simulator
- Pixel 2 simulator
- Apple Store
- Testflight
- Google Play
- Firebase Analytics
- AWS Console
- AWS Amplify
- AWS Cognito
- AWS Lambda
- AWS ApiGateway
- AWS DynamoDB
- NoSQL Workbench
- DynamoDump CLI
- CSV2JSON
- Serverless Framework
- Serverless Offline
- Serverless DynamoDB Local
- AWS CLI
- AWS SDK
- JavaScript
- NodeJS
- Express