Angular & Headless CMS
Tags: angular, javascript, webdev, tutorial
Published: 2019-07-09 21:51:20

---
title: Angular & Headless CMS
published: true
tags: angular,javascript,webdev,tutorial
canonical_url: https://medium.com/@erxk_verduin/angular-headless-cms-6a8c7c77af54
---

#### Build a Blog with Angular and Contentful

I have built a blog application using Angular and a headless CMS, Contentful. Contentful gives developers and non-developers alike the ability to manage content in a web application. I use Contentful to manage content on my website. — I am not sponsored by Contentful and any headless CMS could be substituted. See alternatives [1]

[Live Demo 🌌](http://blog-demo-5c8d8.web.app)

[Download the Source Code 🚀](https://github.com/Everduin94/angular-headless-cms)

![](https://cdn-images-1.medium.com/max/800/1*otCYYCOh2oqJBfhMEh20TA.gif)<figcaption>App Overview</figcaption>

### Summary

- What is a Headless CMS
- Contentful Basics
- Angular: Accessing & Displaying Content
- Hosting

### What is a Headless CMS

As I learned to build web applications, I heard about Content Management Systems (CMS); such as Wordpress or Drupal. I thought to myself, why would a developer use this if they already knew how to build a website? At the time, I did not understand the need or use-case.

Later, when I was ready to create my own side-projects and ship them to non-developers, I paused.

> How can someone, who is not a developer, update content on my web application?

I had already spent a significant amount of time developing my skill set building front-end applications. Would I now have to learn something like WordPress to build apps?

> **Headless CMS has entered the chat.**

Headless CMS, like Contentful, are essentially web applications that abstract away the database/backend from developers and non-developers alike.

A headless CMS does **not** provide a front-end. — They do provide developers with an API to get content from the back-end, and a user interface for non-developers to enter content into the back-end.

We will build an Angular application to display data and use Contentful to create/manage that data.

### Contentful Basics

We will cover the basics of Contentful. — For a comprehensive introduction see [here [2]](https://www.contentful.com/developers/docs/tutorials/).

![](https://cdn-images-1.medium.com/max/800/1*g1Z09E_629IfmUBmn7knKw.png)<figcaption>Contentful Overview</figcaption>

As an example, let’s set up a new Space with a Single Content Type in **five steps**.

![](https://cdn-images-1.medium.com/max/471/1*LYo_ucicO5L8lWmtlCDzVw.png)<figcaption>Top-Left Menu: Create Space</figcaption>

#### 1. Create a Space

Getting started is as simple as signing up. — Once signed up, we can create our own Space. As an analogy, we can think of a Space like our own individual database.

![](https://cdn-images-1.medium.com/max/659/1*5vB1AVPOwdrQAlec8Fyk_w.png)<figcaption>Create a Content Type</figcaption>

#### 2. Create a Content Type

We will add a Content Type to our Space. We can think of a Content Type like a table definition in a Database. — A Content Type is not the actual content, just the design.

![](https://cdn-images-1.medium.com/max/746/1*uSJXh9sjUtGySyiaDqnHXw.png)<figcaption>Add Fields to the Content Type</figcaption>

#### 3. Create Fields

Now we will add fields to our Content Type. Think of fields like columns in a database table. — In our example, we are creating a blog post, which will have fields such as title, description, body, etc…

![](https://cdn-images-1.medium.com/max/847/1*UgdiAOygoT977hy3RLw39w.png)<figcaption>Create new Content</figcaption>

#### 4. Create Content

Each piece of Content we add will be similar to a new row in a database. We will fill out each field we defined earlier in our blogPost Content Type.

![](https://cdn-images-1.medium.com/max/679/1*AuuH61fWsLUtdPSLJuMPpw.png)<figcaption>Space ID &amp; Content Delivery Acess Token</figcaption>

#### 5. Access the API

In the next section, we will use our Space ID and Content Delivery Access Token to retrieve our Contentful data and display it in our application.

### Angular: Accessing & Displaying Content

To get started with the Contentful API, we add the following object to our environment.ts file. We enter the information from **step 5** of Contentful Basics.

{% gist https://gist.github.com/Everduin94/debb2b0736bac7364a92c0e1eebc7c69 %}

#### 1. Display All Entries of a Content Type

Using cdaClient.getEntries(content\_type), we retrieve a promise containing all Content for a specific Content Type. The resolved data is an array of blog posts. Each entry has two properties, fields and sys.

Sys contains information such as created-date and ID. Fields are the fields we defined in step 3 of Contentful Basics.

{% gist https://gist.github.com/Everduin94/cb21e5d2b7d43a98dd89223f65831e00 %}

Leveraging the Angular Structural Directive, \*ngFor, we can dynamically add all blog posts to the DOM. — When we add a new blog post to Contentful, our post will be automatically added by our Contentful Service.

Using Angular Template Syntax, we can build list items displaying info from our Contentful Service such as createdAt, ID, title, description, etc…

{% gist https://gist.github.com/Everduin94/c3fcb350f3e1a492749722e5eec5e5d0 %}

#### 2. Display a specific Entry of a Content Type

Using cdaClient.getEntry(id), we can query a specific entry from our Contentful data. The resolved data is a single blog post with the sys and fields properties.

{% gist https://gist.github.com/Everduin94/8821a48ff7eedf883e46e402c947a77d %}

When a user clicks one of the containers from the first section, the router navigates to a dynamic route /posts/:id. In snippet 1.2, we passed the ID as a parameter via routerLink.— We can retrieve the ID from Angular’s ActivatedRoute paramMap.

{% gist https://gist.github.com/Everduin94/45e41677bec1b0653155fda7a1a08509 %}

{% gist https://gist.github.com/Everduin94/9e51dba72b2887cc6b7d182732da520a %}

Contentful provides a Markdown editor for all text fields. We will leverage this by converting the Markdown to HTML and setting the inner HTML on a div. [[4]](https://fireship.io/)

Use innerHTML judiciously, If we do not have full control over what is being entered into the innerHTML we need to sanitize the input to [prevent xss-attacks [5]](https://angular.io/api/platform-browser/DomSanitizer).

{% gist https://gist.github.com/Everduin94/2cdc9f46a01b4b351fe3ca5c067cd229 %}

Using Angular’s Structural Directive, \*ngIf, we can optionally display a field if it exists. In our example, we will display a link to an original publication if present.

#### 3. Add a New Contentful Entry

After publishing a new Contentful Entry, our application is immediately updated on refresh with the latest Content. — No changes are needed to our Angular project.

![](https://cdn-images-1.medium.com/max/780/1*gYznuJU-g3YzE5MOYk0M_w.gif)<figcaption>Final Product</figcaption>

### Hosting

The live demo is hosted with Firebase. For directions on hosting a project with Firebase see [here [6]](https://www.youtube.com/watch?v=aICeVhu2mAE). For alternative forms of hosting see here [7].

> I am not affiliated with or sponsored by Firebase or any of the alternatives.

### Resources & References

[1] [Sanity](https://www.sanity.io/) | [FlameLink](https://flamelink.io/?gclid=CjwKCAjwsIbpBRBNEiwAZF8-z2vWGi3LO1o6EqAg8Mh9njo35Y5F5l464KcCz7yK0-hPjtg9GuLcKxoC7jgQAvD_BwE) | [Headless Wordpress](https://www.sitepoint.com/wordpress-headless-cms/)

[2] [Contentful-Tutorial](https://www.contentful.com/developers/docs/tutorials/)

[3] [Structural-Directives](https://angular.io/guide/structural-directives)

[4] Learned the Markdown-to-HTML Technique on [fireship](https://fireship.io/)

[5] [DOM Sanitizer](https://angular.io/api/platform-browser/DomSanitizer)

[6] [Host with Firebase](https://www.youtube.com/watch?v=aICeVhu2mAE)

[7] [Netlify](https://www.netlify.com/) | [AWS](https://aws.amazon.com/) | [Digital Ocean](https://www.digitalocean.com/)