> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://contentful.com/developers/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful.com/developers/docs/_mcp/server.

# Create an Angular project with Contentful

> This tutorial will show you how to create an Angular app project from scratch and use data that is stored in Contentful | Getting started with Angular

After its big rewrite [Angular](https://angular.io/) is one of the big players in single page application development. It's built to scale and enables web developers to build large applications following conventions with speed. Very often single page applications are more than just business logic and you'll need a way to manage content and allow editors to make changes without touching code.

This guide will show you how to set up your first Angular app from scratch and use data that is stored in Contentful. In case you're new to Angular you might want to consider doing the [getting started tutorial](https://angular.io/guide/quickstart) first.

## Create a new Angular app

It doesn't matter which JavaScript framework you prefer, most of them come with a CLI tool nowadays. These CLI tools help you get started and scaffolding new apps. For the case of the Angular project, it's [Angular CLI](https://github.com/angular/angular-cli) which you can easily install via the new command line.

```
npm install -g @angular/cli
```

Now you'll have the `ng` command available in your terminal and you're ready to create a new Angular application. So let's jump right in and initialize a new project to make it ready for development.

```
ng new contentful-product-catalog-angular
cd contentful-product-catalog-angular
```

If you now run `npm start` a development server will be started and you'll see that your Angular application is ready to fetch some content.

## Have a look at the content model first

As the project name already reveals, the result of this project will be an app that deals with product catalog data.

When getting starting with Contentful, the web app enables you to get started quickly. This is done by providing example content models to give you an idea of what the best way to deal with structured data is. This tutorial is based on the example data set "product catalog".

You can either set up a new space now and initialize it with the catalog example data, or for the sake of simplicity just use a public Contentful space we provide for demo use cases. The credentials and configuration for the public space are provided in this tutorial.

> **Info**
>
> Creation of a space may result in additional charges if the free spaces available in your [plan](https://www.contentful.com/pricing/) are exhausted.

### Catalog data overview

The product catalog content model consists of three content types: a product, a category, and a brand. Product content entries can have relations to one or more categories and to one brand. Structuring the content model this way makes it easier to reuse entries.

If the concept of content modeling is new to you it's recommended to read [the Contentful modeling basics](https://www.contentful.com/r/knowledgebase/content-modelling-basics/) and [the concept of the Contentful data model](/concepts/data-model) first.

## Create a Contentful service

To start fetching data from Contentful, start by creating an Angular service via the CLI. The `g` is shorthand for the `generate` command.

```
ng g service contentful

installing service
  create src/app/contentful.service.spec.ts
  create src/app/contentful.service.ts
  WARNING Service is generated but not provided, it must be provided to be used
```

This creates a new `contentful.service.ts` file.

```javascript
// ./src/app/contentful.service.ts
import { Injectable } from '@angular/core';

@Injectable()
export class ContentfulService {
  constructor() {}
}
```

To make your first requests use [the Contentful JavaScript client library](https://github.com/contentful/contentful.js) and add it as a dependency to your project.

```
npm i --save contentful
```

You can then use the client library in the service file you just created. Import the `createClient` method of the `contentful` dependency and you're ready to go.

Additionally, you can import `Entry` which can come in handy when being in a TypeScript environment to give additional type information. The `Entry` property is defined in the `index.d.ts` file [of the project](https://github.com/contentful/contentful.js/blob/master/index.d.ts).

```javascript
import { createClient, Entry } from 'contentful';
```

The next step is to set up a config object which holds the needed information to retrieve data from the Contentful API. To use the Contentful API you need to define the id and access token of the space you want to fetch data from.

The ID of the product content type is included in the configuration files object. As you're dealing with three different content types (`product`, `category`, `brand`) this is needed to fetch particular entries like e.g. all of all products later on.

```javascript
const CONFIG = {
  space: 'wl1z0pal05vy',
  accessToken:
    '0e3ec801b5af550c8a1257e8623b1c77ac9b3d8fcfc1b2b7494e3cb77878f92a',

  contentTypeIds: {
    product: '2PqfXUJwE8qSYKuM0U6w8M',
  },
};
```

If you're following this tutorial you don't have to change anything right now as it uses the publicly available example space but if you want to play around with your own space follow [the Authentication section](/references/authentication) to get your own space id and Content Delivery API access token.

Now it's time to fetch data!

To do so define the Contentful client in your service class and add a new method called `getProducts`. This method will fetch the data using the `getEntries` method of the client library client. You can set the `content_type` property inside of the query object with the product content type id to only retrieve products.

```javascript
@Injectable()
export class ContentfulService {
  private cdaClient = createClient({
    space: CONFIG.space,
    accessToken: CONFIG.accessToken
  });

  constructor() { }

  getProducts(query?: object): Promise<Entry<any>[]> {
    return this.cdaClient.getEntries(Object.assign({
      content_type: CONFIG.contentTypeIds.product
    }, query))
    .then(res => res.items);
  }
}
```

`getEntries` returns a promise which will be resolved with meta information like the total number of fetched entries but also an Array of `items` which includes the actual products you're interested in.

The ready to use service file then looks like:

```javascript
// ./src/app/contentful.service.ts
import { Injectable } from '@angular/core';
// import Contentful createClient and type for `Entry`
import { createClient, Entry } from 'contentful';

// configure the service with tokens and content type ids
// SET YOU OWN CONFIG here
const CONFIG = {
  space: 'wl1z0pal05vy',
  accessToken: '0e3ec801b5af550c8a1257e8623b1c77ac9b3d8fcfc1b2b7494e3cb77878f92a',

  contentTypeIds: {
    product: '2PqfXUJwE8qSYKuM0U6w8M'
  }
}

@Injectable()
export class ContentfulService {
  private cdaClient = createClient({
    space: CONFIG.space,
    accessToken: CONFIG.accessToken
  });

  constructor() { }

  getProducts(query?: object): Promise<Entry<any>[]> {
    return this.cdaClient.getEntries(Object.assign({
      content_type: CONFIG.contentTypeIds.product
    }, query))
    .then(res => res.items);
  }
}
```

Afterward, add the service provider to the `AppModule` so that it is available in the component you'll set up in a minute.

```javascript
// ./src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
// import the new service
import { ContentfulService } from './contentful.service';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  exports: [],
  // make the provide available in the application
  providers: [ContentfulService],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

## Add new routes

Now that you have the service ready it's time to define a route in the app folder that shows the products that are stored in Contentful. A single page application usually includes several routes and not every route will use the data coming from Contentful.

To have a clear encapsulation define a separate route which's only purpose is to show the products. At this stage this is only the beginning of your application so you have to define a redirect from the app-root to `/products` so that the initial root HTTP call is handled.

```javascript
// ./src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ContentfulService } from './contentful.service';
// import the router modules and the types for routes
import { RouterModule, Routes } from '@angular/router';

// define the available routes
const routes: Routes = [
  { path: '', redirectTo: '/products', pathMatch: 'full' },
  { path: 'products', component: ProductListComponent },
];

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    // import the new routes
    RouterModule.forRoot(routes),
  ],
  providers: [ContentfulService],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

## Create a product list page component to display Contentful entries

As you saw in the routing configuration, the routing for `products` uses a `ProductListComponent`. So let's create Angular routing for this one. And again the CLI tool has the following command available for this use case.

```
ng g component product-list
```

This command will create a bunch of new files in `./src/app/product-list`. These files cover styling, templating and unit testing.

To use this new component it has to be registered in `app.module.ts` and has to be included in the `declarations` property of the module.

```javascript
// ./src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent } from './app.component';
import { ContentfulService } from './contentful.service';
// import new component
import { ProductListComponent } from './product-list/product-list.component';

const routes: Routes = [
  { path: '', redirectTo: '/products', pathMatch: 'full' },
  // define new component for '/products' route
  { path: 'products', component: ProductListComponent },
];

@NgModule({
  declarations: [
    AppComponent,
    // add product component
    ProductListComponent,
  ],
  imports: [BrowserModule, RouterModule.forRoot(routes)],
  exports: [],
  providers: [ContentfulService],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

Now you can adjust `product-list.component.ts` to make use of the Contentful service you created. To add it to your component you can use [Angular's dependency injection](https://angular.io/guide/dependency-injection) and simply add the service to the `constructor` of the component.

```javascript
constructor(private contentfulService: ContentfulService) { }
```

You should also define [a private class property](https://www.typescriptlang.org/docs/handbook/classes.html#public-private-and-protected-modifiers) to the class which defines that this component will include a collection of several products.

```javascript
private products: Entry<any>[] = [];
```

And then it's already time to get the data and fetch it in the initialization hook which is provided by Angular components.

```javascript
import { Component, OnInit } from '@angular/core';

ngOnInit() {
  this.contentfulService.getProducts()
  .then(products => this.products = products)
}
```

The final component file should look like this then.

```javascript
// ./src/app/product-list/product-list.component.ts
import { Component, OnInit } from '@angular/core';
import { ContentfulService } from '../contentful.service';
import { Entry } from 'contentful';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
  // define private class properties
  private products: Entry<any>[] = [];

  constructor(private contentfulService: ContentfulService) { }

  // fetch data on init
  ngOnInit() {
    this.contentfulService.getProducts()
    .then(products => this.products = products)
  }
}
```

To prove that it's working you can adjust the template for the product list component and display the name of each product in a list.

```html
<!-- ./app/product-list/product-list.component.html-->
<ul class="u-listReset">
  <li *ngFor="let product of products">&#123;&#123; product.fields.productName &#125;&#125;</li>
</ul>
```

### Sum up

What you achieved now is that you've got one route that renders data coming from Contentful. This way editors and content creators can work in a comfortable authoring environment and you can deal with handy JSON data without worrying about content changes that need your attention.

## More routes, more methods, and more functionality

This tutorial only showed the basic functionality of Contentful. If you're interested in more API calls and more components we also created [a more advanced example GitHub project folder](https://github.com/contentful-labs/product-catalogue-web.ts) which includes routes to display product detail information and particular product categories. Have fun!

### Additional resources

If Angular is not your thing we also provide several example apps that are based on the same data set:

* [Product catalog for iOS](https://github.com/contentful/product-catalogue-ios)
* [Product catalog for Android](https://github.com/contentful/product-catalogue-android)

## Next steps

* [Using the Contentful Delivery API in a JavaScript app](/sdks/javascript/tutorials/using-js-cda-sdk/)
* [The concept of the Contentful data model](/concepts/data-model/)