2024-02-04T06:39:05.761Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
e548835e-a910-46b1-b80c-c960e6c265ea
61d6d379389bf9529febc1971d0380c9c68f8f5c55b4f15fe42158e1a46323b3
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Almost every interactive app sends event driven email on a per user basis.
In today's video, we'll look at the fundamentals of transactional email.
You've got mail.
We'll look at strategies for sending email at the right time to increase user engagement and, of course, the technical implementation details with Firebase Cloud Functions, and the SendGrid transactional email API.
And this is also the first video in a new series called minimum viable product, where we start with a generic spec or requirement like how do I send email from my app, then build a full stack solution with multiple front end or back end approaches.
In this tutorial, you'll see the back end integration with Cloud Functions, but if you want to extend it, you can go to Fireship IO and see integrations for Angular, React, Vue, Svelte, and Flutter.
If you're new here, like and subscribe and leave a comment below for a chance to win this t shirt.
Now the great thing about serverless functions is that they make it really easy to implement secure event driven code.
Today, we'll write and deploy 4 different Cloud Functions, each solving a specific problem.
The first one will send a welcome email when a new user signs up.
The second one is an HTTP function that can be called dynamically from your front end code.
The third one is a Firestore function which runs in response to changes to the database.
And the 4th function is Scheduled, which allows you to send an email at a specific time or date.
We'll talk about these strategies in a little more detail as we go along, but let's get started with the initial setup.
The first thing you'll need is a SendGrid account, which is a paid service, but starts off with a free tier to get you started.
Now you'll see a lot of different things on the Send dashboard, but the thing we're interested in is the transactional templates page.
From this page, you'll want to create a new template and then add a version to it.
You can use your own custom HTML or you can go to their drag and drop editor.
But when it comes to dynamic transactional email, you'll We want to create a template that allows you to pass in a bunch of data to customize it on a per user basis, and SendGrid uses handlebars to achieve this in their templates.
You'll notice over here on the left that we have the subject wrapped in handlebars.
That's because we'll be dynamically passing the subject from our back end functions.
Then in the email body, we have hello handlebars name, which will be passed in dynamically as well, and then also the text of the email itself.
After you've created a template, make a note of the template ID.
We're going to need that template ID as well as our SendGrid API key.
To get the API key, we go down here to settings, and then we'll generate a new API key that is restricted to the Mail Send API because we don't really need anything else for this demo.
From there, you can go into a blank project in your editor or in my case I'm working from a monorepo that has multiple front end integrations.
From the command line, you can run Firebase net functions, and we'll be using TypeScript, but that part's optional.
That's going to create a functions directory in the root of the project, So we'll go ahead and cd into the functions directory, then run npm install sendgrid slash mail, and that gives us the official Node SDK for SendGrid.
From there, we need to tell the Firebase functions environment the SendGrid API key, and then also the template ID that we'll use to send emails.
You don't have to save the template ID here, but it is useful if you just want to swap it out without having to completely redeploy your functions.
So now that we can securely access the API key, we can go into the source code in the index.
Ts file and initialize the SendGrid SDK.
We'll also bring in Firebase Admin and then make a reference to the Firestore database because one of our email triggers will be on a database write.
After importing SendGrid, the first thing you'll wanna do is reference your API key from the environment as well as the template ID if you saved it there.
Then all you have to do is call SendGrid Set API key, and you're ready to start sending mail.
The first type of transactional email that we'll tackle is a welcome email.
This strategy is really straightforward.
A new user signs up for the app, and you want to send them an email with some account details and some instructions on how to get started with the app.
We can handle this with the on create hook for Firebase auth.
When a new user signs up, this will give us the user object, which we can then pass off to the SendGrid SDK to send an email.
In the function body, we'll first format the message payload.
The to property is the email address that we'll be sending to, and you can add multiple email addresses here if you format it as an array.
The next option is the from email, which in our case will always be hello at fireship I o.
Then we'll make a reference to the template we created in SendGrid based on its template ID.
Then we have a dynamic template data option, which will take any customized data that we want to pass to SendGrid.
And this data will be replaced wherever we used handlebars in the template itself, which in our case is the subject line and also the name in the email body.
And the final step is to return a promise from the function that sends the email, which we can do by simply returning the SendGrid mail send with the message as the argument.
And that's all it takes to send a user a welcome email.
Now that's great for that specific use case, but there may be times when you just want to send a regular HTTP call that validates that the user's logged in and then send an email to that user.
And that's when callable HTTP functions from Firebase become very useful.
This type of function would allow a user to simply click a button, and then we could send some dynamic data to the back end from our front end code, which could be anything.
Now you probably don't just want any user to be able to do this.
You wanna make sure that it's a logged in user that has a validated email.
When this function is called, we'll have the auth context from the front end.
So we can check to make sure that that auth context is present and that it also has an email address on the token before we send the request to grid.
Now you'll notice that the callable function also has a data object in the payload.
This data can be passed from the front end.
Again, that data can be anything you want from your front end code.
And again, head over to FireShip.
Io to see how the actual front end integrations look in your framework of choice.
Now if you create a callable function or just a regular HTTP function, you You'll wanna make sure that the response you send back is serializable to JSON.
That means you don't just want to return the SendGrid promise, but instead await it and then return an object that says success through.
And then you could handle errors here if anything goes wrong.
So that gives you a really flexible way to manually send email from your front end, but you may want your functions to automatically react to changes to your database.
For example, you might have a blog app, and the author of a blog might want to be notified when a user comments on their post.
And the database will have a collection of posts, and then we'll have a sub collection of comments nested under each post.
So this function will run whenever a new comment is added to that sub collection.
This function will automatically give us access to the comment document, but it won't give us access to the post.
It will only give us the post ID.
So what we need to do is make a reference to that post in the database, and then we'll call Git to retrieve its actual data.
Now if you're in TypeScript Strict mode, you might also want to say or an empty object just to prevent errors from the TypeScript compiler, or you can set strict null checks to false in your tsconfig.
But now that we have the necessary data, we can then format the message.
We can use all this dynamic data to create a custom subject line, and then we can also set the post text to something like this user said something about this post.
And that gives us a function that can send transactional email based on changes to the database.
And that tends to be a lot more simple than trying to send requests from your front end code.
Now at this point, we've only been sending email based on user driven events.
But what if we have something a little more static, like a weekly summary that we want to send to each user?
For that, we can use a PubSub function based on a schedule.
For example, every Friday at 0 500.
From there, we can make a query to Firestore for all of the users that are ready to receive the summary.
That query is going to give us an array of snapshots, so we'll go ahead and map those snapshots down to the actual email on each document.
And that will just give us an array of strings or email addresses that we can send to SendGrid.
From there, you can use your own business logic to calculate the weekly summary, and then we'll return a promise to send the emails just like we've done in all the other functions.
Now in order to start testing these functions out, we need to run Firebase deploy only functions, and they'll be ready for use in a front end application.
You can test the Firestore or auth functions by simply going into the Firebase console and creating new authentication records or Firestore documents in the appropriate places.
And if you're ready to integrate this with a front end framework, head over to Fireship IO to check out the full source code and the framework specific videos.
I'm gonna go ahead and wrap things up there.
Thanks for watching, and I will talk to you soon.

