Learn how to use Contentful as a CMS for Angular 5 Progressive Web Apps. In this episode, I show you how to use the platform, then write a Firebase Cloud Function that will broadcast push notifications when new content is published. https://angularfirebase.com/lessons/contentful-cms-progressive-web-apps/

Frantic: https://www.frantic.com/
Contentful: https://www.contentful.com/
FCM: https://firebase.google.com/docs/cloud-messaging/
2024-02-04T07:57:27.886Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
f56798c8-42f9-4470-8254-cfff40570c96
68ad08c6a4ea719a32815a0bb6927c4b535dc6f47dddee3445c81f4e7c92b3f6
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
In the nineties, we had static websites.
In the 2000s, we had WordPress.
And today, we have programmable content with Contentful.
It works by treating all of your static content like an API.
Let's imagine your product consists of an Angular progressive web app, a native mobile app, and an Electron desktop app.
Contentful serves as a centralized source for all of your content, so anytime something changes you don't have to redeploy every app individually.
In this episode, I'm going to show you how to It's the platform with an Angular 5 progressive web app and broadcast push notifications out anytime new content is published.
Before we get started, I Want to say thank you to lifetime pro member, Frantic.
They're building amazing enterprise grade apps using similar technologies to what I show you here.
If you're looking for inspiration for modern web app development, be sure to check out their portfolio.
To get started with this tutorial, you'll need to first sign up for a free Contentful account.
And the first thing you'll do is create a space for your content.
Spaces allow you to organize your concerns.
For example, you might have one space for blog post and another space or product listings.
In this example I'm going to create a lesson space that will mirror the content that you'll find on angularfirebase.com.
The next step is to create a content type.
So in this case, our content type is going to be a lesson.
But you might also have content types for the author profile or a category listing or any other chunk of content that you can imagine.
After you've created your content type, The next step is to add some fields to it.
A field would be any property related to your actual content type.
So in this case, we're going to set a title field.
The beauty of this platform is that you can standardize and validate each field.
Doing this from scratch would be a ton of extra work for a developer.
The end result is a consistent blueprint for your content that you can handle differently on any platform.
After you have your blueprint created, you can then use Contentful's text editor to Easily add new content.
This is a powerful feature when you have team members who create content for your apps, but aren't actually programmers.
So your content creators get this text editor and your programmers don't have to worry about building one from scratch.
That sums up the basic process for building content with Contentful.
Now let's switch over to Angular and actually use this in our progressive web app.
I'm starting from a brand new Angular app, so run ng new and then cd into the app.
And then the only dependencies are Contentful and a library called Marked, which we're going to use to convert markdown to raw HTML.
Then to interact with the API, I'm going to create a service called Contentful and make sure to add that to the app module.
From there, go back into Contentful and go to the API tab, then copy the space ID and the content delivery token.
Then you'll add these to your environment TS file inside of Angular.
Make sure that you're using the Content Delivery Token.
You don't want to expose any API Token that has the right access to your Contentful API.
From here, we're going to jump into the Service.
And the first thing we'll do is import the Contentful SDK.
And we also need the environment variables that we just configured as well as the RxJS observable class.
So the first thing we need to do is initialize the SDK client.
We do that by calling Contentful create client along with our space ID and our API token.
The first thing I wanna do is console log out the content just so you know what the actual JavaScript object looks like.
We can retrieve a single piece of content, which in this case is our lesson by calling client Get Entry with the entry ID.
That's going to return a Promise which will resolve with the actual lesson content that we To use this method, I'm going to switch over to the App component, then I import the service and I set Up a variable here as an observable that will hold our lesson content here in the next step, then we can inject the service in the constructor.
And during n g on init, we'll call the method that we just defined which will log the content in the browser console.
Each piece of content is assigned a unique ID, so So I'm just copying and pasting that as the argument to our method.
If we load the app, you see we get the content here logged in the console.
It has 2 main properties, the fields property is all of our content.
This is the actual data that we wanna show to the user in the front end.
It corresponds exactly to the field types that you defined in Contentful.
It also has a system property which has some additional metadata about the content.
You may or may not wanna use this depending on your particular use case.
Now that we know what the content looks like, let's convert it into an Observable so it's more Angular friendly.
So I'm creating a get content method here which will first define the Promise in a variable.
It's calling the same client get entry method with the content ID.
Then we can convert it to an observable by calling observable from Promise, and then I'm going to map it down just to the fields.
That's the content that we wanna show the end user.
We don't really need that extra metadata.
To make use of it, I'm switching back to the App component, Then I define the lesson variable by calling this method with the corresponding content ID.
Now we can treat it like a regular Observable in the HTML.
If If you're already familiar with Angular, this code should look very familiar to you.
So first we'll unwrap the Observable by calling n g f and then use the async pipe And then we'll set it to a template variable called lesson.
From there, it's extremely easy to just call the lesson properties directly on the object.
So we'll display the lesson title, Then, uh, created at timestamp is a JavaScript date object, so we can use the Angular date pipe to display that in a user friendly way.
The lesson tags are saved as an array in Contentful, so we can loop over those tags using n g 4.
Then the only issue we're going to run into is when we display the lesson body, and I'll show you why here in just a second.
Here's what we have so far in Angular.
Our title and our tags look great, but if you look closely at the body, It's written in markdown format.
It's just a raw string instead of the actual HTML that we wanna display to the user in the front end.
When you write markdown, it looks like this, but Angular has no way of parsing this automatically.
What we're going to do is create an Angular pipe called md to HTML, And it's going to take advantage of the Marked Library we installed earlier to parse the markdown to HTML.
First, I'm going to go back into the service And we're going to import the Marked Library there.
I'm defining this method in the service just to make it a little more flexible to work with.
So it just takes a markdown string as an argument, And then it calls the marked library to convert it to HTML.
Then we can import the Contentful service inside of our pipe And we'll inject that in the constructor just like we would in a component.
Then all we have to do is take the input value and call the method we just created in the Service on that value.
Then we can add the pipe to our lesson body, but it's still only gonna display a string.
So at this point, we just have a string of HTML code.
What we can do is bind this to the inner HTML property on a div.
This will render it as actual HTML elements, which is what we want to display to the end user.
But just a quick warning, you always wanna make sure that the source of the HTML comes from a trusted location.
If users generate this Content, you wanna make sure to sanitize it to avoid being vulnerable to cross site scripting.
You can read more about this in the official docs.
If we go back into our Angular app, you can now see that our links and our headings are displaying like normal HTML.
Just like that, we now have a powerful content management system to organize content in our progressive web app.
But I did promise you one more thing and that's sending push notifications anytime new content is created in Contentful.
I don't have time to show you push notifications end to end, but I do have multiple lessons covering that topic on angular firebase.com.
What I am going to show you is how to set up webhooks in Contentful and then broadcast notifications using Firebase Cloud Messaging.
Back in Angular, I have Firebase Cloud Functions initialized in my project.
Then I'm going to write a function that uses the admin SDK.
We're going to listen for webhooks from Contentful, And when we receive 1, we're going to parse it and then broadcast messages out to a certain topic.
The webhook is going to send us data whenever a new lesson is published.
All of the lesson details will be in the request body.
So we can say request body fields and the topic we wanna send messages to is lessons.
Then we can use this data to set the notification details.
So we'll say new lesson posted and then we'll say angularfirebase.com posted a new lesson about whatever the lesson title is.
And then we'll also add an icon to it.
Then we can call the Firebase Messaging Library And just call send a topic with that notification payload.
If you're lost at this point, make sure to check out some of my Firebase push notification videos.
This is going to return a Promise.
And if it's successful, then we can send a successful response back to the webhook.
If the message notifications fail, we can send an error response back to Contentful telling it to retry the webhook if necessary.
And it's really that simple.
All we have to do is deploy the function, then we'll go back into Contentful and tell it when and where to send the webhook.
After the function deploy succeeds, make sure to copy and paste the URL that Firebase gives back to you.
Then back in Contentful, you'll go into the space settings And then to Webhooks and then we'll just give it a name of Topic Notifications then copy and paste the URL that Firebase gave you back for that Cloud Function.
Then we only want to send this Webhook when new content is published.
So we can do that by going down to only selected events And then click the box that intersects Entry and Publish.
You can verify that the Webhook works by going back into the Content tab And then create a new piece of content.
After that, you can go back to the webhook screen, and you should see a successful response from the Cloud Function.
It will show you the webhook body that was sent by Contentful and then show you the response that was received from Firebase.
That's it for Angular 5 with Contentful.
If this video helped you, please like and subscribe.
And if you want to learn more advanced features of progressive web apps, consider becoming a pro Subscriber@angularfirebase.com.
You'll get a free copy of my book as well as 1 on 1 project support.
Thanks for watching and I'll see you next time.

