Toronto water monitor

Made with

  • React
  • typescript-icon.svg logo
  • SASS
  • Node.js
  • SQL
Screenshot of toronto water monitor project on the Safari browser


My family got a high water bill from a leaking toilet. This project will prevent that from happening again. I also hope to share it with others so that they don't get high water bills.

Tech stack

Back-end: I want to refine my fundamentals so I used Node.js, TypeScript, Express and PostgreSQL. To deploy, I used Heroku, which brings all of these technologies under one roof.

Front-end: I used React (create-react-app), Formik and Material UI. I really like how the label shrinks when you select a form input (video). However, I hit a limit to the design: a tooltip can't be added in-line because once minified, the tooltip would be too small to be interacted with on a touch device.

Thought process

First, I looked for existing solutions. There are affordable alarms that detect flooding but wouldn't catch a leaking toilet. There are also really expensive solutions that can measure water usage. Finally, I discovered that the city of Toronto has a tool called MyWaterToronto where you can look at your water usage.

The next step was getting the right API calls to get the data. With Postman, it was really easy. I didn't have to login and didn't need to use Puppeteer to automate any UI steps!


Screenshot emails sent by the app

Emailing is really expensive. I looked at Twilio's SendGrid and they had nice docs. However, I eventually implemented everything with Nodemailer, a Node.js package that sends emails for these reasons.

  • I would have to keep track of two email lists
  • in my database
  • with the external service
  • I wanted to keep things simple
  • I didn't like the daily 100 email limit
  • I don't need additional features like the click through rate
  • Twilio SendGrid's aim appears to be catered towards sending batch emails which this app does not do

Unsubscribe link

Screenshot of the welcome email

Another challenge was the unsubscribe link in the email. I don't fully understand how MailChimp and other mail clients do single click unsubscribe. I know that the single click is critical to delivering a better user experience. However, I don't know how MailChimp handles the scenario where the email client pre-fetches URLs. I also know that GET requests should never make a change to the database and MailChimp seems to be getting away with this violation by redirecting the GET request to a POST request.

So I did what felt was the right thing to do: have the unsubscribe email link direct the user to a page with a form where they have to enter their email


I have unit tests for the validation of incoming data.

I have a test that I can manually enable that will send the two types of emails to my personal email address.

Finally, I test the database operations.

Heroku doesn't have a cron job so I used the Heroku daily scheduler to check make the Toronto API calls.

Next steps

I am preparing to talk to people from Civic Tech Toronto and determine what improvements should be made.

I'm also going to make a post on the r/Toronto subreddit.

Other projects