How to Build an Eco-friendly Reminder Service with Twilio SMS

April 27, 2023
Written by
Python Code Nemesis
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by
Mia Adjei
Twilion

How to Build an Eco-friendly Reminder Service with Twilio SMS

This article is for reference only. We're not onboarding new customers to Programmable Video. Existing customers can continue to use the product until December 5, 2024.


We recommend migrating your application to the API provided by our preferred video partner, Zoom. We've prepared this migration guide to assist you in minimizing any service disruption.

In this article, you will create a subscription-based Eco Friendly Reminder Service Application with Twilio for Earth Day using Flask for the backend, React for the frontend and the Twilio SMS API for sending messages. This application is aimed to help individuals develop and maintain eco-friendly habits by providing regular reminders, tips, and suggestions for sustainable living.

Agenda

To follow this tutorial, you will need the following prerequisites:

  • Python 3.x installed
  • Node.js and npm installed

Here is what this tutorial will cover:

  • Introduction to Twilio
  • Get a free Twilio number
  • Create backend REST API with Flask and Python
  • Create frontend UI with React.js
  • Run both simultaneously
  • Test the application by subscribing to Eco Friendly Reminder Service

Learn about Twilio

Twilio is a cloud communications platform that allows developers to build and integrate communication capabilities such as voice, messaging, and video into their applications. Twilio’s APIs are used to send and receive text messages, make and receive phone calls, and handle other types of communication, all from within the developer’s application.

Twilio provides a number of services and APIs that enable developers to build communication functionality into their applications. These services include:

  • Programmable Voice: Allows developers to add voice calling capabilities to their applications.
  • Programmable Messaging: Enables developers to send and receive SMS and MMS messages.
  • Programmable Video: Provides APIs for building real-time video and audio communication into applications.
  • Twilio Flex: A programmable contact center platform that enables developers to build custom contact center applications.
  • Twilio SendGrid: A cloud-based email delivery platform that provides APIs for sending transactional and marketing emails.

Twilio is used by a wide variety of organizations, including startups and large enterprises, to build custom communication functionality into their applications. For example, a business may use Twilio’s messaging API to send text message notifications to customers or use the voice API to build an interactive voice response (IVR) system. Twilio is also used by non-profits and other organizations to build communication capabilities for social impact, such as crisis response and disaster relief.

Get a free Twilio number

If you are new to Twilio, follow the steps below to get started. If you already have a Twilio account and Twilio phone number, feel free to skip to the next section.

To get a free Twilio number, sign up for a Twilio account. Sign up for a free Twilio account here.

Twilio signup

After sign up is completed, a free Twilio number is generated which can be used to integrate and test Twilio APIs. There is a lot of sample code available in different languages like JavaScript and Python.

Twilio Console, showing Send your first SMS step

To test a trial account by sending SMS or calls to someone else, you will need to verify your phone number first. Click on the "verify their number" hyperlink to navigate to that screen and verify the number with a one-time password.

Verify Number

Enter your phone number and select a mode for verification:

Add a Caller ID Page

After phone number verification is complete, the number will be displayed on the Verified Caller IDs screen:

Verified Caller ID pages

On the Twilio Console, your account information, including the Account SID, the Auth Token, and your Twilio Phone number, will be visible. This will be useful when creating the Flask REST API to send an automated SMS to a number from Twilio.

Twilio Account information page

Project setup

Once the Twilio Account setup is complete, the backend code to create a REST API with Flask and Python comes next.

For easier code maintenance and versioning, you can create a GitHub repository. It can be cloned locally, and all changes made there, which can be pushed to the remote repository periodically. This is so that no progress is lost and changes can be easily rolled back.

To do this, create a new GitHub repository called TwilioPythonEarthDay.

Next, follow the instructions in the GitHub documentation to generate a fine-grained personal access token for GitHub. Choose TwilioPythonEarthDay under Repository access by selecting Only select repositories and searching for this repository in the list. Then, under Permissions, scroll down to the Contents section and select Read and write in the dropdown field, so you will be able to get and push code to the repository.

Once you have generated your personal access token, copy it and keep it in a safe place, as it will not be shown again.

Clone the repository locally by running the following command, replacing <YOUR_GITHUB_USERNAME> and <YOUR_PERSONAL_ACCESS_TOKEN> with your own username and personal access token, respectively :