Speaker 0: In the nineties, we had static websites. In the 2000s, we had WordPress. And today, we have programmable content with Contentful. It works by treating all of your static content like an API. Let's imagine your product consists of an Angular progressive web app, a native mobile app, and an Electron desktop app.

Contentful serves as a centralized source for all of your content, so anytime something changes you don't have to redeploy every app individually. In this episode, I'm going to show you how to It's the platform with an Angular 5 progressive web app and broadcast push notifications out anytime new content is published. Before we get started, I Want to say thank you to lifetime pro member, Frantic. They're building amazing enterprise grade apps using similar technologies to what I show you here. If you're looking for inspiration for modern web app development, be sure to check out their portfolio.

To get started with this tutorial, you'll need to first sign up for a free Contentful account. And the first thing you'll do is create a space for your content. Spaces allow you to organize your concerns. For example, you might have one space for blog post and another space or product listings. In this example I'm going to create a lesson space that will mirror the content that you'll find on angularfirebase.com.

The next step is to create a content type. So in this case, our content type is going to be a lesson. But you might also have content types for the author profile or a category listing or any other chunk of content that you can imagine. After you've created your content type, The next step is to add some fields to it. A field would be any property related to your actual content type.

So in this case, we're going to set a title field. The beauty of this platform is that you can standardize and validate each field. Doing this from scratch would be a ton of extra work for a developer. The end result is a consistent blueprint for your content that you can handle differently on any platform. After you have your blueprint created, you can then use Contentful's text editor to Easily add new content.

This is a powerful feature when you have team members who create content for your apps, but aren't actually programmers. So your content creators get this text editor and your programmers don't have to worry about building one from scratch. That sums up the basic process for building content with Contentful. Now let's switch over to Angular and actually use this in our progressive web app. I'm starting from a brand new Angular app, so run ng new and then cd into the app.

And then the only dependencies are Contentful and a library called Marked, which we're going to use to convert markdown to raw HTML. Then to interact with the API, I'm going to create a service called Contentful and make sure to add that to the app module. From there, go back into Contentful and go to the API tab, then copy the space ID and the content delivery token. Then you'll add these to your environment TS file inside of Angular. Make sure that you're using the Content Delivery Token.

You don't want to expose any API Token that has the right access to your Contentful API. From here, we're going to jump into the Service. And the first thing we'll do is import the Contentful SDK. And we also need the environment variables that we just configured as well as the RxJS observable class. So the first thing we need to do is initialize the SDK client.

We do that by calling Contentful create client along with our space ID and our API token. The first thing I wanna do is console log out the content just so you know what the actual JavaScript object looks like. We can retrieve a single piece of content, which in this case is our lesson by calling client Get Entry with the entry ID. That's going to return a Promise which will resolve with the actual lesson content that we To use this method, I'm going to switch over to the App component, then I import the service and I set Up a variable here as an observable that will hold our lesson content here in the next step, then we can inject the service in the constructor. And during n g on init, we'll call the method that we just defined which will log the content in the browser console.

Each piece of content is assigned a unique ID, so So I'm just copying and pasting that as the argument to our method. If we load the app, you see we get the content here logged in the console. It has 2 main properties, the fields property is all of our content. This is the actual data that we wanna show to the user in the front end. It corresponds exactly to the field types that you defined in Contentful.

It also has a system property which has some additional metadata about the content. You may or may not wanna use this depending on your particular use case. Now that we know what the content looks like, let's convert it into an Observable so it's more Angular friendly. So I'm creating a get content method here which will first define the Promise in a variable. It's calling the same client get entry method with the content ID.

Then we can convert it to an observable by calling observable from Promise, and then I'm going to map it down just to the fields. That's the content that we wanna show the end user. We don't really need that extra metadata. To make use of it, I'm switching back to the App component, Then I define the lesson variable by calling this method with the corresponding content ID. Now we can treat it like a regular Observable in the HTML.

If If you're already familiar with Angular, this code should look very familiar to you. So first we'll unwrap the Observable by calling n g f and then use the async pipe And then we'll set it to a template variable called lesson. From there, it's extremely easy to just call the lesson properties directly on the object. So we'll display the lesson title, Then, uh, created at timestamp is a JavaScript date object, so we can use the Angular date pipe to display that in a user friendly way. The lesson tags are saved as an array in Contentful, so we can loop over those tags using n g 4.

Then the only issue we're going to run into is when we display the lesson body, and I'll show you why here in just a second. Here's what we have so far in Angular. Our title and our tags look great, but if you look closely at the body, It's written in markdown format. It's just a raw string instead of the actual HTML that we wanna display to the user in the front end. When you write markdown, it looks like this, but Angular has no way of parsing this automatically.

What we're going to do is create an Angular pipe called md to HTML, And it's going to take advantage of the Marked Library we installed earlier to parse the markdown to HTML. First, I'm going to go back into the service And we're going to import the Marked Library there. I'm defining this method in the service just to make it a little more flexible to work with. So it just takes a markdown string as an argument, And then it calls the marked library to convert it to HTML. Then we can import the Contentful service inside of our pipe And we'll inject that in the constructor just like we would in a component.

Then all we have to do is take the input value and call the method we just created in the Service on that value. Then we can add the pipe to our lesson body, but it's still only gonna display a string. So at this point, we just have a string of HTML code. What we can do is bind this to the inner HTML property on a div. This will render it as actual HTML elements, which is what we want to display to the end user.

But just a quick warning, you always wanna make sure that the source of the HTML comes from a trusted location. If users generate this Content, you wanna make sure to sanitize it to avoid being vulnerable to cross site scripting. You can read more about this in the official docs. If we go back into our Angular app, you can now see that our links and our headings are displaying like normal HTML. Just like that, we now have a powerful content management system to organize content in our progressive web app.

But I did promise you one more thing and that's sending push notifications anytime new content is created in Contentful. I don't have time to show you push notifications end to end, but I do have multiple lessons covering that topic on angular firebase.com. What I am going to show you is how to set up webhooks in Contentful and then broadcast notifications using Firebase Cloud Messaging. Back in Angular, I have Firebase Cloud Functions initialized in my project. Then I'm going to write a function that uses the admin SDK.

We're going to listen for webhooks from Contentful, And when we receive 1, we're going to parse it and then broadcast messages out to a certain topic. The webhook is going to send us data whenever a new lesson is published. All of the lesson details will be in the request body. So we can say request body fields and the topic we wanna send messages to is lessons. Then we can use this data to set the notification details.

So we'll say new lesson posted and then we'll say angularfirebase.com posted a new lesson about whatever the lesson title is. And then we'll also add an icon to it. Then we can call the Firebase Messaging Library And just call send a topic with that notification payload. If you're lost at this point, make sure to check out some of my Firebase push notification videos. This is going to return a Promise.

And if it's successful, then we can send a successful response back to the webhook. If the message notifications fail, we can send an error response back to Contentful telling it to retry the webhook if necessary. And it's really that simple. All we have to do is deploy the function, then we'll go back into Contentful and tell it when and where to send the webhook. After the function deploy succeeds, make sure to copy and paste the URL that Firebase gives back to you.

Then back in Contentful, you'll go into the space settings And then to Webhooks and then we'll just give it a name of Topic Notifications then copy and paste the URL that Firebase gave you back for that Cloud Function. Then we only want to send this Webhook when new content is published. So we can do that by going down to only selected events And then click the box that intersects Entry and Publish. You can verify that the Webhook works by going back into the Content tab And then create a new piece of content. After that, you can go back to the webhook screen, and you should see a successful response from the Cloud Function.

It will show you the webhook body that was sent by Contentful and then show you the response that was received from Firebase. That's it for Angular 5 with Contentful. If this video helped you, please like and subscribe. And if you want to learn more advanced features of progressive web apps, consider becoming a pro Subscriber@angularfirebase.com. You'll get a free copy of my book as well as 1 on 1 project support.

