Luftcare

What is it?

Luftcare is the name of a project I started with a team at the 2018 NASA Space Apps Hackathon.
Our initial intention was to create an app for asthma patients that provided them with better tools for monitoring and improving their health.
Since the Hackathon spanned over a single weekend, I was responsible for creating a PoC app using Nativescript Vue.
Thankfully, our team was able to deliver most of what we had planned, including a smart inhaler prototype and my app. Also, we were local winners and global nominees! 🥳

Check out more about the Hackathon here.
Our smart inhaler prototype.Our smart inhaler prototype.
Our PoC app.Our PoC app.

How did it evolve?

After the Hackathon, we decided to keep working until we had a real product. We reduced our scope and focused on shipping a simple app for doctors to create and evaluate medical questionnaires.
At this point I decided to scrap our Nativescript app and look for a better solution, since the only reason why I chose Nativescript during the event was because I had just 48 hours and no experience with mobile development but a solid Vue background 🤷🏽‍♂️

The stack

A lot of research later, I eventually arrived at our tech stack. I chose Flutter for our mobile app, a GraphQL API with TypeGraphQL and a Vue + TS web client. Below I explore each decision and my experience with all the tech.

How our tech stack evolved over time, a Nativescript logo with an arrow pointing to three more logos, Vue, Flutter and GraphQL.How our tech stack evolved.

GraphQL API Github logo.

For the API, I decided to go with a combination of Typescript, TypeORM, TypeGraphQL and Apollo Server (plus Docker for the Postgres DB image).
My experience was a mixed bag, here are some highlights:

  • ✅ Going with Typescript made the codebase much more maintainable over time, incredibly useful.
  • ✅ Since I had multiple API consumers, choosing GraphQL over REST instantly addressed my over/underfetching concerns.
  • ✅ Using both TypeORM and TypeGraphQL's decorator approach was very nice, since I only had to create one class for each entity, see here.
  • 🚫 TypeGraphQL was very new at the time (at version 0.17.6), so related content was sparse. I had to go with whatever I thought was the best way to do things, facing problems not covered by guides, Stack Overflow or the official docs.
  • 🚫 While TypeGraphQL is very flexible, it can also be very tedious to implement. Creating every single input type/mutation/query can take a long time. I later discovered other approaches which did most of the heavy lifting for me, but it was too late to use in this project.

Vue Web Client Github logo.

Our web client was simple: a dashboard for doctors to create questionnaires and evaluate their responses. With that in mind, I decided to use Typescript, Vue 2 (Nuxt), Element UI, Tailwind CSS and Apollo Client with GraphQL Code Generator.
The experience here was overall more positive than in the API, here are some highlights:

  • ✅ The Vue + Element + Tailwind combo was great! I was flying through the screens using Element's pre-made components and making quick adjustments with Tailwind when needed.
  • GraphQL Codegen + Typescript was also great: by running a script I had the full API types. This made everything much more predictable and easier to maintain.
  • 🚫 Vue 2 + Typescript support could definitely be improved, but I don't consider this a problem currently since Vue 3's support is very good.
Our dashboard. A page containing a sidebar with multiple links, a large line graph and a table.Our dashboard.

Flutter App Github logo.

The app was also very straightforward. It had a login page, a home page with a listing of available and answered questionnaires, and the questionnaire answer pages. Since it consumed a GraphQL API, I used Artemis, a Dart type generator from GraphQL schemas and queries, which made the experience a lot more enjoyable. Here are some of the highlights:

  • Flutter (or any hybrid approach) was definitely the best decision, writing one code and getting two apps was essential for our time limitations.
  • Artemis was also very good: while the setup was more complicated, the generated types help out a lot in the long run.
Home page with questionnaires listing.Home page.
Questionnaire answering page.Questionnaire answering page.

Deployment

The API and Web Dashboard were deployed to a DigitalOcean droplet, and the Flutter App was published on app stores. The CI/CD was handled using Buddy.

Conclusion

The project was interrupted in 2020 due to health concerns over conducting research during the pandemic.
Still, it was fun while it lasted and a great learning opportunity for me. It was my first time doing a lot of things on my own. Like publishing a Flutter app, configuring a CI/CD workflow, and deploying an API/Web app publicly.
I gained a lot of experience and much of what I learned was useful later on.