Shopify’s React Native Standards, Straight From the Team

During the May 2021 edition of Shipit!, Shopify’s monthly event series, engineers Colin Gray, Haris Mahmood, Guil Varandas, and Michelle Fernandez fielded questions on building React Native apps at scale. The conversation covered state management, responsive layouts, testing, and what happens when apps hit the limits of the framework.

Styling and Layout Principles

Shopify leans on its internal Restyle library and the Polaris design system for decisions around accessibility, theming, and typography. The documentation for both is public and serves as a reference point for teams building their own design standards.

On sizing, the team’s guidance is straightforward: keep most things flexible unless a fixed size is absolutely necessary. Fixed dimensions are reserved for icons and imagery. For spacing, padding is used within a component, while margins handle the space between components.

Responsive layouts are handled through Restyle’s support for breakpoints. Styles can accept different values—for instance, font sizes or spacing—depending on the breakpoint defined, allowing UIs to adapt without hard-coded dimensions.

State and the Native Boundary

When integrating React Native with native code in a Brownfield context, the team treats React Native state as the single source of truth. At startup, the native module receives whatever it needs to begin work. Any shared state is managed in React Native and pushed to the native module, with updates coming back through an EventEmitter.

There is one notable exception in the Point of Sale app: the SQLite database is accessed entirely through a native module. Even then, only one source of truth exists—the native module handles its internal state, while shared state remains in React Native.

Shop’s main app and the Point of Sale app are both built with React Native from the ground up. However, Shopify does have a Brownfield app in progress where React Native views are being added incrementally. In that setup, existing native navigation controllers manage the flow—a deliberate choice that requires real integration work to wire up.

Testing and Tooling

Jest is the go-to framework for unit and integration tests at Shopify. For CI, the team uses Buildkite, with nightly builds generated automatically from the main branch. Those builds are uploaded to a test distribution platform where internal testers can opt in to always receive the latest version.

Quality assurance is a shared responsibility: all developers are accountable for checking the app and preventing regressions before release. A tool called ShipIt blocks feature branches with failing tests from merging to main. Some teams have evaluated the visual testing tool Loki, but it did not fit within Shopify’s CI constraints.

Framework Choices and Bugs

Shopify explored Expo early on but found that its apps quickly needed to “eject” from that workflow. The team ultimately settled on creating React Native applications as plain “vanilla” apps, though they encourage Expo for side projects.

As for bugs internal to React Native, the team relies on debugging and observability tools to spot crash patterns. They noted that encountering framework-internal issues is rare, and when it happens, the engineering teams use their expertise to understand and communicate the problem or contribute a fix upstream through standard open-source channels.

Questioned about animations, the team confirmed that Reanimated 2 is in production—the Shop app uses it today, including for the confetti effect that animates when deliveries arrive.

Further Reading

Shopify has published several resources on React Native development, including deep dives into Reanimated 2, managing native code, creating native components, and the future of mobile at the company.