Speaker 0: Almost every interactive app sends event driven email on a per user basis. In today's video, we'll look at the fundamentals of transactional email. You've got mail. We'll look at strategies for sending email at the right time to increase user engagement and, of course, the technical implementation details with Firebase Cloud Functions, and the SendGrid transactional email API. And this is also the first video in a new series called minimum viable product, where we start with a generic spec or requirement like how do I send email from my app, then build a full stack solution with multiple front end or back end approaches.

In this tutorial, you'll see the back end integration with Cloud Functions, but if you want to extend it, you can go to Fireship IO and see integrations for Angular, React, Vue, Svelte, and Flutter. If you're new here, like and subscribe and leave a comment below for a chance to win this t shirt. Now the great thing about serverless functions is that they make it really easy to implement secure event driven code. Today, we'll write and deploy 4 different Cloud Functions, each solving a specific problem. The first one will send a welcome email when a new user signs up.

The second one is an HTTP function that can be called dynamically from your front end code. The third one is a Firestore function which runs in response to changes to the database. And the 4th function is Scheduled, which allows you to send an email at a specific time or date. We'll talk about these strategies in a little more detail as we go along, but let's get started with the initial setup. The first thing you'll need is a SendGrid account, which is a paid service, but starts off with a free tier to get you started.

Now you'll see a lot of different things on the Send dashboard, but the thing we're interested in is the transactional templates page. From this page, you'll want to create a new template and then add a version to it. You can use your own custom HTML or you can go to their drag and drop editor. But when it comes to dynamic transactional email, you'll We want to create a template that allows you to pass in a bunch of data to customize it on a per user basis, and SendGrid uses handlebars to achieve this in their templates. You'll notice over here on the left that we have the subject wrapped in handlebars.

That's because we'll be dynamically passing the subject from our back end functions. Then in the email body, we have hello handlebars name, which will be passed in dynamically as well, and then also the text of the email itself. After you've created a template, make a note of the template ID. We're going to need that template ID as well as our SendGrid API key. To get the API key, we go down here to settings, and then we'll generate a new API key that is restricted to the Mail Send API because we don't really need anything else for this demo.

From there, you can go into a blank project in your editor or in my case I'm working from a monorepo that has multiple front end integrations. From the command line, you can run Firebase net functions, and we'll be using TypeScript, but that part's optional. That's going to create a functions directory in the root of the project, So we'll go ahead and cd into the functions directory, then run npm install sendgrid slash mail, and that gives us the official Node SDK for SendGrid. From there, we need to tell the Firebase functions environment the SendGrid API key, and then also the template ID that we'll use to send emails. You don't have to save the template ID here, but it is useful if you just want to swap it out without having to completely redeploy your functions.

So now that we can securely access the API key, we can go into the source code in the index. Ts file and initialize the SendGrid SDK. We'll also bring in Firebase Admin and then make a reference to the Firestore database because one of our email triggers will be on a database write. After importing SendGrid, the first thing you'll wanna do is reference your API key from the environment as well as the template ID if you saved it there. Then all you have to do is call SendGrid Set API key, and you're ready to start sending mail.

The first type of transactional email that we'll tackle is a welcome email. This strategy is really straightforward. A new user signs up for the app, and you want to send them an email with some account details and some instructions on how to get started with the app. We can handle this with the on create hook for Firebase auth. When a new user signs up, this will give us the user object, which we can then pass off to the SendGrid SDK to send an email.

In the function body, we'll first format the message payload. The to property is the email address that we'll be sending to, and you can add multiple email addresses here if you format it as an array. The next option is the from email, which in our case will always be hello at fireship I o. Then we'll make a reference to the template we created in SendGrid based on its template ID. Then we have a dynamic template data option, which will take any customized data that we want to pass to SendGrid.

And this data will be replaced wherever we used handlebars in the template itself, which in our case is the subject line and also the name in the email body. And the final step is to return a promise from the function that sends the email, which we can do by simply returning the SendGrid mail send with the message as the argument. And that's all it takes to send a user a welcome email. Now that's great for that specific use case, but there may be times when you just want to send a regular HTTP call that validates that the user's logged in and then send an email to that user. And that's when callable HTTP functions from Firebase become very useful.

This type of function would allow a user to simply click a button, and then we could send some dynamic data to the back end from our front end code, which could be anything. Now you probably don't just want any user to be able to do this. You wanna make sure that it's a logged in user that has a validated email. When this function is called, we'll have the auth context from the front end. So we can check to make sure that that auth context is present and that it also has an email address on the token before we send the request to grid.

Now you'll notice that the callable function also has a data object in the payload. This data can be passed from the front end. Again, that data can be anything you want from your front end code. And again, head over to FireShip. Io to see how the actual front end integrations look in your framework of choice.

Now if you create a callable function or just a regular HTTP function, you You'll wanna make sure that the response you send back is serializable to JSON. That means you don't just want to return the SendGrid promise, but instead await it and then return an object that says success through. And then you could handle errors here if anything goes wrong. So that gives you a really flexible way to manually send email from your front end, but you may want your functions to automatically react to changes to your database. For example, you might have a blog app, and the author of a blog might want to be notified when a user comments on their post.

And the database will have a collection of posts, and then we'll have a sub collection of comments nested under each post. So this function will run whenever a new comment is added to that sub collection. This function will automatically give us access to the comment document, but it won't give us access to the post. It will only give us the post ID. So what we need to do is make a reference to that post in the database, and then we'll call Git to retrieve its actual data.