git clone https://<YOUR_GITHUB_USERNAME>:<YOUR_PERSONAL_ACCESS_TOKEN>@github.com/<YOUR_GITHUB_USERNAME>/TwilioPythonEarthDay.git

Once you have cloned the repository, change into the TwilioPythonEarthDay directory:

cd TwilioPythonEarthDay

To set up the remote repository to keep track with the main branch, run this command:

git remote set-url origin https://<YOUR_GITHUB_USERNAME>:<YOUR_PERSONAL_ACCESS_TOKEN>@github.com/<YOUR_GITHUB_USERNAME>/TwilioPythonEarthDay.git

Backend REST API with Flask and Python

Inside the TwilioPythonEarthDay directory, create a folder named backend and enter it:

mkdir backend
cd backend

Inside this folder, create and activate a new Python virtual environment, and then install the dependencies you will need for this project. If you are on a Unix or macOS system, run the following commands to do this:

python3 -m venv venv
source venv/bin/activate
pip install twilio flask flask_apscheduler flask_cors 

If you following this tutorial on a Windows machine, run the following commands instead:

python -m venv venv
venv\Scripts\activate
pip install twilio flask flask_apscheduler flask_cors 

For the code you'll write in this tutorial to work, you will also need to set a few environment variables. Set the following environment variables, replacing the placeholder text with your values for Account SID, Auth Token, and Twilio phone number. You can find these in the Twilio Console:

export TWILIO_ACCOUNT_SID="XXXXXXXXXXXXX"
export TWILIO_AUTH_TOKEN="XXXXXXXXXXXXX"
export TWILIO_PHONE_NUMBER="+XXXXXXXXXX"

Create a file called app.py and add the following code:

import os
from flask import Flask, request
from flask_cors import CORS, cross_origin
from twilio.rest import Client
from flask_apscheduler import APScheduler
import random

app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
scheduler = APScheduler()

# Your Twilio account sid and auth token
client = Client(os.environ.get('TWILIO_ACCOUNT_SID'), os.environ.get('TWILIO_AUTH_TOKEN') )


# A list to store phone numbers and frequency of reminders
subscribers = []
# list of strings
eco_reminders = [
    "Compost food scraps and yard waste to reduce landfill waste",
    "Use reusable water bottles and coffee cups",
    "Switch to LED light bulbs to save energy",
    "Buy local and in-season produce to reduce carbon emissions from transportation",
    "Take public transportation or walk instead of driving whenever possible",
    "Fix leaky faucets to conserve water",
    "Donate or repurpose unwanted items instead of throwing them away",
    "Choose environmentally-friendly cleaning products",
    "Reduce meat consumption to reduce the environmental impact of livestock farming",
    "Use a clothesline to dry clothes instead of a dryer",
    "Take steps to reduce energy consumption in your home, such as adding insulation",
    "Avoid single-use plastics such as straws, utensils, and packaging",
    "Plant a vegetable garden to grow your own food",
    "Shop at secondhand stores to reduce the environmental impact of fast fashion",
    "Turn off the tap while brushing your teeth to conserve water",
    "Use a reusable razor or electric shaver instead of disposable razors",
    "Choose to walk or bike for short trips instead of using a car",
    "Use natural lighting whenever possible instead of turning on lights",
    "Buy products with minimal packaging to reduce waste",
    "Take public transportation, carpool, or work from home to reduce your carbon footprint"
]

def send_reminders(phone_number):
    eco_reminder=random.choice(eco_reminders)

    message = client.messages.create(
        to=phone_number,
        from_=os.environ.get('TWILIO_PHONE_NUMBER',),
        body=eco_reminder
    )
    print("Message sent!")



@app.route("/sign-up", methods=["POST"])
@cross_origin()
def sign_up():
    data = request.get_json()
    phone_number = data["phoneNumber"]
    frequency = data["frequency"]
    print(phone_number)

    # Add the phone number and frequency to the subscribers list
    subscribers.append({"phone_number": phone_number, "frequency": frequency})

    # Send a confirmation message to the user
    message = client.messages.create(
        to=phone_number,
        from_=os.environ.get('TWILIO_PHONE_NUMBER',),
        body="Successfully signed up for eco-friendly reminders!"
    )

    scheduler.add_job(id = 'Scheduled Task', func=send_reminders, args = [phone_number], trigger="interval", minutes=int(frequency))
    print("send message to",phone_number,"with frequency",frequency)

    return "{\"status\" : \"ok\"}", 200


