In the spring of 2020, we started working on the community tree watering project. It is a volunteer initiative whose goal is meaningful community care for urban greenery, specifically watering trees and saving water.
The zalejme.cz web application currently contains a database of more than one hundred thousand trees and allows users to interact with them. Due to the non-profit nature of the entire project, the main challenge proved to be coming up with an architecture supporting this functionality that wouldn't be too costly.
What solution did we choose?
There were many options to choose from, but in the end, the Amazon Web Services (AWS) platform won us over by providing specific services for free up to a certain limit. These limits were an important factor in the development--each major decision had to be considered in terms of resource usage. We often had to look for less straightforward paths. Uploading the trees to the database was one of the more difficult steps. Because the number of trees significantly exceeded the available transfer limit, we had to create a service that depleted it and then waited long enough for it to be fully filled until the entire dataset is loaded.
What challenges did we face?
One of the stumbling blocks when working with AWS is the rapid increase in the amount of must-have resources (databases, storage, interconnections) needed to add functionality. In order not to be completely overwhelmed with creating and managing individual resources and in order to make our work as easy as possible, we picked The Serverless Framework. It takes a lot of the organizational and devops work off our hands. Another advantage is the support of plugins, some of which we use to replicate the functionality of AWS in the local environment for the easiest possible development.
The depiction of the trees itself also turned out to be challenging. The usual approach to displaying a large amount of data on a map is to use a service that allows individual points to be integrated into the map tiles themselves and then downloaded as a whole, without the need for client processing. However, the application had an additional requirement--we wanted to change the state of these points (especially the color) several times a day depending on the newly calculated water demand. In addition, we were yet again financially limited.
Ultimately, this burden was transferred to the client which downloads a minimum list of all the trees from the server and then, depending on the location of the map, quickly draws only those that should actually be visible. Thus we have achieved solid performance on various devices and the minimum necessary investment.
How does the application work?
The user sees the map of the Czech Republic including the cooperating cities. By zooming in and out, he can switch between multiple view levels, ranging from cities through neighborhoods to individual trees. Clicking on a tree brings up a detailed view with color-coded info on its watering needs. There, the user can also tick that they’ve watered the tree and how much water they used (which will be reflected in subsequent data updates).
There are several things going on in the background. A couple of times an hour, we recalculate the water demand for individual trees, and every day we obtain and store new information about rainfall.
The aim is to motivate users to water trees regularly, especially those that are in urgent need of watering. To identify them, a self-improving algorithm will be used which already takes into account several factors, such as the width of the tree crown, historical precipitation in the area and more. As the amount of data increases and as we keep cooperating with specialists, we would like to further improve this calculation.
The project will soon be open source and available to the general public with the aim of acquiring new developers.
The final list of technologies is as follows:
- Backend: AWS Lambda functions in TypeScript
- Database: AWS DynamoDB
- Static storage: AWS S3
- API: AWS API Gateway
- Frontend: React (create-react-app) + TypeScript
- Mapping: Leaflet
- Weather: OpenWeatherMap