Now if you're in TypeScript Strict mode, you might also want to say or an empty object just to prevent errors from the TypeScript compiler, or you can set strict null checks to false in your tsconfig. But now that we have the necessary data, we can then format the message. We can use all this dynamic data to create a custom subject line, and then we can also set the post text to something like this user said something about this post. And that gives us a function that can send transactional email based on changes to the database. And that tends to be a lot more simple than trying to send requests from your front end code.

Now at this point, we've only been sending email based on user driven events. But what if we have something a little more static, like a weekly summary that we want to send to each user? For that, we can use a PubSub function based on a schedule. For example, every Friday at 0 500. From there, we can make a query to Firestore for all of the users that are ready to receive the summary.

That query is going to give us an array of snapshots, so we'll go ahead and map those snapshots down to the actual email on each document. And that will just give us an array of strings or email addresses that we can send to SendGrid. From there, you can use your own business logic to calculate the weekly summary, and then we'll return a promise to send the emails just like we've done in all the other functions. Now in order to start testing these functions out, we need to run Firebase deploy only functions, and they'll be ready for use in a front end application. You can test the Firestore or auth functions by simply going into the Firebase console and creating new authentication records or Firestore documents in the appropriate places.

And if you're ready to integrate this with a front end framework, head over to Fireship IO to check out the full source code and the framework specific videos. I'm gonna go ahead and wrap things up there. Thanks for watching, and I will talk to you soon.
Almost every interactive app sends event driven email on a per user basis. In today's video, we'll look at the fundamentals of transactional email. You've got mail. We'll look at strategies for sending email at the right time to increase user engagement and, of course, the technical implementation details with Firebase Cloud Functions, and the SendGrid transactional email API. And this is also the first video in a new series called minimum viable product, where we start with a generic spec or requirement like how do I send email from my app, then build a full stack solution with multiple front end or back end approaches. In this tutorial, you'll see the back end integration with Cloud Functions, but if you want to extend it, you can go to Fireship IO and see integrations for Angular, React, Vue, Svelte, and Flutter.
email
video gaming
streaming
youtube
If you're new here, like and subscribe and leave a comment below for a chance to win this t shirt. Now the great thing about serverless functions is that they make it really easy to implement secure event driven code. Today, we'll write and deploy 4 different Cloud Functions, each solving a specific problem. The first one will send a welcome email when a new user signs up. The second one is an HTTP function that can be called dynamically from your front end code. The third one is a Firestore function which runs in response to changes to the database.
And the 4th function is Scheduled, which allows you to send an email at a specific time or date. We'll talk about these strategies in a little more detail as we go along, but let's get started with the initial setup. The first thing you'll need is a SendGrid account, which is a paid service, but starts off with a free tier to get you started. Now you'll see a lot of different things on the Send dashboard, but the thing we're interested in is the transactional templates page. From this page, you'll want to create a new template and then add a version to it.
email
You can use your own custom HTML or you can go to their drag and drop editor. But when it comes to dynamic transactional email, you'll We want to create a template that allows you to pass in a bunch of data to customize it on a per user basis, and SendGrid uses handlebars to achieve this in their templates. You'll notice over here on the left that we have the subject wrapped in handlebars. That's because we'll be dynamically passing the subject from our back end functions. Then in the email body, we have hello handlebars name, which will be passed in dynamically as well, and then also the text of the email itself. After you've created a template, make a note of the template ID. We're going to need that template ID as well as our SendGrid API key.
email
To get the API key, we go down here to settings, and then we'll generate a new API key that is restricted to the Mail Send API because we don't really need anything else for this demo. From there, you can go into a blank project in your editor or in my case I'm working from a monorepo that has multiple front end integrations. From the command line, you can run Firebase net functions, and we'll be using TypeScript, but that part's optional. That's going to create a functions directory in the root of the project, So we'll go ahead and cd into the functions directory, then run npm install sendgrid slash mail, and that gives us the official Node SDK for SendGrid. From there, we need to tell the Firebase functions environment the SendGrid API key, and then also the template ID that we'll use to send emails. You don't have to save the template ID here, but it is useful if you just want to swap it out without having to completely redeploy your functions. So now that we can securely access the API key, we can go into the source code in the index. Ts file and initialize the SendGrid SDK. We'll also bring in Firebase Admin and then make a reference to the Firestore database because one of our email triggers will be on a database write.
After importing SendGrid, the first thing you'll wanna do is reference your API key from the environment as well as the template ID if you saved it there. Then all you have to do is call SendGrid Set API key, and you're ready to start sending mail. The first type of transactional email that we'll tackle is a welcome email. This strategy is really straightforward. A new user signs up for the app, and you want to send them an email with some account details and some instructions on how to get started with the app. We can handle this with the on create hook for Firebase auth. When a new user signs up, this will give us the user object, which we can then pass off to the SendGrid SDK to send an email. In the function body, we'll first format the message payload. The to property is the email address that we'll be sending to, and you can add multiple email addresses here if you format it as an array. The next option is the from email, which in our case will always be hello at fireship I o. Then we'll make a reference to the template we created in SendGrid based on its template ID. Then we have a dynamic template data option, which will take any customized data that we want to pass to SendGrid.
email
And this data will be replaced wherever we used handlebars in the template itself, which in our case is the subject line and also the name in the email body.
And the final step is to return a promise from the function that sends the email, which we can do by simply returning the SendGrid mail send with the message as the argument. And that's all it takes to send a user a welcome email. Now that's great for that specific use case, but there may be times when you just want to send a regular HTTP call that validates that the user's logged in and then send an email to that user.
email
And that's when callable HTTP functions from Firebase become very useful. This type of function would allow a user to simply click a button, and then we could send some dynamic data to the back end from our front end code, which could be anything.
Now you probably don't just want any user to be able to do this. You wanna make sure that it's a logged in user that has a validated email. When this function is called, we'll have the auth context from the front end. So we can check to make sure that that auth context is present and that it also has an email address on the token before we send the request to grid.
email
Now you'll notice that the callable function also has a data object in the payload. This data can be passed from the front end. Again, that data can be anything you want from your front end code. And again, head over to FireShip. Io to see how the actual front end integrations look in your framework of choice.
data
Now if you create a callable function or just a regular HTTP function, you You'll wanna make sure that the response you send back is serializable to JSON.
That means you don't just want to return the SendGrid promise, but instead await it and then return an object that says success through. And then you could handle errors here if anything goes wrong. So that gives you a really flexible way to manually send email from your front end, but you may want your functions to automatically react to changes to your database. For example, you might have a blog app, and the author of a blog might want to be notified when a user comments on their post. And the database will have a collection of posts, and then we'll have a sub collection of comments nested under each post. So this function will run whenever a new comment is added to that sub collection.
email
blogging
This function will automatically give us access to the comment document, but it won't give us access to the post. It will only give us the post ID.
So what we need to do is make a reference to that post in the database, and then we'll call Git to retrieve its actual data. Now if you're in TypeScript Strict mode, you might also want to say or an empty object just to prevent errors from the TypeScript compiler, or you can set strict null checks to false in your tsconfig.
databases
But now that we have the necessary data, we can then format the message. We can use all this dynamic data to create a custom subject line, and then we can also set the post text to something like this user said something about this post. And that gives us a function that can send transactional email based on changes to the database. And that tends to be a lot more simple than trying to send requests from your front end code. Now at this point, we've only been sending email based on user driven events. But what if we have something a little more static, like a weekly summary that we want to send to each user? For that, we can use a PubSub function based on a schedule. For example, every Friday at 0 500. From there, we can make a query to Firestore for all of the users that are ready to receive the summary. That query is going to give us an array of snapshots, so we'll go ahead and map those snapshots down to the actual email on each document.
email
data
databases
And that will just give us an array of strings or email addresses that we can send to SendGrid. From there, you can use your own business logic to calculate the weekly summary, and then we'll return a promise to send the emails just like we've done in all the other functions.
email
Now in order to start testing these functions out, we need to run Firebase deploy only functions, and they'll be ready for use in a front end application. You can test the Firestore or auth functions by simply going into the Firebase console and creating new authentication records or Firestore documents in the appropriate places.
And if you're ready to integrate this with a front end framework, head over to Fireship IO to check out the full source code and the framework specific videos. I'm gonna go ahead and wrap things up there. Thanks for watching, and I will talk to you soon.
streaming
software
video gaming
Almost every interactive app sends event driven email on a per user basis. In today's video, we'll look at the fundamentals of transactional email. You've got mail. We'll look at strategies for sending email at the right time to increase user engagement and, of course, the technical implementation details with Firebase Cloud Functions, and the SendGrid transactional email API. And this is also the first video in a new series called minimum viable product, where we start with a generic spec or requirement like how do I send email from my app, then build a full stack solution with multiple front end or back end approaches. In this tutorial, you'll see the back end integration with Cloud Functions, but if you want to extend it, you can go to Fireship IO and see integrations for Angular, React, Vue, Svelte, and Flutter. If you're new here, like and subscribe and leave a comment below for a chance to win this t shirt. Now the great thing about serverless functions is that they make it really easy to implement secure event driven code. Today, we'll write and deploy 4 different Cloud Functions, each solving a specific problem. The first one will send a welcome email when a new user signs up. The second one is an HTTP function that can be called dynamically from your front end code. The third one is a Firestore function which runs in response to changes to the database. And the 4th function is Scheduled, which allows you to send an email at a specific time or date. We'll talk about these strategies in a little more detail as we go along, but let's get started with the initial setup. The first thing you'll need is a SendGrid account, which is a paid service, but starts off with a free tier to get you started. Now you'll see a lot of different things on the Send dashboard, but the thing we're interested in is the transactional templates page. From this page, you'll want to create a new template and then add a version to it. You can use your own custom HTML or you can go to their drag and drop editor. But when it comes to dynamic transactional email, you'll We want to create a template that allows you to pass in a bunch of data to customize it on a per user basis, and SendGrid uses handlebars to achieve this in their templates. You'll notice over here on the left that we have the subject wrapped in handlebars. That's because we'll be dynamically passing the subject from our back end functions. Then in the email body, we have hello handlebars name, which will be passed in dynamically as well, and then also the text of the email itself. After you've created a template, make a note of the template ID. We're going to need that template ID as well as our SendGrid API key. To get the API key, we go down here to settings, and then we'll generate a new API key that is restricted to the Mail Send API because we don't really need anything else for this demo. From there, you can go into a blank project in your editor or in my case I'm working from a monorepo that has multiple front end integrations. From the command line, you can run Firebase net functions, and we'll be using TypeScript, but that part's optional. That's going to create a functions directory in the root of the project, So we'll go ahead and cd into the functions directory, then run npm install sendgrid slash mail, and that gives us the official Node SDK for SendGrid. From there, we need to tell the Firebase functions environment the SendGrid API key, and then also the template ID that we'll use to send emails. You don't have to save the template ID here, but it is useful if you just want to swap it out without having to completely redeploy your functions. So now that we can securely access the API key, we can go into the source code in the index. Ts file and initialize the SendGrid SDK. We'll also bring in Firebase Admin and then make a reference to the Firestore database because one of our email triggers will be on a database write. After importing SendGrid, the first thing you'll wanna do is reference your API key from the environment as well as the template ID if you saved it there. Then all you have to do is call SendGrid Set API key, and you're ready to start sending mail. The first type of transactional email that we'll tackle is a welcome email. This strategy is really straightforward. A new user signs up for the app, and you want to send them an email with some account details and some instructions on how to get started with the app. We can handle this with the on create hook for Firebase auth. When a new user signs up, this will give us the user object, which we can then pass off to the SendGrid SDK to send an email. In the function body, we'll first format the message payload. The to property is the email address that we'll be sending to, and you can add multiple email addresses here if you format it as an array. The next option is the from email, which in our case will always be hello at fireship I o. Then we'll make a reference to the template we created in SendGrid based on its template ID. Then we have a dynamic template data option, which will take any customized data that we want to pass to SendGrid. And this data will be replaced wherever we used handlebars in the template itself, which in our case is the subject line and also the name in the email body. And the final step is to return a promise from the function that sends the email, which we can do by simply returning the SendGrid mail send with the message as the argument. And that's all it takes to send a user a welcome email. Now that's great for that specific use case, but there may be times when you just want to send a regular HTTP call that validates that the user's logged in and then send an email to that user. And that's when callable HTTP functions from Firebase become very useful. This type of function would allow a user to simply click a button, and then we could send some dynamic data to the back end from our front end code, which could be anything. Now you probably don't just want any user to be able to do this. You wanna make sure that it's a logged in user that has a validated email. When this function is called, we'll have the auth context from the front end. So we can check to make sure that that auth context is present and that it also has an email address on the token before we send the request to grid. Now you'll notice that the callable function also has a data object in the payload. This data can be passed from the front end. Again, that data can be anything you want from your front end code. And again, head over to FireShip. Io to see how the actual front end integrations look in your framework of choice. Now if you create a callable function or just a regular HTTP function, you You'll wanna make sure that the response you send back is serializable to JSON. That means you don't just want to return the SendGrid promise, but instead await it and then return an object that says success through. And then you could handle errors here if anything goes wrong. So that gives you a really flexible way to manually send email from your front end, but you may want your functions to automatically react to changes to your database. For example, you might have a blog app, and the author of a blog might want to be notified when a user comments on their post. And the database will have a collection of posts, and then we'll have a sub collection of comments nested under each post. So this function will run whenever a new comment is added to that sub collection. This function will automatically give us access to the comment document, but it won't give us access to the post. It will only give us the post ID. So what we need to do is make a reference to that post in the database, and then we'll call Git to retrieve its actual data. Now if you're in TypeScript Strict mode, you might also want to say or an empty object just to prevent errors from the TypeScript compiler, or you can set strict null checks to false in your tsconfig. But now that we have the necessary data, we can then format the message. We can use all this dynamic data to create a custom subject line, and then we can also set the post text to something like this user said something about this post. And that gives us a function that can send transactional email based on changes to the database. And that tends to be a lot more simple than trying to send requests from your front end code. Now at this point, we've only been sending email based on user driven events. But what if we have something a little more static, like a weekly summary that we want to send to each user? For that, we can use a PubSub function based on a schedule. For example, every Friday at 0 500. From there, we can make a query to Firestore for all of the users that are ready to receive the summary. That query is going to give us an array of snapshots, so we'll go ahead and map those snapshots down to the actual email on each document. And that will just give us an array of strings or email addresses that we can send to SendGrid. From there, you can use your own business logic to calculate the weekly summary, and then we'll return a promise to send the emails just like we've done in all the other functions. Now in order to start testing these functions out, we need to run Firebase deploy only functions, and they'll be ready for use in a front end application. You can test the Firestore or auth functions by simply going into the Firebase console and creating new authentication records or Firestore documents in the appropriate places. And if you're ready to integrate this with a front end framework, head over to Fireship IO to check out the full source code and the framework specific videos. I'm gonna go ahead and wrap things up there. Thanks for watching, and I will talk to you soon.
Almost
almost
every
every
interactive
interactive
app
app
sends
sends
event
event
driven
driven
email
email
on
on
a
a
per
per
user
user
basis.
basis
In
in
today's
today's
video,
video
we'll
we'll
look
look
at
at
the
the
fundamentals
fundamentals
of
of
transactional
transactional
email.
email
You've
you've
got
got
mail.
mail
We'll
we'll
look
look
at
at
strategies
strategies
for
for
sending
sending
email
email
at
at
the
the
right
right
time
time
to
to
increase
increase
user
user
engagement
engagement
and,
and
of
of
course,
course
the
the
technical
technical
implementation
implementation
details
details
with
with
Firebase
firebase
Cloud
cloud
Functions,
functions
and
and
the
the
SendGrid
sendgrid
transactional
transactional
email
email
API.
api
And
and
this
this
is
is
also
also
the
the
first
first
video
video
in
in
a
a
new
new
series
series
called
called
minimum
minimum
viable
viable
product,
product
where
where
we
we
start
start
with
with
a
a
generic
generic
spec
spec
or
or
requirement
requirement
like
like
how
how
do
do
I
i
send
send
email
email
from
from
my
my
app,
app
then
then
build
build
a
a
full
full
stack
stack
solution
solution
with
with
multiple
multiple
front
front
end
end
or
or
back
back
end
end
approaches.
approaches
In
in
this
this
tutorial,
tutorial
you'll
you'll
see
see
the
the
back
back
end
end
integration
integration
with
with
Cloud
cloud
Functions,
functions
but
but
if
if
you
you
want
want
to
to
extend
extend
it,
it
you
you
can
can
go
go
to
to
Fireship
fireship
IO
io
and
and
see
see
integrations
integrations
for
for
Angular,
angular
React,
react
Vue,
vue
Svelte,
svelte
and
and
Flutter.
flutter
If
if
you're
you're
new
new
here,
here
like
like
and
and
subscribe
subscribe
and
and
leave
leave
a
a
comment
comment
below
below
for
for
a
a
chance
chance
to
to
win
win
this
this
t
t
shirt.
shirt
Now
now
the
the
great
great
thing
thing
about
about
serverless
serverless
functions
functions
is
is
that
that
they
they
make
make
it
it
really
really
easy
easy
to
to
implement
implement
secure
secure
event
event
driven
driven
code.
code
Today,
today
we'll
we'll
write
write
and
and
deploy
deploy
4
4
different
different
Cloud
cloud
Functions,
functions
each
each
solving
solving
a
a
specific
specific
problem.
problem
The
the
first
first
one
one
will
will
send
send
a
a
welcome
welcome
email
email
when
when
a
a
new
new
user
user
signs
signs
up.
up
The
the
second
second
one
one
is
is
an
an
HTTP
http
function
function
that
that
can
can
be
be
called
called
dynamically
dynamically
from
from
your
your
front
front
end
end
code.
code
The
the
third
third
one
one
is
is
a
a
Firestore
firestore
function
function
which
which
runs
runs
in
in
response
response
to
to
changes
changes
to
to
the
the
database.
database
And
and
the
the
4th
4th
function
function
is
is
Scheduled,
scheduled
which
which
allows
allows
you
you
to
to
send
send
an
an
email
email
at
at
a
a
specific
specific
time
time
or
or
date.
date
We'll
we'll
talk
talk
about
about
these
these
strategies
strategies
in
in
a
a
little
little
more
more
detail
detail
as
as
we
we
go
go
along,
along
but
but
let's
let's
get
get
started
started
with
with
the
the
initial
initial
setup.
setup
The
the
first
first
thing
thing
you'll
you'll
need
need
is
is
a
a
SendGrid
sendgrid
account,
account
which
which
is
is
a
a
paid
paid
service,
service
but
but
starts
starts
off
off
with
with
a
a
free
free
tier
tier
to
to
get
get
you
you
started.
started
Now
now
you'll
you'll
see
see
a
a
lot
lot
of
of
different
different
things
things
on
on
the
the
Send
send
dashboard,
dashboard
but
but
the
the
thing
thing
we're
we're
interested
interested
in
in
is
is
the
the
transactional
transactional
templates
templates
page.
page
From
from
this
this
page,
page
you'll
you'll
want
want
to
to
create
create
a
a
new
new
template
template
and
and
then
then
add
add
a
a
version
version
to
to
it.
it
You
you
can
can
use
use
your
your
own
own
custom
custom
HTML
html
or
or
you
you
can
can
go
go
to
to
their
their
drag
drag
and
and
drop
drop
editor.
editor
But
but
when
when
it
it
comes
comes
to
to
dynamic
dynamic
transactional
transactional
email,
email
you'll
you'll
We
we
want
want
to
to
create
create
a
a
template
template
that
that
allows
allows
you
you
to
to
pass
pass
in
in
a
a
bunch
bunch
of
of
data
data
to
to
customize
customize
it
it
on
on
a
a
per
per
user
user
basis,
basis
and
and
SendGrid
sendgrid
uses
uses
handlebars
handlebars
to
to
achieve
achieve
this
this
in
in
their
their
templates.
templates
You'll
you'll
notice
notice
over
over
here
here
on
on
the
the
left
left
that
that
we
we
have
have
the
the
subject
subject
wrapped
wrapped
in
in
handlebars.
handlebars
That's
that's
because
because
we'll
we'll
be
be
dynamically
dynamically
passing
passing
the
the
subject
subject
from
from
our
our
back
back
end
end
functions.
functions
Then
then
in
in
the
the
email
email
body,
body
we
we
have
have
hello
hello
handlebars
handlebars
name,
name
which
which
will
will
be
be
passed
passed
in
in
dynamically
dynamically
as
as
well,
well
and
and
then
then
also
also
the
the
text
text
of
of
the
the
email
email
itself.
itself
After
after
you've
you've
created
created
a
a
template,
template
make
make
a
a
note
note
of
of
the
the
template
template
ID.
id
We're
we're
going
going
to
to
need
need
that
that
template
template
ID
id
as
as
well
well
as
as
our
our
SendGrid
sendgrid
API
api
key.
key
To
to
get
get
the
the
API
api
key,
key
we
we
go
go
down
down
here
here
to
to
settings,
settings
and
and
then
then
we'll
we'll
generate
generate
a
a
new
new
API
api
key
key
that
that
is
is
restricted
restricted
to
to
the
the
Mail
mail
Send
send
API
api
because
because
we
we
don't
don't
really
really
need
need
anything
anything
else
else
for
for
this
this
demo.
demo
From
from
there,
there
you
you
can
can
go
go
into
into
a
a
blank
blank
project
project
in
in
your
your
editor
editor
or
or
in
in
my
my
case
case
I'm
i'm
working
working
from
from
a
a
monorepo
monorepo
that
that
has
has
multiple
multiple
front
front
end
end
integrations.
integrations
From
from
the
the
command
command
line,
line
you
you
can
can
run
run
Firebase
firebase
net
net
functions,
functions
and
and
we'll
we'll
be
be
using
using
TypeScript,
typescript
but
but
that
that
part's
part's
optional.
optional
That's
that's
going
going
to
to
create
create
a
a
functions
functions
directory
directory
in
in
the
the
root
root
of
of
the
the
project,
project
So
so
we'll
we'll
go
go
ahead
ahead
and
and
cd
cd
into
into
the
the
functions
functions
directory,
directory
then
then
run
run
npm
npm
install
install
sendgrid
sendgrid
slash
slash
mail,
mail
and
and
that
that
gives
gives
us
us
the
the
official
official
Node
node
SDK
sdk
for
for
SendGrid.
sendgrid
From
from
there,
there
we
we
need
need
to
to
tell
tell
the
the
Firebase
firebase
functions
functions
environment
environment
the
the
SendGrid
sendgrid
API
api
key,
key
and
and
then
then
also
also
the
the
template
template
ID
id
that
that
we'll
we'll
use
use
to
to
send
send
emails.
emails
You
you
don't
don't
have
have
to
to
save
save
the
the
template
template
ID
id
here,
here
but
but
it
it
is
is
useful
useful
if
if
you
you
just
just
want
want
to
to
swap
swap
it
it
out
out
without
without
having
having
to
to
completely
completely
redeploy
redeploy
your
your
functions.
functions
So
so
now
now
that
that
we
we
can
can
securely
securely
access
access
the
the
API
api
key,
key
we
we
can
can
go
go
into
into
the
the
source
source
code
code
in
in
the
the
index.
index
Ts
ts
file
file
and
and
initialize
initialize
the
the
SendGrid
sendgrid
SDK.
sdk
We'll
we'll
also
also
bring
bring
in
in
Firebase
firebase
Admin
admin
and
and
then
then
make
make
a
a
reference
reference
to
to
the
the
Firestore
firestore
database
database
because
because
one
one
of
of
our
our
email
email
triggers
triggers
will
will
be
be
on
on
a
a
database
database
write.
write
After
after
importing
importing
SendGrid,
sendgrid
the
the
first
first
thing
thing
you'll
you'll
wanna
wanna
do
do
is
is
reference
reference
your
your
API
api
key
key
from
from
the
the
environment
environment
as
as
well
well
as
as
the
the
template
template
ID
id
if
if
you
you
saved
saved
it
it
there.
there
Then
then
all
all
you
you
have
have
to
to
do
do
is
is
call
call
SendGrid
sendgrid
Set
set
API
api
key,
key
and
and
you're
you're
ready
ready
to
to
start
start
sending
sending
mail.
mail
The
the
first
first
type
type
of
of
transactional
transactional
email
email
that
that
we'll
we'll
tackle
tackle
is
is
a
a
welcome
welcome
email.
email
This
this
strategy
strategy
is
is
really
really
straightforward.
straightforward
A
a
new
new
user
user
signs
signs
up
up
for
for
the
the
app,
app
and
and
you
you
want
want
to
to
send
send
them
them
an
an
email
email
with
with
some
some
account
account
details
details
and
and
some
some
instructions
instructions
on
on
how
how
to
to
get
get
started
started
with
with
the
the
app.
app
We
we
can
can
handle
handle
this
this
with
with
the
the
on
on
create
create
hook
hook
for
for
Firebase
firebase
auth.
auth
When
when
a
a
new
new
user
user
signs
signs
up,
up
this
this
will
will
give
give
us
us
the
the
user
user
object,
object
which
which
we
we
can
can
then
then
pass
pass
off
off
to
to
the
the
SendGrid
sendgrid
SDK
sdk
to
to
send
send
an
an
email.
email
In
in
the
the
function
function
body,
body
we'll
we'll
first
first
format
format
the
the
message
message
payload.
payload
The
the
to
to
property
property
is
is
the
the
email
email
address
address
that
that
we'll
we'll
be
be
sending
sending
to,
to
and
and
you
you
can
can
add
add
multiple
multiple
email
email
addresses
addresses
here
here
if
if
you
you
format
format
it
it
as
as
an
an
array.
array
The
the
next
next
option
option
is
is
the
the
from
from
email,
email
which
which
in
in
our
our
case
case
will
will
always
always
be
be
hello
hello
at
at
fireship
fireship
I
i
o.
o
Then
then
we'll
we'll
make
make
a
a
reference
reference
to
to
the
the
template
template
we
we
created
created
in
in
SendGrid
sendgrid
based
based
on
on
its
its
template
template
ID.
id
Then
then
we
we
have
have
a
a
dynamic
dynamic
template
template
data
data
option,
option
which
which
will
will
take
take
any
any
customized
customized
data
data
that
that
we
we
want
want
to
to
pass
pass
to
to
SendGrid.
sendgrid
And
and
this
this
data
data
will
will
be
be
replaced
replaced
wherever
wherever
we
we
used
used
handlebars
handlebars
in
in
the
the
template
template
itself,
itself
which
which
in
in
our
our
case
case
is
is
the
the
subject
subject
line
line
and
and
also
also
the
the
name
name
in
in
the
the
email
email
body.
body
And
and
the
the
final
final
step
step
is
is
to
to
return
return
a
a
promise
promise
from
from
the
the
function
function
that
that
sends
sends
the
the
email,
email
which
which
we
we
can
can
do
do
by
by
simply
simply
returning
returning
the
the
SendGrid
sendgrid
mail
mail
send
send
with
with
the
the
message
message
as
as
the
the
argument.
argument
And
and
that's
that's
all
all
it
it
takes
takes
to
to
send
send
a
a
user
user
a
a
welcome
welcome
email.
email
Now
now
that's
that's
great
great
for
for
that
that
specific
specific
use
use
case,
case
but
but
there
there
may
may
be
be
times
times
when
when
you
you
just
just
want
want
to
to
send
send
a
a
regular
regular
HTTP
http
call
call
that
that
validates
validates
that
that
the
the
user's
user's
logged
logged
in
in
and
and
then
then
send
send
an
an
email
email
to
to
that
that
user.
user
And
and
that's
that's
when
when
callable
callable
HTTP
http
functions
functions
from
from
Firebase
firebase
become
become
very
very
useful.
useful
This
this
type
type
of
of
function
function
would
would
allow
allow
a
a
user
user
to
to
simply
simply
click
click
a
a
button,
button
and
and
then
then
we
we
could
could
send
send
some
some
dynamic
dynamic
data
data
to
to
the
the
back
back
end
end
from
from
our
our
front
front
end
end
code,
code
which
which
could
could
be
be
anything.
anything
Now
now
you
you
probably
probably
don't
don't
just
just
want
want
any
any
user
user
to
to
be
be
able
able
to
to
do
do
this.
this
You
you
wanna
wanna
make
make
sure
sure
that
that
it's
it's
a
a
logged
logged
in
in
user
user
that
that
has
has
a
a
validated
validated
email.
email
When
when
this
this
function
function
is
is
called,
called
we'll
we'll
have
have
the
the
auth
auth
context
context
from
from
the
the
front
front
end.
end
So
so
we
we
can
can
check
check
to
to
make
make
sure
sure
that
that
that
that
auth
auth
context
context
is
is
present
present
and
and
that
that
it
it
also
also
has
has
an
an
email
email
address
address
on
on
the
the
token
token
before
before
we
we
send
send
the
the
request
request
to
to
grid.
grid
Now
now
you'll
you'll
notice
notice
that
that
the
the
callable
callable
function
function
also
also
has
has
a
a
data
data
object
object
in
in
the
the
payload.
payload
This
this
data
data
can
can
be
be
passed
passed
from
from
the
the
front
front
end.
end
Again,
again
that
that
data
data
can
can
be
be
anything
anything
you
you
want
want
from
from
your
your
front
front
end
end
code.
code
And
and
again,
again
head
head
over
over
to
to
FireShip.
fireship
Io
io
to
to
see
see
how
how
the
the
actual
actual
front
front
end
end
integrations
integrations
look
look
in
in
your
your
framework
framework
of
of
choice.
choice
Now
now
if
if
you
you
create
create
a
a
callable
callable
function
function
or
or
just
just
a
a
regular
regular
HTTP
http
function,
function
you
you
You'll
you'll
wanna
wanna
make
make
sure
sure
that
that
the
the
response
response
you
you
send
send
back
back
is
is
serializable
serializable
to
to
JSON.
json
That
that
means
means
you
you
don't
don't
just
just
want
want
to
to
return
return
the
the
SendGrid
sendgrid
promise,
promise
but
but
instead
instead
await
await
it
it
and
and
then
then
return
return
an
an
object
object
that
that
says
says
success
success
through.
through
And
and
then
then
you
you
could
could
handle
handle
errors
errors
here
here
if
if
anything
anything
goes
goes
wrong.
wrong
So
so
that
that
gives
gives
you
you
a
a
really
really
flexible
flexible
way
way
to
to
manually
manually
send
send
email
email
from
from
your
your
front
front
end,
end
but
but
you
you
may
may
want
want
your
your
functions
functions
to
to
automatically
automatically
react
react
to
to
changes
changes
to
to
your
your
database.
database
For
for
example,
example
you
you
might
might
have
have
a
a
blog
blog
app,
app
and
and
the
the
author
author
of
of
a
a
blog
blog
might
might
want
want
to
to
be
be
notified
notified
when
when
a
a
user
user
comments
comments
on
on
their
their
post.
post
And
and
the
the
database
database
will
will
have
have
a
a
collection
collection
of
of
posts,
posts
and
and
then
then
we'll
we'll
have
have
a
a
sub
sub
collection
collection
of
of
comments
comments
nested
nested
under
under
each
each
post.
post
So
so
this
this
function
function
will
will
run
run
whenever
whenever
a
a
new
new
comment
comment
is
is
added
added
to
to
that
that
sub
sub
collection.
collection
This
this
function
function
will
will
automatically
automatically
give
give
us
us
access
access
to
to
the
the
comment
comment
document,
document
but
but
it
it
won't
won't
give
give
us
us
access
access
to
to
the
the
post.
post
It
it
will
will
only
only
give
give
us
us
the
the
post
post
ID.
id
So
so
what
what
we
we
need
need
to
to
do
do
is
is
make
make
a
a
reference
reference
to
to
that
that
post
post
in
in
the
the
database,
database
and
and
then
then
we'll
we'll
call
call
Git
git
to
to
retrieve
retrieve
its
its
actual
actual
data.
data
Now
now
if
if
you're
you're
in
in
TypeScript
typescript
Strict
strict
mode,
mode
you
you
might
might
also
also
want
want
to
to
say
say
or
or
an
an
empty
empty
object
object
just
just
to
to
prevent
prevent
errors
errors
from
from
the
the
TypeScript
typescript
compiler,
compiler
or
or
you
you
can
can
set
set
strict
strict
null
null
checks
checks
to
to
false
false
in
in
your
your
tsconfig.
tsconfig
But
but
now
now
that
that
we
we
have
have
the
the
necessary
necessary
data,
data
we
we
can
can
then
then
format
format
the
the
message.
message
We
we
can
can
use
use
all
all
this
this
dynamic
dynamic
data
data
to
to
create
create
a
a
custom
custom
subject
subject
line,
line
and
and
then
then
we
we
can
can
also
also
set
set
the
the
post
post
text
text
to
to
something
something
like
like
this
this
user
user
said
said
something
something
about
about
this
this
post.
post
And
and
that
that
gives
gives
us
us
a
a
function
function
that
that
can
can
send
send
transactional
transactional
email
email
based
based
on
on
changes
changes
to
to
the
the
database.
database
And
and
that
that
tends
tends
to
to
be
be
a
a
lot
lot
more
more
simple
simple
than
than
trying
trying
to
to
send
send
requests
requests
from
from
your
your
front
front
end
end
code.
code
Now
now
at
at
this
this
point,
point
we've
we've
only
only
been
been
sending
sending
email
email
based
based
on
on
user
user
driven
driven
events.
events
But
but
what
what
if
if
we
we
have
have
something
something
a
a
little
little
more
more
static,
static
like
like
a
a
weekly
weekly
summary
summary
that
that
we
we
want
want
to
to
send
send
to
to
each
each
user?
user
For
for
that,
that
we
we
can
can
use
use
a
a
PubSub
pubsub
function
function
based
based
on
on
a
a
schedule.
schedule
For
for
example,
example
every
every
Friday
friday
at
at
0
0
500.
500
From
from
there,
there
we
we
can
can
make
make
a
a
query
query
to
to
Firestore
firestore
for
for
all
all
of
of
the
the
users
users
that
that
are
are
ready
ready
to
to
receive
receive
the
the
summary.
summary
That
that
query
query
is
is
going
going
to
to
give
give
us
us
an
an
array
array
of
of
snapshots,
snapshots
so
so
we'll
we'll
go
go
ahead
ahead
and
and
map
map
those
those
snapshots
snapshots
down
down
to
to
the
the
actual
actual
email
email
on
on
each
each
document.
document
And
and
that
that
will
will
just
just
give
give
us
us
an
an
array
array
of
of
strings
strings
or
or
email
email
addresses
addresses
that
that
we
we
can
can
send
send
to
to
SendGrid.
sendgrid
From
from
there,
there
you
you
can
can
use
use
your
your
own
own
business
business
logic
logic
to
to
calculate
calculate
the
the
weekly
weekly
summary,
summary
and
and
then
then
we'll
we'll
return
return
a
a
promise
promise
to
to
send
send
the
the
emails
emails
just
just
like
like
we've
we've
done
done
in
in
all
all
the
the
other
other
functions.
functions
Now
now
in
in
order
order
to
to
start
start
testing
testing
these
these
functions
functions
out,
out
we
we
need
need
to
to
run
run
Firebase
firebase
deploy
deploy
only
only
functions,
functions
and
and
they'll
they'll
be
be
ready
ready
for
for
use
use
in
in
a
a
front
front
end
end
application.
application
You
you
can
can
test
test
the
the
Firestore
firestore
or
or
auth
auth
functions
functions
by
by
simply
simply
going
going
into
into
the
the
Firebase
firebase
console
console
and
and
creating
creating
new
new
authentication
authentication
records
records
or
or
Firestore
firestore
documents
documents
in
in
the
the
appropriate
appropriate
places.
places
And
and
if
if
you're
you're
ready
ready
to
to
integrate
integrate
this
this
with
with
a
a
front
front
end
end
framework,
framework
head
head
over
over
to
to
Fireship
fireship
IO
io
to
to
check
check
out
out
the
the
full
full
source
source
code
code
and
and
the
the
framework
framework
specific
specific
videos.
videos
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
Thanks
thanks
for
for
watching,
watching
and
and
I
i
will
will
talk
talk
to
to
you
you
soon.
soon
success
The speaker explains the fundamentals of email and how to send it at the right time to increase user engagement. They go through four different strategies for secure event driven code, including a SendGrid account, API key, templates, and SDK. The process of creating a template ID, setting the SendGrid API key, and sending emails is discussed, along with the use of SendGrid and the importance of being logged in and validating email addresses. The speaker also mentions the use of SendGrid and the integration of Fir analysis with a front end framework.
Transactional Email 101 📧 with SendGrid & Firebase Cloud Functions
The fundamentals of transactional email 📧. How to use SendGrid with Firebase Cloud Functions to send email from your app. 

Check out the full lesson for demos with Angular, React, Vue, Svelte, and Flutter. 

SendGrid https://sendgrid.com/
Cloud Functions https://firebase.google.com/docs/functions

#email #firebase #sendgrid

Download the quiz app 🤓

iOS https://itunes.apple.com/us/app/fireship/id1462592372?mt=8
Android https://play.google.com/store/apps/details?id=io.fireship.quizapp

Upgrade to Fireship PRO at https://fireship.io/pro
Use code lORhwXd2 for 25% off your first payment.