Building hopps.io

Screen Shot 2020-04-08 at 1.15.39 PM.png

In January I started helping my friend Aamir with his new startup, Hopps. Hopps is an on-demand service for real-time help. Hopps customers want to tackle their engineering or marketing problem instantly. Hopps experts provide the solutions Hopps customers seek. This blogpost is going to focus on the technology that powers Hopps and the content is best suited for web application developers. If you want to learn more about the product itself visit hopps.io.

Infrastructure #

One of the first questions to tackle is how to get code changes into and out of production in minutes. Most users won’t notice bugs you ship if you can fix them quickly. A fast deployment pipeline is like a Command+Z (Undo) shortcut for your product. It gives you the freedom to experiment with the ability to roll-back changes quickly. Get your product out as fast as possible and start using it. The day we shipped the audio, video, and screenshare features of Hopps we said goodbye to Slack calls and instead use Hopps to communicate with each other on a daily basis.

Screen Shot 2020-04-08 at 8.43.01 AM.png

Our latest changes deployed in 2 min, 21 sec

We use Github Actions for deployment. Code deploys on every commit. Commits to the develop branch go to a staging environment, master commits go straight to production. Hopps uses Docker containers to ensure our code runs reliably and is portable. Our web servers are vanilla AWS EC2 instances running Docker engine. The database is backed up nightly and prior to every deployment. In case of catastrophic failure, Hopps could be serving requests from new hardware within an hour.

Back-end #

NestJS powers the Hopps back-end. NestJS is an Angular inspired NodeJS web framework written in Typescript. I am not a fan of Angular, but I am a huge fan of Typescript and Typescript is a first class citizen in the NestJS world. NestJS is also extensible and versatile, two relatable adjectives when starting a company. Extensible because you can use existing libraries instead of re-inventing the wheel. Versatile because it is a Swiss army knife with caching, logging, database integration, web sockets and more baked in.

Screen Shot 2020-04-08 at 11.59.47 AM.png

GraphQL query and response for a Hopps session (all fields not present)

Hopps’ back-end is responsible for user authentication, maintaining current help sessions and help session history, dispatching notifications to experts and processing payments. Hopps uses GraphQL (NestJS has good support for GraphQL) to query and update server data. GraphQL subscriptions allow for real-time communication, meaning our pages update in real-time without the need to refresh. AWS Cognito is our authentication provider and we use JWT to grant authorization to create or join a session. We use Stripe to store and process payment information. AWS Simple Notification Service dispatches SMS notifications to our experts whenever a customer requests a session. Data is stored in MongoDB.

Front-end #

On the front-end we use React Native with Typescript. React Native is a framework for building mobile applications, but thanks to this clever library the same code also runs in a web browser. With this approach, it’s easy to release Hopps code in the Apple App Store and Google Play Store in the future.

Screen Shot 2020-04-10 at 11.50.29 AM.png

What a Hopps customer sees on the homepage

The front-end queries user and help session information from the server using Apollo GraphQL client. Apollo provides very nice tooling. With each back-end GraphQL schema change, the front-end automatically generates the corresponding Typescript typings. This means that if you mistype a query or field name the code won’t even compile. With real-time subscriptions over web sockets you can leave a Hopps tab open in the background and get a “chime” notification whenever someone requests a new session.

Typescript, Twilio, and AWS Cognito #

Typescript is amazing. If you develop in Javascript, don’t bother writing a single test until you migrate to Typescript. Similar to tests, the Typescript compiler ensures your current code is correct and reduces possible bugs in future code. It will keep new developers from breaking things as you scale the team. Not taking advantage of Typescript is like disabling your automatic spell checker and instead asking someone to proofread your writing. The proofreader may do a better job but the automatic spell checker will catch 98% of your mistakes instantly, free of charge.

Screen Shot 2020-04-09 at 6.39.54 PM.png

The core Hopps experience: audio + video + screen share + billable time

Twilio is at the core of every Hopps session. It provides a WebRTC signaling service for routing video, audio and screen sharing. Twilio provides good support for React and since the Covid-19 pandemic the ecosystem has advanced at a furious pace. Each Hopps session creates a dedicated Twilio Live Video room. Only authorized users are allowed to enter. An hour long session using Twilio Live Video API costs under 25 cents.

User authentication is a complicated beast. You need to setup an email server and SMS messaging service, then decide on a secure hashing algorithm and storage. Maybe you want to login with your Gmail account. Should you implement 2FA options and device fingerprinting for additional security? So much work before you even start to build the core functionality of your product. AWS Cognito does all of the above for you and that’s why we chose it. However, AWS Cognito is best suited for private applications like logging into private accounting software where different users do not interact. Making it work for Hopps users has not been trivial.

Thanks for reading #

Hope you enjoyed reading this. If you need engineering help or want to discuss your tech stack, you can find me on Hopps.

 
16
Kudos
 
16
Kudos

Now read this

NSA puzzle

My dad recently presented me with a puzzle. The puzzle consists of nine square tiles. Each tile edge has the top or bottom half of an Air Force, Army, Marines, or Navy emblem. The challenge is to arrange the tiles in a 3x3 grid where all... Continue →