if __name__ == "__main__":
    # Schedule the send_reminders function to run at the frequency specified by the user
    scheduler.start()
    app.run(debug=True)

Here is an explanation of each part of the code:

The send_reminders function takes a phone number as input and sends a randomly selected eco-friendly reminder to that phone number using the Twilio client. The function selects a random message from the eco_reminders list defined earlier in the code. The message is sent using the client.messages.create method, and a confirmation message is printed to the console when the message is sent.

The /sign-up route is defined using the @app.route decorator. This route accepts HTTP POST requests containing JSON data with the phone number and frequency of the desired reminders. When a request is received, the sign_up function is called. The function retrieves the phone number and frequency from the JSON data and adds them to the subscribers list. A confirmation message is sent to the user using the Twilio client, and a scheduled task is created using the scheduler.add_job method to send reminders to the user at the specified frequency.

The scheduler.start() method is called to start the scheduler, and the Flask application is run using the app.run() method with the debug=True parameter to enable debugging mode.

Overall, the code sets up a Flask web application that allows users to sign up for eco-friendly reminders via SMS. When a user signs up, their phone number and desired reminder frequency are added to a list of subscribers, and a scheduled task is created to send reminders to the user at the specified frequency. The reminders themselves are randomly selected from a list of pre-defined messages, and are sent using the Twilio API.

That’s it, you are done with the backend code for the Flask server.

Now, you can run the server with the following command:

flask run

If all is working as expected, you should see log statements like the following:

(venv) [backend] flask run                                                               
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit

Frontend with React.js

Open a new terminal window. In the root directory of the TwilioPythonEarthDay project, create a new React app called frontend:

npx create-react-app frontend

Once the app has been created, change into the directory, install react-bootstrap, and run the app with the following commands:

cd frontend
npm install react-bootstrap
npm start

You can download an image from any site like https://unsplash.com/ . Rename it to ecoimg.jpg and store it inside the frontend directory.

Verify the app is running by visiting http://localhost:3000 in the browser. The default React app will be visible. Next, create a file in TwilioPythonEarthDayOld/frontend/src called EcoFriendlyForm.js and insert the following code:

import React, { useState } from "react";
import { Form, Button } from "react-bootstrap";

import ecoimg from "./ecoimg.jpg";

const EcoFriendlyForm = () => {
 const [phoneNumber, setPhoneNumber] = useState("");
 const [frequency, setFrequency] = useState("");

 const handleSubmit = async (event) => {
   event.preventDefault();

   console.log(
     JSON.stringify({
       phoneNumber: phoneNumber,
       frequency: frequency,
     })
   );

   var res;

   try {
     res = await fetch("http://127.0.0.1:5000/sign-up", {
       method: "POST",
       headers: {
         Accept: "application/json",
         "Content-Type": "application/json",
       },
       body: JSON.stringify({
         phoneNumber: phoneNumber,
         frequency: frequency,
       }),
     });
   } catch (error) {
     console.log(error);
   }

   if (res.ok) {
     await res.json();
   } else {
     window.alert(res.status());
   }
 };

 return (
   <div style={containerStyle}>
     <img
       src={ecoimg}
       alt="earth image"
       width={"400px"}
       height={"220px"}
     />
     <h1 style={titleStyle}>Eco Friendly Reminder Service</h1>
     <Form onSubmit={handleSubmit} style={formStyle}>
       <Form.Group>
         <Form.Label style={formLabelStyle}>Phone Number</Form.Label>
         <Form.Control
           type="tel"
           value={phoneNumber}
           onChange={(event) => setPhoneNumber(event.target.value)}
           required
           style={formControlStyle}
         />
       </Form.Group>
       <Form.Group>
         <Form.Label style={formLabelStyle}>Frequency (hours)</Form.Label>
         <Form.Control
           type="number"
           value={frequency}
           onChange={(event) => setFrequency(event.target.value)}
           required
           style={formControlStyle}
         />
       </Form.Group>
       <Button type="submit" style={submitButtonStyle}>
         Sign Up
       </Button>
     </Form>
   </div>
 );
};

