Behold my full-stack open-source heatmap based social app, made with React Native and Apollo GraphQL

Featuring: PostgreSQL, Mapbox, Firebase, Twilio, & Cloudinary

TL;DR: Get it 👉 here 👈

There’s a spicy story behind this amazing app and why I’ve decided to release it to the public. However, I think it would be more appropriate to tell about its tail in another post and keep this one as technical as possible. After all, this is what you came here for, no?

About the app

Hot&Cold (aka “the app”) is a social mobile app where you can publish statuses and have discussions around various topics. Kind of like Twitter, but for meeting people. At any time, you can create a status and drop it on the map, and wait for people to join a discussion around it.

Hot&Cold makes clever use of colors to differentiate between 2 types of statuses: “hot” statuses (colored pink) indicate that the creator of the status would like to meet, while “cold” statuses (colored light-blue) indicate that the creator of the status is looking to have an online discussion.

In addition, a live heatmap is rendered on top of the geographical map to indicate how popular a discussion around a specific status is. Statuses that have discussions with many participants and messages will have a big About its architectured cluster underneath them, as opposed to less popular statuses that will have a small blue cluster underneath them (again, note the “hot” and “cold” references).

About its implementation

  • The app tries to make use of React function components together with hooks API as much as possible.
  • The app uses Apollo-GraphQL for state management, together with Context API to hold instances of different kinds of services e.g. authentication and GPS.
  • The app uses an event emitter to detect responses from the GraphQL backend and link different side effects in the Apollo store.
  • The app uses GraphQL subscriptions to handle live updates e.g. updating chat messages.
  • The app uses react-navigation 4.x, with a custom hooks implementation on top of it, to handle navigation and transitions between screens. When I first started working on the app, version 5.x, with hooks support, was not yet available. Both work in a very similar way.
  • The app uses multiple routers to handle navigation inside composite screen views e.g. tabs navigation.
  • The app uses Firebase Cloud Messaging to handle push notifications.
  • The app uses Firebase Test Lab together with a custom test runner to run e2e tests (see bobcat).
  • The app uses an algorithm called packed Hilbert R-tree to handle spatial indexing and fast searching on the map (see flatbush).

As a side note, I wish I would have used Context API for theme and localization management. These are one of those things that I do now by default when creating a new app. In this app — it’s all hardcoded.

  • The app uses Sequelize as an ORM, which was later migrated into a raw PostresSQL client pg-promise. This allowed me to run more complex queries and configure them beyond the scope of Sequelize.
  • The app uses a custom implementation of one-time password SMS authentication. It uses Twilio to handle the actual text messaging.
  • The app uses Cloudinary to hold media assets. This is also useful for transforming the assets e.g. changing resolution or having round borders.
  • The app uses predefined geo polygons to index features on the map more optimally. Usually, a polygon would represent a city. Be sure to define your city of choice if you want it to be available on the app.
  • The app uses a custom dependency injection implementation (see container).

Download

The app is currently available for download on PlayStore.

Alternatively, the source code is available on GitHub:

Note that areas are manually defined for better spatial indexing. If you’re not able to log in to the app, you’re welcome to define a polygon of your city of choice in create-areas.js seed module.

Eytan is a JavaScript artist who comes from the land of the Promise(). His hobbies are eating, sleeping; and open-source… He loves open-source.