Building an offline first PWA
— volt, PWA, Typescript — 3 min read
As a volounteer for Volt I was asked to help make an app to keep track of where campaign posters are for the german elections. The had a clear set of requirements:
- it should with no or terrible internet connection
- it needs to store geopoints of locations of posters
- it needs to be able to show a map with the locations
- it must be possible to for members of Volt to invite other people to join the campaign
This was beginning of 2021, getting these requirements straight in a volounteer organisation was not easy. I learned a lot about how to get things done in a volounteer organisation. But in the end we had a clear set of goals.
I decided to use ViteJS to build an offline first PWA. Vite is a build tool that uses esbuild to bundle the code. It is fast and has some great features for building PWAs. For language I always use Typescript, as I like the type safety it provides. All in all this was nothing new for me.
ReactJS with RXDB provided the remainder of the stack. If you are wondering what CSS framework I used, I didnt. After trying out a few I decided to just use plain CSS. I like the idea of using a framework, if it helps me to build a UI faster. But I always end up with stuck in documentations, and adding a bunch of custom CSS to fix things to do what I want. So I decided to just use plain CSS.
Actually the decision was not quite mine, I asked some of my developer friends from Withlocals to help build the app. They are all very experienced developers, and I wanted to learn from them. So i provided 2 days of BBQ food, beer and a place to sleep and we made it the first fun weekend after a long pandemic lockdown. This was May 2021.
All in all the relieve to be able to be outside, in the sun, with BBQ and beer provided a big distraction from the work. But we managed to get a working app in 2 days. They really helped me a lot with the design, and styling. The whole thing looks really great now.
The app is deployed fully serverless, only an EC2 bastion instance is used to provide access to the database directly. The backend is deployed to AWS Lambda using Postgraphile, the database is a Serveless Aurora Postgres instance, and the frontend is deployed to S3 and Cloudfront. The whole thing only costs money when its actuall used.
Building the first working version was more work than I expected. But I am happy with the result. In hindsight using RXDB with a postgraphile backend was good idea, but syncing is a bit of a pain. I will write a follow up post about the syncing issues. In summary however, a basic mockup was done in a couple days, getting the whole app to work nicely including syncing, offline-first etc, took a couple more weeks after work time.
The year after I spent quite some time adding logic for tracking flyer distribution. However it seemed nobody needed that feature, so I stopped working on it. I have had to bugfix some things the app a couple times since then, but it is still working.
Lessons learned: syncing apps to servers is hard, but doable. This project made me fall in love with Postgres and Postgraphile.