At OfferUp we believe in creating simple and intuitive experiences for our community. OfferUp’s mobile apps have been built on native platforms for years. As we started building the next set of capabilities for customers, it was clear that we were going to have to overhaul our apps with a lot of new features and experiences to delight our buyers and sellers, which gave us an opportunity to rethink our technology choices. We wanted to invest in technologies that could help us move faster by focusing on a smaller number of new industry-standard technologies.
OfferUp’s existing offerings have always been more focused on our mobile apps and our web experience has always lagged behind. We knew we wanted to change this to make the web app come to parity with mobile. As we started exploring our choices for the new tech stack, we agreed on some tenets.
Consistency: We should build uniform experiences across mobile and web.
Reusability: We will encourage and increase code reuse across all platforms.
Speed of development: The team should be able to ship quality mobile products on multiple platforms as fast as possible.
Future-proof: Our solution would work for not only our initial scope, but one we could use as we added complexity to our apps over the next few years.
Team compatible: All of our team members will be able to contribute uniformly to all platforms rather than just iOS, Android or Web.
Excellence of User Experience: The app should deliver a user experience as superior as the best native apps in terms of performance (60fps animations and transitions) and system integration (access to camera, push notifications and other device capabilities).
Well-supported: Our choice of technology should be well-adopted in the developer community.
We felt that maintaining separate codebases for iOS, Android and web would not be ideal and would not let us build at the pace we wanted, so we started looking at cross-platform options. As our apps added more features, we started realizing that our codebases started diverging and it became increasingly complex to keep them in sync.
We began by evaluating web views or Progressive Web Applications, frameworks like Cordova and Ionic, Flutter and the Dart programming language, and React JS and React Native. As we played with some prototypes, it became clear that React JS and React Native were the most mature and performant solutions out there. React is a well-adopted technology set that will not only help us build beautiful app experiences, but also excite our engineers to learn a cool new technology that could define the future of mobile development. It would also help us attract new, high-quality talent.
What is React Native and how does it work?
There are two important pieces to each React Native application:
There is a native engine, which runs in each standard native app and handles displaying the elements of the user interface and processes user gestures.
These two elements exist on separate threads and never communicate directly or block each other. Between these two threads lies a bridge which is the core that allows React Native to function.
The bridge has three important characteristics:
Asynchronous. It enables asynchronous communication between the threads. This ensures that they never block each other.
Batched. It transfers messages from one thread to the other in an optimized way.
Serializable. The two threads never share or operate with the same data. Instead, they exchange serialized messages.
Our path to the new OfferUp apps
While there are plenty of third-party npm packages available for almost any feature/functionality we realized that the team was interested in building our own packages and we encouraged their enthusiasm. This ensured that we could build our own custom experiences as well as provide engineers the gratification of building uniqueness to the platform.
We found out early enough that the team was interested in picking a unique challenge instead of using vanilla React Native to build the apps. We created a plan to create a React + React Native powered internal framework by building the right set of components, tools and infrastructure to make our development effective, efficient, and productive. We made some early decisions that have helped us:
Create a Design Language System. We created a standard set of interfaces, themes, styles and components that will be used across the entire app to ensure a consistent development pattern. Examples of this are our predefined color palettes, layout definitions, style guides and theming library.
Build a Universal Component Library. We built a set of primitive UI controls and widgets that are reused as building blocks across OfferUp screens. Even though the underlying rendering implementations differ between React and ReactNative, we make sure that we have a common interface for the client screens so that we can use a modular approach for defining our layouts.
Closely partner with design. The decisions to use a design language and Universal Component Library help us closely work with the design team. We use a tool called Storybook to share our components and definitions with the design organization. Design then uses these components to create the screen layouts thereby eliminating the possibility of a mismatch between design and implementation.
Expose backend via a GraphQL service. We decided to set up an Apollo GraphQL service which the client uses to connect with the backend APIs. Using GraphQL helps us consolidate multiple backend queries used for a single operation into 1 query from the client. The GraphQL layer then makes these queries, collects, filters, and collates the data into a single lightweight response payload that it can then send back to the client.
Invest in tooling and testing. We use tools like Jest, Detox, Appium, and Cucumber for our unit test and UI automation test frameworks. Cucumber lets us write automated tests in plain, easy to understand phrases allowing even non-technical people in the organization to write tests for common flows within the app.
Looking forward to our new experiences launching in the summer of 2020
Reducing the number of technologies has helped our team at OfferUp build a deeper expertise around a smaller set of core technologies. It has also helped us make sure we can focus on delivering a uniform experience using a single codebase for both mobile and web. Over the last few months our client engineering team has been building expertise in React technologies and overall we are excited that we made the right decision by switching to React/React Native. We are also planning to share our components and packages back to the React community so other developers can consume and contribute back to our efforts. We look forward to releasing the new OfferUp experience soon.
Sound fun? Come join us!
OfferUp is always hiring and we have a number of roles open across the organization in engineering, product and design. Check them out at https://about.offerup.com/careers/
Authored by Manuj Bahl