Facebook Pixel

Developer blog

Notes from the inside.


development

The current tech stack of MOTI

There are a lot of pieces to making an app, most of which most users will never know or care about, and they shouldn't. Here's what we're using to make all the stuff we're working on...

Doppler

When you have a bunch of apps and services that all rely on the same set of services, like the database and auth services, you want to make it easier to manage all your environment secrets. We found Doppler was invaluable to be able to maintain multiple dev, staging, and production environments in one place. The Doppler CLI gets integrated into every project so you can easily pull in secrets into the project either locally during development, or during the CI/CD process when building. I can't recommend it enough.

Backend

As a frontend developer I'm pretty comfortable writing Javascript or Typescript. So when you're bootstrapping a company you go with what you know. The backend is written as a CRUD app using Fastify since at the time it was the fastest most extensible JS framework for building out the API.

The backend app is containerized with Docker so we can deploy it to AWS ECS using an automated CI/CD process with Github actions. A load balancer with autoscaling (with reasonable limits) lets us scale up and down as network traffic conditions change. We are also using Gitpod for remote development so we can work in an environment that will most closely resemble the deployed production environment.

A custom built CLI tool lets us deal with ECS, building docker images, and generally makes the CI/CD process less messy.

Mobile client app

The existing mobile app is written in Dart/Flutter for its cross platform benefits. We considered React Native also, but at the time of rebuilding the app we gambled that Flutter would give us consistent rendering across platforms, easier animations, and potentially a smoother UI. The major downside is you can't hot-load most updates like in React Native, needing a store approval for every small update.

The mobile (and desktop) app leans on a few core 3rd party services to make the most critical services more reliable. As we grow these services will be replaced by our own code, but for now they are worth their weight in gold.

  • Firebase Auth for username & password based auth.
  • Ably for realtime websocket communication.
  • Agora for video chat

Desktop client app

The desktop app is built with Electron for macOS and Windows and rendered with Svelte. I chose Svelte because I found it to be a superior alternative to React for building highly reactive apps, and we're not relying on 3rd party UI libraries. While Electron has some pretty high overhead, being able to use the latest Chrome web tech is a massive win and makes development pretty easy. The original hope was the Flutter app could be used for desktop which would give us our one codebase to rule them all, but in reality this app is too complex for that to happen, and Flutter on desktop just wasn't mature enough at the time we got started.

Web sites

Some internal tools and the marketing site are built using SvelteKit, which can directly communicate with the database if need be, or talk to our backend API on the server side. SvelteKit adapters make it so we can easily deploy to our own hosted Node server for the site you're reading right now. We develop these sites locally and deploy to production by pushing to the main branch on our GitHub repos.

For this blog we are using Sanity.io for basic content management of the posts.

Databases

We chose Google Firestore as our primary database which provides us with (mildly blazing) fast reads and high reliability. As a document database there are some challenges with needing to have duplicated data to make it fast, but there are always tradeoffs when it comes to that stuff. AWS OpenSearch is used as a caching database to make user searches quick and flexible.

Currently we are exploring the feasibility of switching our primary database to Postgres via Drizzle. We'll see if it makes sense to go that route since it requires a significant rewrite of the backend.