Thanks for watching and I'll see you next time.
In the nineties, we had static websites. In the 2000s, we had WordPress. And today, we have programmable content with Contentful. It works by treating all of your static content like an API. Let's imagine your product consists of an Angular progressive web app, a native mobile app, and an Electron desktop app. Contentful serves as a centralized source for all of your content, so anytime something changes you don't have to redeploy every app individually. In this episode, I'm going to show you how to It's the platform with an Angular 5 progressive web app and broadcast push notifications out anytime new content is published. Before we get started, I Want to say thank you to lifetime pro member, Frantic. They're building amazing enterprise grade apps using similar technologies to what I show you here. If you're looking for inspiration for modern web app development, be sure to check out their portfolio. To get started with this tutorial, you'll need to first sign up for a free Contentful account. And the first thing you'll do is create a space for your content. Spaces allow you to organize your concerns. For example, you might have one space for blog post and another space or product listings. In this example I'm going to create a lesson space that will mirror the content that you'll find on angularfirebase.com.
animation
technology
space
software development
websites
multimedia
internet
software
The next step is to create a content type.
So in this case, our content type is going to be a lesson. But you might also have content types for the author profile or a category listing or any other chunk of content that you can imagine. After you've created your content type, The next step is to add some fields to it.
publishing
A field would be any property related to your actual content type.
So in this case, we're going to set a title field. The beauty of this platform is that you can standardize and validate each field. Doing this from scratch would be a ton of extra work for a developer. The end result is a consistent blueprint for your content that you can handle differently on any platform. After you have your blueprint created, you can then use Contentful's text editor to Easily add new content. This is a powerful feature when you have team members who create content for your apps, but aren't actually programmers. So your content creators get this text editor and your programmers don't have to worry about building one from scratch. That sums up the basic process for building content with Contentful. Now let's switch over to Angular and actually use this in our progressive web app. I'm starting from a brand new Angular app, so run ng new and then cd into the app.
software development
software
crafts
animation
And then the only dependencies are Contentful and a library called Marked, which we're going to use to convert markdown to raw HTML. Then to interact with the API, I'm going to create a service called Contentful and make sure to add that to the app module. From there, go back into Contentful and go to the API tab, then copy the space ID and the content delivery token.
software
software development
Then you'll add these to your environment TS file inside of Angular.
Make sure that you're using the Content Delivery Token. You don't want to expose any API Token that has the right access to your Contentful API. From here, we're going to jump into the Service. And the first thing we'll do is import the Contentful SDK. And we also need the environment variables that we just configured as well as the RxJS observable class. So the first thing we need to do is initialize the SDK client.
software development
software
We do that by calling Contentful create client along with our space ID and our API token. The first thing I wanna do is console log out the content just so you know what the actual JavaScript object looks like. We can retrieve a single piece of content, which in this case is our lesson by calling client Get Entry with the entry ID. That's going to return a Promise which will resolve with the actual lesson content that we To use this method, I'm going to switch over to the App component, then I import the service and I set Up a variable here as an observable that will hold our lesson content here in the next step, then we can inject the service in the constructor.
And during n g on init, we'll call the method that we just defined which will log the content in the browser console. Each piece of content is assigned a unique ID, so So I'm just copying and pasting that as the argument to our method. If we load the app, you see we get the content here logged in the console.
programming
It has 2 main properties, the fields property is all of our content.
This is the actual data that we wanna show to the user in the front end. It corresponds exactly to the field types that you defined in Contentful. It also has a system property which has some additional metadata about the content. You may or may not wanna use this depending on your particular use case. Now that we know what the content looks like, let's convert it into an Observable so it's more Angular friendly. So I'm creating a get content method here which will first define the Promise in a variable.
data
data analysis
data management
databases
documentation
It's calling the same client get entry method with the content ID. Then we can convert it to an observable by calling observable from Promise, and then I'm going to map it down just to the fields.
That's the content that we wanna show the end user. We don't really need that extra metadata. To make use of it, I'm switching back to the App component, Then I define the lesson variable by calling this method with the corresponding content ID. Now we can treat it like a regular Observable in the HTML.
documentation
If If you're already familiar with Angular, this code should look very familiar to you. So first we'll unwrap the Observable by calling n g f and then use the async pipe And then we'll set it to a template variable called lesson. From there, it's extremely easy to just call the lesson properties directly on the object. So we'll display the lesson title, Then, uh, created at timestamp is a JavaScript date object, so we can use the Angular date pipe to display that in a user friendly way.
The lesson tags are saved as an array in Contentful, so we can loop over those tags using n g 4. Then the only issue we're going to run into is when we display the lesson body, and I'll show you why here in just a second. Here's what we have so far in Angular.
programming
Our title and our tags look great, but if you look closely at the body, It's written in markdown format. It's just a raw string instead of the actual HTML that we wanna display to the user in the front end. When you write markdown, it looks like this, but Angular has no way of parsing this automatically. What we're going to do is create an Angular pipe called md to HTML, And it's going to take advantage of the Marked Library we installed earlier to parse the markdown to HTML. First, I'm going to go back into the service And we're going to import the Marked Library there. I'm defining this method in the service just to make it a little more flexible to work with.
So it just takes a markdown string as an argument, And then it calls the marked library to convert it to HTML. Then we can import the Contentful service inside of our pipe And we'll inject that in the constructor just like we would in a component. Then all we have to do is take the input value and call the method we just created in the Service on that value. Then we can add the pipe to our lesson body, but it's still only gonna display a string. So at this point, we just have a string of HTML code.
programming
What we can do is bind this to the inner HTML property on a div. This will render it as actual HTML elements, which is what we want to display to the end user. But just a quick warning, you always wanna make sure that the source of the HTML comes from a trusted location. If users generate this Content, you wanna make sure to sanitize it to avoid being vulnerable to cross site scripting. You can read more about this in the official docs.
If we go back into our Angular app, you can now see that our links and our headings are displaying like normal HTML. Just like that, we now have a powerful content management system to organize content in our progressive web app. But I did promise you one more thing and that's sending push notifications anytime new content is created in Contentful.
youtube
I don't have time to show you push notifications end to end, but I do have multiple lessons covering that topic on angular firebase.com. What I am going to show you is how to set up webhooks in Contentful and then broadcast notifications using Firebase Cloud Messaging. Back in Angular, I have Firebase Cloud Functions initialized in my project.
Then I'm going to write a function that uses the admin SDK. We're going to listen for webhooks from Contentful, And when we receive 1, we're going to parse it and then broadcast messages out to a certain topic. The webhook is going to send us data whenever a new lesson is published.
programming
All of the lesson details will be in the request body.
So we can say request body fields and the topic we wanna send messages to is lessons. Then we can use this data to set the notification details. So we'll say new lesson posted and then we'll say angularfirebase.com posted a new lesson about whatever the lesson title is. And then we'll also add an icon to it.
teaching
Then we can call the Firebase Messaging Library And just call send a topic with that notification payload. If you're lost at this point, make sure to check out some of my Firebase push notification videos. This is going to return a Promise. And if it's successful, then we can send a successful response back to the webhook. If the message notifications fail, we can send an error response back to Contentful telling it to retry the webhook if necessary. And it's really that simple. All we have to do is deploy the function, then we'll go back into Contentful and tell it when and where to send the webhook. After the function deploy succeeds, make sure to copy and paste the URL that Firebase gives back to you. Then back in Contentful, you'll go into the space settings And then to Webhooks and then we'll just give it a name of Topic Notifications then copy and paste the URL that Firebase gave you back for that Cloud Function. Then we only want to send this Webhook when new content is published. So we can do that by going down to only selected events And then click the box that intersects Entry and Publish. You can verify that the Webhook works by going back into the Content tab And then create a new piece of content. After that, you can go back to the webhook screen, and you should see a successful response from the Cloud Function.
It will show you the webhook body that was sent by Contentful and then show you the response that was received from Firebase. That's it for Angular 5 with Contentful. If this video helped you, please like and subscribe. And if you want to learn more advanced features of progressive web apps, consider becoming a pro Subscriber@angularfirebase.com. You'll get a free copy of my book as well as 1 on 1 project support. Thanks for watching and I'll see you next time.
books
youtube
literature
publishing
In the nineties, we had static websites. In the 2000s, we had WordPress. And today, we have programmable content with Contentful. It works by treating all of your static content like an API. Let's imagine your product consists of an Angular progressive web app, a native mobile app, and an Electron desktop app. Contentful serves as a centralized source for all of your content, so anytime something changes you don't have to redeploy every app individually. In this episode, I'm going to show you how to It's the platform with an Angular 5 progressive web app and broadcast push notifications out anytime new content is published. Before we get started, I Want to say thank you to lifetime pro member, Frantic. They're building amazing enterprise grade apps using similar technologies to what I show you here. If you're looking for inspiration for modern web app development, be sure to check out their portfolio. To get started with this tutorial, you'll need to first sign up for a free Contentful account. And the first thing you'll do is create a space for your content. Spaces allow you to organize your concerns. For example, you might have one space for blog post and another space or product listings. In this example I'm going to create a lesson space that will mirror the content that you'll find on angularfirebase.com. The next step is to create a content type. So in this case, our content type is going to be a lesson. But you might also have content types for the author profile or a category listing or any other chunk of content that you can imagine. After you've created your content type, The next step is to add some fields to it. A field would be any property related to your actual content type. So in this case, we're going to set a title field. The beauty of this platform is that you can standardize and validate each field. Doing this from scratch would be a ton of extra work for a developer. The end result is a consistent blueprint for your content that you can handle differently on any platform. After you have your blueprint created, you can then use Contentful's text editor to Easily add new content. This is a powerful feature when you have team members who create content for your apps, but aren't actually programmers. So your content creators get this text editor and your programmers don't have to worry about building one from scratch. That sums up the basic process for building content with Contentful. Now let's switch over to Angular and actually use this in our progressive web app. I'm starting from a brand new Angular app, so run ng new and then cd into the app. And then the only dependencies are Contentful and a library called Marked, which we're going to use to convert markdown to raw HTML. Then to interact with the API, I'm going to create a service called Contentful and make sure to add that to the app module. From there, go back into Contentful and go to the API tab, then copy the space ID and the content delivery token. Then you'll add these to your environment TS file inside of Angular. Make sure that you're using the Content Delivery Token. You don't want to expose any API Token that has the right access to your Contentful API. From here, we're going to jump into the Service. And the first thing we'll do is import the Contentful SDK. And we also need the environment variables that we just configured as well as the RxJS observable class. So the first thing we need to do is initialize the SDK client. We do that by calling Contentful create client along with our space ID and our API token. The first thing I wanna do is console log out the content just so you know what the actual JavaScript object looks like. We can retrieve a single piece of content, which in this case is our lesson by calling client Get Entry with the entry ID. That's going to return a Promise which will resolve with the actual lesson content that we To use this method, I'm going to switch over to the App component, then I import the service and I set Up a variable here as an observable that will hold our lesson content here in the next step, then we can inject the service in the constructor. And during n g on init, we'll call the method that we just defined which will log the content in the browser console. Each piece of content is assigned a unique ID, so So I'm just copying and pasting that as the argument to our method. If we load the app, you see we get the content here logged in the console. It has 2 main properties, the fields property is all of our content. This is the actual data that we wanna show to the user in the front end. It corresponds exactly to the field types that you defined in Contentful. It also has a system property which has some additional metadata about the content. You may or may not wanna use this depending on your particular use case. Now that we know what the content looks like, let's convert it into an Observable so it's more Angular friendly. So I'm creating a get content method here which will first define the Promise in a variable. It's calling the same client get entry method with the content ID. Then we can convert it to an observable by calling observable from Promise, and then I'm going to map it down just to the fields. That's the content that we wanna show the end user. We don't really need that extra metadata. To make use of it, I'm switching back to the App component, Then I define the lesson variable by calling this method with the corresponding content ID. Now we can treat it like a regular Observable in the HTML. If If you're already familiar with Angular, this code should look very familiar to you. So first we'll unwrap the Observable by calling n g f and then use the async pipe And then we'll set it to a template variable called lesson. From there, it's extremely easy to just call the lesson properties directly on the object. So we'll display the lesson title, Then, uh, created at timestamp is a JavaScript date object, so we can use the Angular date pipe to display that in a user friendly way. The lesson tags are saved as an array in Contentful, so we can loop over those tags using n g 4. Then the only issue we're going to run into is when we display the lesson body, and I'll show you why here in just a second. Here's what we have so far in Angular. Our title and our tags look great, but if you look closely at the body, It's written in markdown format. It's just a raw string instead of the actual HTML that we wanna display to the user in the front end. When you write markdown, it looks like this, but Angular has no way of parsing this automatically. What we're going to do is create an Angular pipe called md to HTML, And it's going to take advantage of the Marked Library we installed earlier to parse the markdown to HTML. First, I'm going to go back into the service And we're going to import the Marked Library there. I'm defining this method in the service just to make it a little more flexible to work with. So it just takes a markdown string as an argument, And then it calls the marked library to convert it to HTML. Then we can import the Contentful service inside of our pipe And we'll inject that in the constructor just like we would in a component. Then all we have to do is take the input value and call the method we just created in the Service on that value. Then we can add the pipe to our lesson body, but it's still only gonna display a string. So at this point, we just have a string of HTML code. What we can do is bind this to the inner HTML property on a div. This will render it as actual HTML elements, which is what we want to display to the end user. But just a quick warning, you always wanna make sure that the source of the HTML comes from a trusted location. If users generate this Content, you wanna make sure to sanitize it to avoid being vulnerable to cross site scripting. You can read more about this in the official docs. If we go back into our Angular app, you can now see that our links and our headings are displaying like normal HTML. Just like that, we now have a powerful content management system to organize content in our progressive web app. But I did promise you one more thing and that's sending push notifications anytime new content is created in Contentful. I don't have time to show you push notifications end to end, but I do have multiple lessons covering that topic on angular firebase.com. What I am going to show you is how to set up webhooks in Contentful and then broadcast notifications using Firebase Cloud Messaging. Back in Angular, I have Firebase Cloud Functions initialized in my project. Then I'm going to write a function that uses the admin SDK. We're going to listen for webhooks from Contentful, And when we receive 1, we're going to parse it and then broadcast messages out to a certain topic. The webhook is going to send us data whenever a new lesson is published. All of the lesson details will be in the request body. So we can say request body fields and the topic we wanna send messages to is lessons. Then we can use this data to set the notification details. So we'll say new lesson posted and then we'll say angularfirebase.com posted a new lesson about whatever the lesson title is. And then we'll also add an icon to it. Then we can call the Firebase Messaging Library And just call send a topic with that notification payload. If you're lost at this point, make sure to check out some of my Firebase push notification videos. This is going to return a Promise. And if it's successful, then we can send a successful response back to the webhook. If the message notifications fail, we can send an error response back to Contentful telling it to retry the webhook if necessary. And it's really that simple. All we have to do is deploy the function, then we'll go back into Contentful and tell it when and where to send the webhook. After the function deploy succeeds, make sure to copy and paste the URL that Firebase gives back to you. Then back in Contentful, you'll go into the space settings And then to Webhooks and then we'll just give it a name of Topic Notifications then copy and paste the URL that Firebase gave you back for that Cloud Function. Then we only want to send this Webhook when new content is published. So we can do that by going down to only selected events And then click the box that intersects Entry and Publish. You can verify that the Webhook works by going back into the Content tab And then create a new piece of content. After that, you can go back to the webhook screen, and you should see a successful response from the Cloud Function. It will show you the webhook body that was sent by Contentful and then show you the response that was received from Firebase. That's it for Angular 5 with Contentful. If this video helped you, please like and subscribe. And if you want to learn more advanced features of progressive web apps, consider becoming a pro Subscriber@angularfirebase.com. You'll get a free copy of my book as well as 1 on 1 project support. Thanks for watching and I'll see you next time.
In
in
the
the
nineties,
nineties
we
we
had
had
static
static
websites.
websites
In
in
the
the
2000s,
2000s
we
we
had
had
WordPress.
wordpress
And
and
today,
today
we
we
have
have
programmable
programmable
content
content
with
with
Contentful.
contentful
It
it
works
works
by
by
treating
treating
all
all
of
of
your
your
static
static
content
content
like
like
an
an
API.
api
Let's
let's
imagine
imagine
your
your
product
product
consists
consists
of
of
an
an
Angular
angular
progressive
progressive
web
web
app,
app
a
a
native
native
mobile
mobile
app,
app
and
and
an
an
Electron
electron
desktop
desktop
app.
app
Contentful
contentful
serves
serves
as
as
a
a
centralized
centralized
source
source
for
for
all
all
of
of
your
your
content,
content
so
so
anytime
anytime
something
something
changes
changes
you
you
don't
don't
have
have
to
to
redeploy
redeploy
every
every
app
app
individually.
individually
In
in
this
this
episode,
episode
I'm
i'm
going
going
to
to
show
show
you
you
how
how
to
to
It's
it's
the
the
platform
platform
with
with
an
an
Angular
angular
5
5
progressive
progressive
web
web
app
app
and
and
broadcast
broadcast
push
push
notifications
notifications
out
out
anytime
anytime
new
new
content
content
is
is
published.
published
Before
before
we
we
get
get
started,
started
I
i
Want
want
to
to
say
say
thank
thank
you
you
to
to
lifetime
lifetime
pro
pro
member,
member
Frantic.
frantic
They're
they're
building
building
amazing
amazing
enterprise
enterprise
grade
grade
apps
apps
using
using
similar
similar
technologies
technologies
to
to
what
what
I
i
show
show
you
you
here.
here
If
if
you're
you're
looking
looking
for
for
inspiration
inspiration
for
for
modern
modern
web
web
app
app
development,
development
be
be
sure
sure
to
to
check
check
out
out
their
their
portfolio.
portfolio
To
to
get
get
started
started
with
with
this
this
tutorial,
tutorial
you'll
you'll
need
need
to
to
first
first
sign
sign
up
up
for
for
a
a
free
free
Contentful
contentful
account.
account
And
and
the
the
first
first
thing
thing
you'll
you'll
do
do
is
is
create
create
a
a
space
space
for
for
your
your
content.
content
Spaces
spaces
allow
allow
you
you
to
to
organize
organize
your
your
concerns.
concerns
For
for
example,
example
you
you
might
might
have
have
one
one
space
space
for
for
blog
blog
post
post
and
and
another
another
space
space
or
or
product
product
listings.
listings
In
in
this
this
example
example
I'm
i'm
going
going
to
to
create
create
a
a
lesson
lesson
space
space
that
that
will
will
mirror
mirror
the
the
content
content
that
that
you'll
you'll
find
find
on
on
angularfirebase.com.
angularfirebase.com
The
the
next
next
step
step
is
is
to
to
create
create
a
a
content
content
type.
type
So
so
in
in
this
this
case,
case
our
our
content
content
type
type
is
is
going
going
to
to
be
be
a
a
lesson.
lesson
But
but
you
you
might
might
also
also
have
have
content
content
types
types
for
for
the
the
author
author
profile
profile
or
or
a
a
category
category
listing
listing
or
or
any
any
other
other
chunk
chunk
of
of
content
content
that
that
you
you
can
can
imagine.
imagine
After
after
you've
you've
created
created
your
your
content
content
type,
type
The
the
next
next
step
step
is
is
to
to
add
add
some
some
fields
fields
to
to
it.
it
A
a
field
field
would
would
be
be
any
any
property
property
related
related
to
to
your
your
actual
actual
content
content
type.
type
So
so
in
in
this
this
case,
case
we're
we're
going
going
to
to
set
set
a
a
title
title
field.
field
The
the
beauty
beauty
of
of
this
this
platform
platform
is
is
that
that
you
you
can
can
standardize
standardize
and
and
validate
validate
each
each
field.
field
Doing
doing
this
this
from
from
scratch
scratch
would
would
be
be
a
a
ton
ton
of
of
extra
extra
work
work
for
for
a
a
developer.
developer
The
the
end
end
result
result
is
is
a
a
consistent
consistent
blueprint
blueprint
for
for
your
your
content
content
that
that
you
you
can
can
handle
handle
differently
differently
on
on
any
any
platform.
platform
After
after
you
you
have
have
your
your
blueprint
blueprint
created,
created
you
you
can
can
then
then
use
use
Contentful's
contentful's
text
text
editor
editor
to
to
Easily
easily
add
add
new
new
content.
content
This
this
is
is
a
a
powerful
powerful
feature
feature
when
when
you
you
have
have
team
team
members
members
who
who
create
create
content
content
for
for
your
your
apps,
apps
but
but
aren't
aren't
actually
actually
programmers.
programmers
So
so
your
your
content
content
creators
creators
get
get
this
this
text
text
editor
editor
and
and
your
your
programmers
programmers
don't
don't
have
have
to
to
worry
worry
about
about
building
building
one
one
from
from
scratch.
scratch
That
that
sums
sums
up
up
the
the
basic
basic
process
process
for
for
building
building
content
content
with
with
Contentful.
contentful
Now
now
let's
let's
switch
switch
over
over
to
to
Angular
angular
and
and
actually
actually
use
use
this
this
in
in
our
our
progressive
progressive
web
web
app.
app
I'm
i'm
starting
starting
from
from
a
a
brand
brand
new
new
Angular
angular
app,
app
so
so
run
run
ng
ng
new
new
and
and
then
then
cd
cd
into
into
the
the
app.
app
And
and
then
then
the
the
only
only
dependencies
dependencies
are
are
Contentful
contentful
and
and
a
a
library
library
called
called
Marked,
marked
which
which
we're
we're
going
going
to
to
use
use
to
to
convert
convert
markdown
markdown
to
to
raw
raw
HTML.
html
Then
then
to
to
interact
interact
with
with
the
the
API,
api
I'm
i'm
going
going
to
to
create
create
a
a
service
service
called
called
Contentful
contentful
and
and
make
make
sure
sure
to
to
add
add
that
that
to
to
the
the
app
app
module.
module
From
from
there,
there
go
go
back
back
into
into
Contentful
contentful
and
and
go
go
to
to
the
the
API
api
tab,
tab
then
then
copy
copy
the
the
space
space
ID
id
and
and
the
the
content
content
delivery
delivery
token.
token
Then
then
you'll
you'll
add
add
these
these
to
to
your
your
environment
environment
TS
ts
file
file
inside
inside
of
of
Angular.
angular
Make
make
sure
sure
that
that
you're
you're
using
using
the
the
Content
content
Delivery
delivery
Token.
token
You
you
don't
don't
want
want
to
to
expose
expose
any
any
API
api
Token
token
that
that
has
has
the
the
right
right
access
access
to
to
your
your
Contentful
contentful
API.
api
From
from
here,
here
we're
we're
going
going
to
to
jump
jump
into
into
the
the
Service.
service
And
and
the
the
first
first
thing
thing
we'll
we'll
do
do
is
is
import
import
the
the
Contentful
contentful
SDK.
sdk
And
and
we
we
also
also
need
need
the
the
environment
environment
variables
variables
that
that
we
we
just
just
configured
configured
as
as
well
well
as
as
the
the
RxJS
rxjs
observable
observable
class.
class
So
so
the
the
first
first
thing
thing
we
we
need
need
to
to
do
do
is
is
initialize
initialize
the
the
SDK
sdk
client.
client
We
we
do
do
that
that
by
by
calling
calling
Contentful
contentful
create
create
client
client
along
along
with
with
our
our
space
space
ID
id
and
and
our
our
API
api
token.
token
The
the
first
first
thing
thing
I
i
wanna
wanna
do
do
is
is
console
console
log
log
out
out
the
the
content
content
just
just
so
so
you
you
know
know
what
what
the
the
actual
actual
JavaScript
javascript
object
object
looks
looks
like.
like
We
we
can
can
retrieve
retrieve
a
a
single
single
piece
piece
of
of
content,
content
which
which
in
in
this
this
case
case
is
is
our
our
lesson
lesson
by
by
calling
calling
client
client
Get
get
Entry
entry
with
with
the
the
entry
entry
ID.
id
That's
that's
going
going
to
to
return
return
a
a
Promise
promise
which
which
will
will
resolve
resolve
with
with
the
the
actual
actual
lesson
lesson
content
content
that
that
we
we
To
to
use
use
this
this
method,
method
I'm
i'm
going
going
to
to
switch
switch
over
over
to
to
the
the
App
app
component,
component
then
then
I
i
import
import
the
the
service
service
and
and
I
i
set
set
Up
up
a
a
variable
variable
here
here
as
as
an
an
observable
observable
that
that
will
will
hold
hold
our
our
lesson
lesson
content
content
here
here
in
in
the
the
next
next
step,
step
then
then
we
we
can
can
inject
inject
the
the
service
service
in
in
the
the
constructor.
constructor
And
and
during
during
n
n
g
g
on
on
init,
init
we'll
we'll
call
call
the
the
method
method
that
that
we
we
just
just
defined
defined
which
which
will
will
log
log
the
the
content
content
in
in
the
the
browser
browser
console.
console
Each
each
piece
piece
of
of
content
content
is
is
assigned
assigned
a
a
unique
unique
ID,
id
so
so
So
so
I'm
i'm
just
just
copying
copying
and
and
pasting
pasting
that
that
as
as
the
the
argument
argument
to
to
our
our
method.
method
If
if
we
we
load
load
the
the
app,
app
you
you
see
see
we
we
get
get
the
the
content
content
here
here
logged
logged
in
in
the
the
console.
console
It
it
has
has
2
2
main
main
properties,
properties
the
the
fields
fields
property
property
is
is
all
all
of
of
our
our
content.
content
This
this
is
is
the
the
actual
actual
data
data
that
that
we
we
wanna
wanna
show
show
to
to
the
the
user
user
in
in
the
the
front
front
end.
end
It
it
corresponds
corresponds
exactly
exactly
to
to
the
the
field
field
types
types
that
that
you
you
defined
defined
in
in
Contentful.
contentful
It
it
also
also
has
has
a
a
system
system
property
property
which
which
has
has
some
some
additional
additional
metadata
metadata
about
about
the
the
content.
content
You
you
may
may
or
or
may
may
not
not
wanna
wanna
use
use
this
this
depending
depending
on
on
your
your
particular
particular
use
use
case.
case
Now
now
that
that
we
we
know
know
what
what
the
the
content
content
looks
looks
like,
like
let's
let's
convert
convert
it
it
into
into
an
an
Observable
observable
so
so
it's
it's
more
more
Angular
angular
friendly.
friendly
So
so
I'm
i'm
creating
creating
a
a
get
get
content
content
method
method
here
here
which
which
will
will
first
first
define
define
the
the
Promise
promise
in
in
a
a
variable.
variable
It's
it's
calling
calling
the
the
same
same
client
client
get
get
entry
entry
method
method
with
with
the
the
content
content
ID.
id
Then
then
we
we
can
can
convert
convert
it
it
to
to
an
an
observable
observable
by
by
calling
calling
observable
observable
from
from
Promise,
promise
and
and
then
then
I'm
i'm
going
going
to
to
map
map
it
it
down
down
just
just
to
to
the
the
fields.
fields
That's
that's
the
the
content
content
that
that
we
we
wanna
wanna
show
show
the
the
end
end
user.
user
We
we
don't
don't
really
really
need
need
that
that
extra
extra
metadata.
metadata
To
to
make
make
use
use
of
of
it,
it
I'm
i'm
switching
switching
back
back
to
to
the
the
App
app
component,
component
Then
then
I
i
define
define
the
the
lesson
lesson
variable
variable
by
by
calling
calling
this
this
method
method
with
with
the
the
corresponding
corresponding
content
content
ID.
id
Now
now
we
we
can
can
treat
treat
it
it
like
like
a
a
regular
regular
Observable
observable
in
in
the
the
HTML.
html
If
if
If
if
you're
you're
already
already
familiar
familiar
with
with
Angular,
angular
this
this
code
code
should
should
look
look
very
very
familiar
familiar
to
to
you.
you
So
so
first
first
we'll
we'll
unwrap
unwrap
the
the
Observable
observable
by
by
calling
calling
n
n
g
g
f
f
and
and
then
then
use
use
the
the
async
async
pipe
pipe
And
and
then
then
we'll
we'll
set
set
it
it
to
to
a
a
template
template
variable
variable
called
called
lesson.
lesson
From
from
there,
there
it's
it's
extremely
extremely
easy
easy
to
to
just
just
call
call
the
the
lesson
lesson
properties
properties
directly
directly
on
on
the
the
object.
object
So
so
we'll
we'll
display
display
the
the
lesson
lesson
title,
title
Then,
then
uh,
uh
created
created
at
at
timestamp
timestamp
is
is
a
a
JavaScript
javascript
date
date
object,
object
so
so
we
we
can
can
use
use
the
the
Angular
angular
date
date
pipe
pipe
to
to
display
display
that
that
in
in
a
a
user
user
friendly
friendly
way.
way
The
the
lesson
lesson
tags
tags
are
are
saved
saved
as
as
an
an
array
array
in
in
Contentful,
contentful
so
so
we
we
can
can
loop
loop
over
over
those
those
tags
tags
using
using
n
n
g
g
4.
4
Then
then
the
the
only
only
issue
issue
we're
we're
going
going
to
to
run
run
into
into
is
is
when
when
we
we
display
display
the
the
lesson
lesson
body,
body
and
and
I'll
i'll
show
show
you
you
why
why
here
here
in
in
just
just
a
a
second.
second
Here's
here's
what
what
we
we
have
have
so
so
far
far
in
in
Angular.
angular
Our
our
title
title
and
and
our
our
tags
tags
look
look
great,
great
but
but
if
if
you
you
look
look
closely
closely
at
at
the
the
body,
body
It's
it's
written
written
in
in
markdown
markdown
format.
format
It's
it's
just
just
a
a
raw
raw
string
string
instead
instead
of
of
the
the
actual
actual
HTML
html
that
that
we
we
wanna
wanna
display
display
to
to
the
the
user
user
in
in
the
the
front
front
end.
end
When
when
you
you
write
write
markdown,
markdown
it
it
looks
looks
like
like
this,
this
but
but
Angular
angular
has
has
no
no
way
way
of
of
parsing
parsing
this
this
automatically.
automatically
What
what
we're
we're
going
going
to
to
do
do
is
is
create
create
an
an
Angular
angular
pipe
pipe
called
called
md
md
to
to
HTML,
html
And
and
it's
it's
going
going
to
to
take
take
advantage
advantage
of
of
the
the
Marked
marked
Library
library
we
we
installed
installed
earlier
earlier
to
to
parse
parse
the
the
markdown
markdown
to
to
HTML.
html
First,
first
I'm
i'm
going
going
to
to
go
go
back
back
into
into
the
the
service
service
And
and
we're
we're
going
going
to
to
import
import
the
the
Marked
marked
Library
library
there.
there
I'm
i'm
defining
defining
this
this
method
method
in
in
the
the
service
service
just
just
to
to
make
make
it
it
a
a
little
little
more
more
flexible
flexible
to
to
work
work
with.
with
So
so
it
it
just
just
takes
takes
a
a
markdown
markdown
string
string
as
as
an
an
argument,
argument
And
and
then
then
it
it
calls
calls
the
the
marked
marked
library
library
to
to
convert
convert
it
it
to
to
HTML.
html
Then
then
we
we
can
can
import
import
the
the
Contentful
contentful
service
service
inside
inside
of
of
our
our
pipe
pipe
And
and
we'll
we'll
inject
inject
that
that
in
in
the
the
constructor
constructor
just
just
like
like
we
we
would
would
in
in
a
a
component.
component
Then
then
all
all
we
we
have
have
to
to
do
do
is
is
take
take
the
the
input
input
value
value
and
and
call
call
the
the
method
method
we
we
just
just
created
created
in
in
the
the
Service
service
on
on
that
that
value.
value
Then
then
we
we
can
can
add
add
the
the
pipe
pipe
to
to
our
our
lesson
lesson
body,
body
but
but
it's
it's
still
still
only
only
gonna
gonna
display
display
a
a
string.
string
So
so
at
at
this
this
point,
point
we
we
just
just
have
have
a
a
string
string
of
of
HTML
html
code.
code
What
what
we
we
can
can
do
do
is
is
bind
bind
this
this
to
to
the
the
inner
inner
HTML
html
property
property
on
on
a
a
div.
div
This
this
will
will
render
render
it
it
as
as
actual
actual
HTML
html
elements,
elements
which
which
is
is
what
what
we
we
want
want
to
to
display
display
to
to
the
the
end
end
user.
user
But
but
just
just
a
a
quick
quick
warning,
warning
you
you
always
always
wanna
wanna
make
make
sure
sure
that
that
the
the
source
source
of
of
the
the
HTML
html
comes
comes
from
from
a
a
trusted
trusted
location.
location
If
if
users
users
generate
generate
this
this
Content,
content
you
you
wanna
wanna
make
make
sure
sure
to
to
sanitize
sanitize
it
it
to
to
avoid
avoid
being
being
vulnerable
vulnerable
to
to
cross
cross
site
site
scripting.
scripting
You
you
can
can
read
read
more
more
about
about
this
this
in
in
the
the
official
official
docs.
docs
If
if
we
we
go
go
back
back
into
into
our
our
Angular
angular
app,
app
you
you
can
can
now
now
see
see
that
that
our
our
links
links
and
and
our
our
headings
headings
are
are
displaying
displaying
like
like
normal
normal
HTML.
html
Just
just
like
like
that,
that
we
we
now
now
have
have
a
a
powerful
powerful
content
content
management
management
system
system
to
to
organize
organize
content
content
in
in
our
our
progressive
progressive
web
web
app.
app
But
but
I
i
did
did
promise
promise
you
you
one
one
more
more
thing
thing
and
and
that's
that's
sending
sending
push
push
notifications
notifications
anytime
anytime
new
new
content
content
is
is
created
created
in
in
Contentful.
contentful
I
i
don't
don't
have
have
time
time
to
to
show
show
you
you
push
push
notifications
notifications
end
end
to
to
end,
end
but
but
I
i
do
do
have
have
multiple
multiple
lessons
lessons
covering
covering
that
that
topic
topic
on
on
angular
angular
firebase.com.
firebase.com
What
what
I
i
am
am
going
going
to
to
show
show
you
you
is
is
how
how
to
to
set
set
up
up
webhooks
webhooks
in
in
Contentful
contentful
and
and
then
then
broadcast
broadcast
notifications
notifications
using
using
Firebase
firebase
Cloud
cloud
Messaging.
messaging
Back
back
in
in
Angular,
angular
I
i
have
have
Firebase
firebase
Cloud
cloud
Functions
functions
initialized
initialized
in
in
my
my
project.
project
Then
then
I'm
i'm
going
going
to
to
write
write
a
a
function
function
that
that
uses
uses
the
the
admin
admin
SDK.
sdk
We're
we're
going
going
to
to
listen
listen
for
for
webhooks
webhooks
from
from
Contentful,
contentful
And
and
when
when
we
we
receive
receive
1,
1
we're
we're
going
going
to
to
parse
parse
it
it
and
and
then
then
broadcast
broadcast
messages
messages
out
out
to
to
a
a
certain
certain
topic.
topic
The
the
webhook
webhook
is
is
going
going
to
to
send
send
us
us
data
data
whenever
whenever
a
a
new
new
lesson
lesson
is
is
published.
published
All
all
of
of
the
the
lesson
lesson
details
details
will
will
be
be
in
in
the
the
request
request
body.
body
So
so
we
we
can
can
say
say
request
request
body
body
fields
fields
and
and
the
the
topic
topic
we
we
wanna
wanna
send
send
messages
messages
to
to
is
is
lessons.
lessons
Then
then
we
we
can
can
use
use
this
this
data
data
to
to
set
set
the
the
notification
notification
details.
details
So
so
we'll
we'll
say
say
new
new
lesson
lesson
posted
posted
and
and
then
then
we'll
we'll
say
say
angularfirebase.com
angularfirebase.com
posted
posted
a
a
new
new
lesson
lesson
about
about
whatever
whatever
the
the
lesson
lesson
title
title
is.
is
And
and
then
then
we'll
we'll
also
also
add
add
an
an
icon
icon
to
to
it.
it
Then
then
we
we
can
can
call
call
the
the
Firebase
firebase
Messaging
messaging
Library
library
And
and
just
just
call
call
send
send
a
a
topic
topic
with
with
that
that
notification
notification
payload.
payload
If
if
you're
you're
lost
lost
at
at
this
this
point,
point
make
make
sure
sure
to
to
check
check
out
out
some
some
of
of
my
my
Firebase
firebase
push
push
notification
notification
videos.
videos
This
this
is
is
going
going
to
to
return
return
a
a
Promise.
promise
And
and
if
if
it's
it's
successful,
successful
then
then
we
we
can
can
send
send
a
a
successful
successful
response
response
back
back
to
to
the
the
webhook.
webhook
If
if
the
the
message
message
notifications
notifications
fail,
fail
we
we
can
can
send
send
an
an
error
error
response
response
back
back
to
to
Contentful
contentful
telling
telling
it
it
to
to
retry
retry
the
the
webhook
webhook
if
if
necessary.
necessary
And
and
it's
it's
really
really
that
that
simple.
simple
All
all
we
we
have
have
to
to
do
do
is
is
deploy
deploy
the
the
function,
function
then
then
we'll
we'll
go
go
back
back
into
into
Contentful
contentful
and
and
tell
tell
it
it
when
when
and
and
where
where
to
to
send
send
the
the
webhook.
webhook
After
after
the
the
function
function
deploy
deploy
succeeds,
succeeds
make
make
sure
sure
to
to
copy
copy
and
and
paste
paste
the
the
URL
url
that
that
Firebase
firebase
gives
gives
back
back
to
to
you.
you
Then
then
back
back
in
in
Contentful,
contentful
you'll
you'll
go
go
into
into
the
the
space
space
settings
settings
And
and
then
then
to
to
Webhooks
webhooks
and
and
then
then
we'll
we'll
just
just
give
give
it
it
a
a
name
name
of
of
Topic
topic
Notifications
notifications
then
then
copy
copy
and
and
paste
paste
the
the
URL
url
that
that
Firebase
firebase
gave
gave
you
you
back
back
for
for
that
that
Cloud
cloud
Function.
function
Then
then
we
we
only
only
want
want
to
to
send
send
this
this
Webhook
webhook
when
when
new
new
content
content
is
is
published.
published
So
so
we
we
can
can
do
do
that
that
by
by
going
going
down
down
to
to
only
only
selected
selected
events
events
And
and
then
then
click
click
the
the
box
box
that
that
intersects
intersects
Entry
entry
and
and
Publish.
publish
You
you
can
can
verify
verify
that
that
the
the
Webhook
webhook
works
works
by
by
going
going
back
back
into
into
the
the
Content
content
tab
tab
And
and
then
then
create
create
a
a
new
new
piece
piece
of
of
content.
content
After
after
that,
that
you
you
can
can
go
go
back
back
to
to
the
the
webhook
webhook
screen,
screen
and
and
you
you
should
should
see
see
a
a
successful
successful
response
response
from
from
the
the
Cloud
cloud
Function.
function
It
it
will
will
show
show
you
you
the
the
webhook
webhook
body
body
that
that
was
was
sent
sent
by
by
Contentful
contentful
and
and
then
then
show
show
you
you
the
the
response
response
that
that
was
was
received
received
from
from
Firebase.
firebase
That's
that's
it
it
for
for
Angular
angular
5
5
with
with
Contentful.
contentful
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
subscribe.
subscribe
And
and
if
if
you
you
want
want
to
to
learn
learn
more
more
advanced
advanced
features
features
of
of
progressive
progressive
web
web
apps,
apps
consider
consider
becoming
becoming
a
a
pro
pro
Subscriber@angularfirebase.com.
subscriber@angularfirebase.com
You'll
you'll
get
get
a
a
free
free
copy
copy
of
of
my
my
book
book
as
as
well
well
as
as
1
1
on
on
1
1
project
project
support.
support
Thanks
thanks
for
for
watching
watching
and
and
I'll
i'll
see
see
you
you
next
next
time.
time
success
The speakers discuss the use of a platform called contentful for web app development, which allows for organized content creation and validation. They also explain how to sign up for a free content creation account and use it in a web app. The process involves creating a get content method, mapping it down to fields, and importing the content delivery token. The speakers also explain how to use the Marked Library and content management system in the web app, as well as setting up web reminded and push notifications. They also explain how to set up web chunking and send a message to a certain topic using the Azure cloud service.
Contentful - CMS for Angular Progressive Web Apps
In the nineties, we had static websites. In the 2000s, we had WordPress. And today, we have programmable content with Contentful. It works by treating all of your static content like an API. Let's imagine your product consists of an Angular progressive web app, a native mobile app, and an Electron desktop app. Contentful serves as a centralized source for all of your content, so anytime something changes you don't have to redeploy every app individually. In this episode, I'm going to show you how to It's the platform with an Angular 5 progressive web app and broadcast push notifications out anytime new content is published. Before we get started, I Want to say thank you to lifetime pro member, Frantic. They're building amazing enterprise grade apps using similar technologies to what I show you here. If you're looking for inspiration for modern web app development, be sure to check out their portfolio. To get started with this tutorial, you'll need to first sign up for a free Contentful account. And the first thing you'll do is create a space for your content. Spaces allow you to organize your concerns. For example, you might have one space for blog post and another space or product listings. In this example I'm going to create a lesson space that will mirror the content that you'll find on angularfirebase.com. The next step is to create a content type. So in this case, our content type is going to be a lesson. But you might also have content types for the author profile or a category listing or any other chunk of content that you can imagine. After you've created your content type, The next step is to add some fields to it. A field would be any property related to your actual content type. So in this case, we're going to set a title field. The beauty of this platform is that you can standardize and validate each field. Doing this from scratch would be a ton of extra work for a developer. The end result is a consistent blueprint for your content that you can handle differently on any platform. After you have your blueprint created, you can then use Contentful's text editor to Easily add new content. This is a powerful feature when you have team members who create content for your apps, but aren't actually programmers. So your content creators get this text editor and your programmers don't have to worry about building one from scratch. That sums up the basic process for building content with Contentful. Now let's switch over to Angular and actually use this in our progressive web app. I'm starting from a brand new Angular app, so run ng new and then cd into the app. And then the only dependencies are Contentful and a library called Marked, which we're going to use to convert markdown to raw HTML. Then to interact with the API, I'm going to create a service called Contentful and make sure to add that to the app module. From there, go back into Contentful and go to the API tab, then copy the space ID and the content delivery token. Then you'll add these to your environment TS file inside of Angular. Make sure that you're using the Content Delivery Token. You don't want to expose any API Token that has the right access to your Contentful API. From here, we're going to jump into the Service. And the first thing we'll do is import the Contentful SDK. And we also need the environment variables that we just configured as well as the RxJS observable class. So the first thing we need to do is initialize the SDK client. We do that by calling Contentful create client along with our space ID and our API token. The first thing I wanna do is console log out the content just so you know what the actual JavaScript object looks like. We can retrieve a single piece of content, which in this case is our lesson by calling client Get Entry with the entry ID. That's going to return a Promise which will resolve with the actual lesson content that we To use this method, I'm going to switch over to the App component, then I import the service and I set Up a variable here as an observable that will hold our lesson content here in the next step, then we can inject the service in the constructor. And during n g on init, we'll call the method that we just defined which will log the content in the browser console. Each piece of content is assigned a unique ID, so So I'm just copying and pasting that as the argument to our method. If we load the app, you see we get the content here logged in the console. It has 2 main properties, the fields property is all of our content. This is the actual data that we wanna show to the user in the front end. It corresponds exactly to the field types that you defined in Contentful. It also has a system property which has some additional metadata about the content. You may or may not wanna use this depending on your particular use case. Now that we know what the content looks like, let's convert it into an Observable so it's more Angular friendly. So I'm creating a get content method here which will first define the Promise in a variable. It's calling the same client get entry method with the content ID. Then we can convert it to an observable by calling observable from Promise, and then I'm going to map it down just to the fields. That's the content that we wanna show the end user. We don't really need that extra metadata. To make use of it, I'm switching back to the App component, Then I define the lesson variable by calling this method with the corresponding content ID. Now we can treat it like a regular Observable in the HTML. If If you're already familiar with Angular, this code should look very familiar to you. So first we'll unwrap the Observable by calling n g f and then use the async pipe And then we'll set it to a template variable called lesson. From there, it's extremely easy to just call the lesson properties directly on the object. So we'll display the lesson title, Then, uh, created at timestamp is a JavaScript date object, so we can use the Angular date pipe to display that in a user friendly way. The lesson tags are saved as an array in Contentful, so we can loop over those tags using n g 4. Then the only issue we're going to run into is when we display the lesson body, and I'll show you why here in just a second. Here's what we have so far in Angular. Our title and our tags look great, but if you look closely at the body, It's written in markdown format. It's just a raw string instead of the actual HTML that we wanna display to the user in the front end. When you write markdown, it looks like this, but Angular has no way of parsing this automatically. What we're going to do is create an Angular pipe called md to HTML, And it's going to take advantage of the Marked Library we installed earlier to parse the markdown to HTML. First, I'm going to go back into the service And we're going to import the Marked Library there. I'm defining this method in the service just to make it a little more flexible to work with. So it just takes a markdown string as an argument, And then it calls the marked library to convert it to HTML. Then we can import the Contentful service inside of our pipe And we'll inject that in the constructor just like we would in a component. Then all we have to do is take the input value and call the method we just created in the Service on that value. Then we can add the pipe to our lesson body, but it's still only gonna display a string. So at this point, we just have a string of HTML code. What we can do is bind this to the inner HTML property on a div. This will render it as actual HTML elements, which is what we want to display to the end user. But just a quick warning, you always wanna make sure that the source of the HTML comes from a trusted location. If users generate this Content, you wanna make sure to sanitize it to avoid being vulnerable to cross site scripting. You can read more about this in the official docs. If we go back into our Angular app, you can now see that our links and our headings are displaying like normal HTML. Just like that, we now have a powerful content management system to organize content in our progressive web app. But I did promise you one more thing and that's sending push notifications anytime new content is created in Contentful. I don't have time to show you push notifications end to end, but I do have multiple lessons covering that topic on angular firebase.com. What I am going to show you is how to set up webhooks in Contentful and then broadcast notifications using Firebase Cloud Messaging. Back in Angular, I have Firebase Cloud Functions initialized in my project. Then I'm going to write a function that uses the admin SDK. We're going to listen for webhooks from Contentful, And when we receive 1, we're going to parse it and then broadcast messages out to a certain topic. The webhook is going to send us data whenever a new lesson is published. All of the lesson details will be in the request body. So we can say request body fields and the topic we wanna send messages to is lessons. Then we can use this data to set the notification details. So we'll say new lesson posted and then we'll say angularfirebase.com posted a new lesson about whatever the lesson title is. And then we'll also add an icon to it. Then we can call the Firebase Messaging Library And just call send a topic with that notification payload. If you're lost at this point, make sure to check out some of my Firebase push notification videos. This is going to return a Promise. And if it's successful, then we can send a successful response back to the webhook. If the message notifications fail, we can send an error response back to Contentful telling it to retry the webhook if necessary. And it's really that simple. All we have to do is deploy the function, then we'll go back into Contentful and tell it when and where to send the webhook. After the function deploy succeeds, make sure to copy and paste the URL that Firebase gives back to you. Then back in Contentful, you'll go into the space settings And then to Webhooks and then we'll just give it a name of Topic Notifications then copy and paste the URL that Firebase gave you back for that Cloud Function. Then we only want to send this Webhook when new content is published. So we can do that by going down to only selected events And then click the box that intersects Entry and Publish. You can verify that the Webhook works by going back into the Content tab And then create a new piece of content. After that, you can go back to the webhook screen, and you should see a successful response from the Cloud Function. It will show you the webhook body that was sent by Contentful and then show you the response that was received from Firebase. That's it for Angular 5 with Contentful. If this video helped you, please like and subscribe. And if you want to learn more advanced features of progressive web apps, consider becoming a pro Subscriber@angularfirebase.com. You'll get a free copy of my book as well as 1 on 1 project support. Thanks for watching and I'll see you next time.
The speakers discuss the use of a platform called contentful for web app development, which allows for organized content creation and validation. They also explain how to sign up for a free content creation account and use it in a web app. The process involves creating a get content method, mapping it down to fields, and importing the content delivery token. The speakers also explain how to use the Marked Library and content management system in the web app, as well as setting up web reminded and push notifications. They also explain how to set up web chunking and send a message to a certain topic using the Azure cloud service.