const containerStyle = {
 display: "flex",
 flexDirection: "column",
 alignItems: "center",
 padding: "50px",
 backgroundColor: "#7DCE82",
};



const titleStyle = {
 marginBottom: "25px",
 color: "#FFFFFF",
};

const formStyle = {
 width: "50%",
 marginTop: "25px",
};

const formLabelStyle = {
 color: "#FFFFFF",
};

const formControlStyle = {
 backgroundColor: "#FFFFFF",
};

const submitButtonStyle = {
 backgroundColor: "#048C03",
 color: "#FFFFFF",
};

export default EcoFriendlyForm;

This code defines a functional component EcoFriendlyForm, which renders a form for a user to sign up for an eco-friendly reminder service. The form includes fields for the user's phone number and the frequency at which they would like to receive reminders.

When the form is submitted, the handleSubmit function is called. This function first prevents the default behavior of the form (i.e., submitting and reloading the page) using the event.preventDefault() method. Then, it logs the values of the phoneNumber and frequency state variables to the console using JSON.stringify.

The function then uses the fetch method to send a POST request to a local server at http://127.0.0.1:5000/sign-up, which includes the user's phoneNumber and frequency as JSON data in the request body. If the request is successful (i.e., if the response has an ok status code), the function calls res.json() to parse the response as JSON. Otherwise, it displays an alert with the response status code using window.alert(res.status()).

The component returns JSX that defines the layout and appearance of the form. The useState hook is used to define and manage state variables for phoneNumber and frequency. The form includes two Form.Group components, each with a Form.Label and a Form.Control component. The Form.Control components are controlled inputs that set the state variables for phoneNumber and frequency using the onChange event. Finally, the component includes a Button component with the text "Sign Up" and a type of "submit", which triggers the handleSubmit function when clicked. The styles for the various elements are defined using JavaScript objects and applied using the style prop.

Next, replace the code in TwilioPythonEarthDay/frontend/src/App.js to include this EcoFriendlyForm component:

import React from "react";
import EcoFriendlyForm from "./EcoFriendlyForm";

function App() {
 return (
   <div>
     <h1>Eco-Friendly Reminder Service</h1>
     <EcoFriendlyForm />
   </div>
 );
}

export default App;

This code creates a React component called App that renders an h1 element with the text "Eco-Friendly Reminder Service" and the EcoFriendlyForm component. The EcoFriendlyForm component is imported from the frontend/src/EcoFriendlyForm file.

By rendering the EcoFriendlyForm component within the App component, you can display a form for users to sign up for the eco-friendly reminder service. When the user fills out the form and clicks the "Sign Up" button, the form data will be sent to the Flask API for processing.

Testing

Next, run both the backend server and frontend app simultaneously, if they are not still already running from earlier. In one terminal, change into the backend folder and type:

flask run

The server will run on port 5000:

Flask App running in terminal

In another terminal, change into the frontend directory and type:

npm start

Running react app from terminal

Navigate to http://localhost:3000/ to see the Eco Friendly Reminder Service web application!

Eco Friendly Reminder Service webpage

To test the application, enter your own or one of your verified phone numbers in the international E.164 format, and choose a frequency for eco-friendly reminders. Once signup is completed successfully, you will receive an SMS notification that you have subscribed.

Messages received from Eco friendly reminder Service

Based on your selected frequency, you will receive eco-friendly reminders to keep you on track with your sustainable habits and help you reduce your environmental impact.

All the code for the above tutorial is available on GitHub:

GitHub - PythonCodeNemesis/TwilioPythonEarthday

Conclusion

In conclusion, the subscription-based Eco-Friendly Reminder Service Application you have created for Earth Day using Twilio, Flask, Python, and React has the potential to empower individuals to make meaningful changes in their daily lives that can collectively have a positive impact on the environment. By providing personalized reminders, users can develop and maintain eco-friendly habits over time and feel motivated to make further progress towards sustainability. This application is aimed at inspiring a greater sense of environmental responsibility and contributing towards a more sustainable future for all.


References

1. What is Twilio? An introduction to the leading customer engagement …


The author goes by the name Python Code Nemesis. She loves writing technical articles on Python frameworks and open source on her Medium. In her free time, she paints. You can reach her on her Medium at https://medium.com/@dpythoncodenemesis!