# Contentstack for Developers

### About this export

| Field | Value |
| --- | --- |
| **content_type** | course |
| **platform** | contentstack-academy |
| **source_url** | https://www.contentstack.com/academy/courses/contentstack-for-developers |
| **language** | en |
| **product_area** | contentstack |
| **learning_path** | contentstack-developer-certification |
| **course_id** | contentstack-for-developers |
| **slug** | contentstack-for-developers |
| **version** | 2026-03-01 |
| **last_updated** | 2026-05-04 |
| **status** | published |
| **keywords** | ["contentstack","cms","composable","headless cms","learn contentstack"] |
| **summary_one_line** | The Contentstack Developer Onboarding Course is designed to equip learners with comprehensive knowledge on various aspects of the platform, including its architecture, APIs, SDKs, and the process of creating a NextJS web… |
| **total_duration_minutes** | 132 |
| **lessons_count** | 29 |
| **video_lessons_count** | 5 |
| **text_lessons_count** | 24 |
| **linked_learning_path** | contentstack-developer-certification |
| **linked_assessment_ref** | LMS_UNCONFIGURED_COURSE_ASSESSMENT |
| **markdown_file_url** | /academy/md/courses/contentstack-for-developers.md |
| **generated_at** | 2026-05-04T05:36:50.592Z |
| **intended_audience** | [] |
| **prerequisites** | [] |
| **related_courses** | [] |

> **Academy MD v3** — companion `.md` for Ask AI. Quizzes and graded assessments are **LMS-only**; this file never contains answer keys.

## Course Overview

| Metadata | Value |
| --- | --- |
| Catalog duration | 2h 11m 51s |
| Released (if known) | 2026-03-01 |
| Product area | contentstack |

### Description

The Contentstack Developer Onboarding Course is designed to equip learners with comprehensive knowledge on various aspects of the platform, including its architecture, APIs, SDKs, and the process of creating a NextJS web application.   
[Download Playground Here](https://github.com/contentstack/contentstack-academy-playground)

You can also install a training instance by visiting our Legacy Academy. Click the [Create Training Instance](https://www.contentstack.com/academy/training-instance) button on the home page.

Throughout the course, learners will receive detailed instruction on how to utilize Contentstack's features to build robust and scalable web applications. They will gain a deep understanding of the platform's architecture, enabling them to develop applications that take full advantage of Contentstack's capabilities. 

Additionally, the course will provide learners with hands-on experience using Contentstack's APIs and SDKs, enabling them to develop efficient and effective web applications. By the end of the course, learners will be equipped with the skills and knowledge necessary to create high-quality web applications using Contentstack.

### Overview

### Topics Covered

Management and Images  
Content Delivery API  
Using the Images API  
Creating the Hero Detail Page  
Creating the Hero Gallery Page  
Design Patterns with Content Types  
Deploying the Starter App with Contentstack Launch  
Importing Content with the CLI and CMA  
Working with Roles and Permissions  
Workflow  
Webhooks  
Automate - Using an HTTP Connector to Send Data to a 3rd Party System  
What is the Contentstack Apps Marketplace?  
Using Marketplace Apps  
Installing the NextJS Starter App with the CLI  
Helpful Developer Resources

#### Objectives

Objectives for the Contentstack Developer Onboarding Course:

1\. Understand the basic concepts and terminology related to Contentstack and its platform.  
2\. Gain a deep understanding of the architecture  of Contentstack.  
3\. Learn how to utilize Contentstack's APIs and SDKs to develop web applications.  
4\. Understand the benefits of using Contentstack for web development projects.  
5\. Learn how to create a NextJS web application using Contentstack.  
6\. Learn how to manage and configure content types within Contentstack.  
7\. Develop a working knowledge of best practices for web development using Contentstack.

### Learning objectives

1. Follow each lesson in order.
2. Practice in a training stack using placeholders **YOUR_STACK_API_KEY** and **YOUR_DELIVERY_TOKEN** in local `.env` files only.
3. Validate API responses against the official documentation.

### Topics covered

contentstack; cms; composable; headless cms; learn contentstack

## Course structure

```text
contentstack-for-developers/
├── 01-what-we-ll-build · text · 3 min
├── 02-getting-started · video · 224s
├── 03-big-picture-architecture · text · 1 min
├── 04-architecture-walkthrough · video · 173s
├── 05-environments-walkthrough · video · 185s
├── 06-using-the-content-delivery-api · text · 2 min
├── 07-using-the-content-delivery-api-documentation · text · 3 min
├── 08-querying-the-content-delivery-api-with-the-documentation · video · 135s
├── 09-using-the-postman-collection-to-connect-with-the-content-delivery-api · text · 1 min
├── 10-using-postman-to-query-the-contentstack-content-delivery-api-walkthrough · video · 204s
├── 11-using-the-javascript-content-delivery-sdk · text · 1 min
├── 12-using-the-graphql-api-with-postman · text · 1 min
├── 13-cdn-and-caching · text · 1 min
├── 14-query-examples-with-the-content-delivery-api · text · 1 min
├── 15-using-the-images-api · text · 1 min
├── 16-creating-the-hero-detail-page · text · 1 min
├── 17-creating-the-hero-gallery-page · text · 1 min
├── 18-design-patterns-with-content-types · text · 1 min
├── 19-deploying-the-starter-app-with-contentstack-launch · text · 1 min
├── 20-importing-content-with-the-cli-and-cma · text · 1 min
├── 21-working-with-roles-and-permissions · text · 1 min
├── 22-workflow · text · 1 min
├── 23-webhooks · text · 1 min
├── 24-automate--using-an-http-connector-to-send-data-to-a-3rd-party-system · text · 1 min
├── 25-what-is-contentstack-marketplace- · text · 1 min
├── 26-using-marketplace-apps · text · 1 min
├── 27-installing-the-nextjs-starter-app-with-the-cli · text · 1 min
├── 28-helpful-resources · text · 1 min
├── 29-quiz · quiz (LMS only) · 3 min
```

## Lessons

### Lesson 01 — What We'll Build

<!-- ai_metadata: {"lesson_id":"01","type":"text","duration_minutes":3,"topics":["What","Build"]} -->

#### Lesson text

## Developer Onboarding Course - Introduction

Welcome to our exciting new course on developing web applications with Contentstack! If you're looking to build powerful, scalable, and customizable web applications, then you're in the right place. In this course, we'll guide you through the fundamentals of Contentstack, including content modeling, API and SDK usage, and more. We'll also cover advanced topics such as extending a NextJS app, enabling localization, and optimizing your content delivery. With our easy-to-follow tutorials and hands-on exercises, you'll quickly gain the skills and knowledge needed to build stunning web applications that meet the needs of your clients and users. So, whether you're a seasoned developer or just starting out, join us on this exciting journey and take your web development skills to the next level with Contentstack!

The main tasks in the course are:

1.  Create a new detail page (new content type, new NextJS Component, new CD API query)
2.  Create a new gallery landing page (new content type, new NextJS Component, more complicated CD API Queries)

**We also cover the following:**

*   Starter app overview, install, and walk through
*   Using CMA to read and import content
*   SDKs/APIs overview and introduction
*   SDKs/APIs deep dive with patterns/practices
*   Roles and Permissions
*   Workflow
*   Marketplace intro
*   Automation hub intro

## What we will be building

### Composable Hero Gallery Page:

![composable-heros.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltd51a0c5b982c72f8/664c027a1983ea9d6dac29b4/composable-heros.png)

### Composable Hero Detail Page:

![composable-heros-detail.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltcba8639d82e39f82/664c02a3785339639e9e3d9f/composable-heros-detail.png)

## Getting Started

1.  **Create a new Training Instance** - Go to [https://www.contentstack.com/academy/training-instance](https://www.contentstack.com/academy/training-instance) and select **Create a Training Instance**.
2.  **Download the course code from Github** - ([https://github.com/contentstack/contentstack-academy-playground](https://github.com/contentstack/contentstack-academy-playground)).
3.  **Rename the .env.local.sample file** to .env.local and update the following configuration properties:  
    ![rename-sample.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltb3b6b76e3ee547ed/664c033cc9024cafa4ad58b4/rename-sample.png)
4.  **Build the project** with 'npm i'.
5.  **Run the website** with 'npm run dev'.

#### Key takeaways

- Connect **What We'll Build** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 02 — Getting Started

<!-- ai_metadata: {"lesson_id":"02","type":"video","duration_seconds":224,"video_url":"https://cdn.jwplayer.com/previews/HoLoBca0","thumbnail_url":"https://cdn.jwplayer.com/v2/media/HoLoBca0/poster.jpg?width=720","topics":["Getting","Started"]} -->

#### Video details

#### At a glance

- **Title:** Dev-getting Started With The Contentstack Academy Website
- **Duration:** 3m 44s
- **Media link:** https://cdn.jwplayer.com/previews/HoLoBca0
- **Publish date (unix):** 1716254996

#### Streaming renditions

- application/vnd.apple.mpegurl
- audio/mp4 · AAC Audio · 113744 kbps
- video/mp4 · 180p · 200p · 152758 kbps
- video/mp4 · 270p · 300p · 180832 kbps
- video/mp4 · 360p · 400p · 207568 kbps
- video/mp4 · 406p · 450p · 223975 kbps
- video/mp4 · 540p · 600p · 281504 kbps
- video/mp4 · 720p · 800p · 365707 kbps

#### Timed text tracks (delivery)

- **thumbnails:** `https://cdn.jwplayer.com/strips/HoLoBca0-120.vtt`

#### Video transcript

```transcript
<!-- PLACEHOLDER: replace with real transcript before publish -->
[00:00] Transcript not attached in source entry.
```

#### Key takeaways

- Connect **Getting Started** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 03 — Big Picture Architecture

<!-- ai_metadata: {"lesson_id":"03","type":"text","duration_minutes":1,"topics":["Big","Picture","Architecture"]} -->

#### Lesson text

# **Architecture**

## **Big Picture Architecture Diagram**

### **Backend**

The Backend of Contentstack is the CMS with the ability to create and publish content.  **The focus here is on editor ease-of-use by providing a simple, powerful and flexible UI for content creation and management.**  In addition to the out of the box functionality, we also provide an ability to extend the interface by creating UI Extensions using our App SDK and connect to 3rd-party applications such as DAM providers, Analytics, E-Commerce platforms and more.

### **Frontend**

The focus on the frontend is high-performance for your website and web application. APIs and SDKs are provided to the developer for using in their applications to perform read-only queries to the content.  The Content Delivery APIs use an internal CDN to cache all queries to the platform which results in higher performance for all your web applications.  This is also where we find the Images API for delivering image assets.

![Architecture.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt40df19fbdfa691c4/664c7d55a671fa7891f218bf/Architecture.png)

## **Environments**

*   One Stack can publish to multiple Environments.  Think of Environments as “publish destinations”.
    
*   Each Environment has one Delivery Token, otherwise known as an Access Token.  That token is unique per Environment.
    
*   Each Stack has an API key.  There is only 1 API key per Stack and it is unique.
    
*   Most API calls will require both an API token and a Delivery / Access Token.
    

![environment.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta9f0e57d8a3c5a6e/664c7d9f79abee8ebd3d1534/environment.png)**Multi-Stack Architecture Diagram**

![multi-stack.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltd1dd48a1fcbec491/664c7de28a66292552b1397b/multi-stack.png)

#### Key takeaways

- Connect **Big Picture Architecture** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 04 — Architecture Walkthrough

<!-- ai_metadata: {"lesson_id":"04","type":"video","duration_seconds":173,"video_url":"https://cdn.jwplayer.com/previews/gu1hi4sL","thumbnail_url":"https://cdn.jwplayer.com/v2/media/gu1hi4sL/poster.jpg?width=720","topics":["Architecture","Walkthrough"]} -->

#### Video details

#### At a glance

- **Title:** Dev-big Picture Architecture
- **Duration:** 2m 53s
- **Media link:** https://cdn.jwplayer.com/previews/gu1hi4sL
- **Publish date (unix):** 1716254996

#### Streaming renditions

- application/vnd.apple.mpegurl
- audio/mp4 · AAC Audio · 114030 kbps
- video/mp4 · 180p · 200p · 137534 kbps
- video/mp4 · 270p · 300p · 148470 kbps
- video/mp4 · 360p · 400p · 162344 kbps
- video/mp4 · 406p · 450p · 169505 kbps
- video/mp4 · 540p · 600p · 193874 kbps

#### Timed text tracks (delivery)

- **thumbnails:** `https://cdn.jwplayer.com/strips/gu1hi4sL-120.vtt`

#### Video transcript

```transcript
<!-- PLACEHOLDER: replace with real transcript before publish -->
[00:00] Transcript not attached in source entry.
```

#### Key takeaways

- Connect **Architecture Walkthrough** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 05 — Environments Walkthrough

<!-- ai_metadata: {"lesson_id":"05","type":"video","duration_seconds":185,"video_url":"https://cdn.jwplayer.com/previews/xDslMX1l","thumbnail_url":"https://cdn.jwplayer.com/v2/media/xDslMX1l/poster.jpg?width=720","topics":["Environments","Walkthrough"]} -->

#### Video details

#### At a glance

- **Title:** Dev-environments
- **Duration:** 3m 5s
- **Media link:** https://cdn.jwplayer.com/previews/xDslMX1l
- **Publish date (unix):** 1716254996

#### Streaming renditions

- application/vnd.apple.mpegurl
- audio/mp4 · AAC Audio · 113540 kbps
- video/mp4 · 180p · 200p · 139607 kbps
- video/mp4 · 270p · 300p · 154759 kbps
- video/mp4 · 360p · 400p · 171856 kbps
- video/mp4 · 406p · 450p · 182649 kbps
- video/mp4 · 540p · 600p · 214541 kbps

#### Timed text tracks (delivery)

- **thumbnails:** `https://cdn.jwplayer.com/strips/xDslMX1l-120.vtt`

#### Video transcript

```transcript
<!-- PLACEHOLDER: replace with real transcript before publish -->
[00:00] Transcript not attached in source entry.
```

#### Key takeaways

- Connect **Environments Walkthrough** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 06 — Using the Content Delivery API

<!-- ai_metadata: {"lesson_id":"06","type":"text","duration_minutes":2,"topics":["Using","the","Content","Delivery","API"]} -->

#### Lesson text

In this module, we'll dive into the world of Contentstack's powerful APIs that can help you build your digital experiences faster, easier, and better. Our APIs are designed to help developers access content and make updates programatically.

First, we'll start with Contentstack's Content Delivery API. This API allows developers to retrieve content from Contentstack's headless CMS and deliver it to any digital platform or device. You'll learn how to use our API to retrieve content in a structured and organized manner, so you can easily integrate it into your website, app, or any other digital platform.

Next, we'll explore Contentstack's Content Management API. This API enables developers to create, update, and manage content in Contentstack's headless CMS programmatically. You'll learn how to leverage our API to automate content creation, content management workflows, and enable seamless collaboration between developers and content editors, and increase the efficiency of your content creation processes.

Finally, we'll dive into Contentstack's Images API. This API allows you to transform and optimize images on-the-fly, so you can deliver the best possible visual experience to your users. You'll learn how to use our API to resize, compress, and optimize images.

By the end of this module, you'll have a deep understanding of Contentstack's powerful APIs and how to leverage them to build faster, better, and more engaging digital experiences. So, let's get started!

# Using the Content Delivery API

Contentstack's Content Delivery API is a powerful tool that enables developers to retrieve content from Contentstack's headless CMS and deliver it to any digital platform or device. It allows you to fetch content in a structured and organized manner, which makes it easier to integrate into your website, app, or any other digital platform.

The Content Delivery API is built on top of a powerful caching layer, which ensures lightning-fast performance even when you're dealing with large amounts of content. This caching layer also ensures that your content is always up-to-date and in sync with the latest updates made to the CMS.

One of the biggest advantages of using Contentstack's Content Delivery API is that it's completely agnostic to the technology stack you're using. Whether you're building your website using a traditional CMS or a modern front-end framework like React or Vue.js, the Content Delivery API can be seamlessly integrated into your workflow.

With the Content Delivery API, you can also retrieve content in multiple languages, which is essential for building global websites and apps. The API also allows you to fetch only the content you need, which reduces the amount of data transfer and improves the overall performance of your application.

[Content Delivery API Documentation](https://www.contentstack.com/docs/developers/apis/content-delivery-api/)

![API-map.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbeecb6f7ab8cf28a/664d437c785339c0e89e4f8e/API-map.png)

#### Key takeaways

- Connect **Using the Content Delivery API** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 07 — Using the Content Delivery API documentation

<!-- ai_metadata: {"lesson_id":"07","type":"text","duration_minutes":3,"topics":["Using","the","Content","Delivery","API","documentation"]} -->

#### Lesson text

Here's how you can start using our Content Delivery API documentation:

1.  Go to the [Get Entries](https://www.contentstack.com/docs/developers/apis/content-delivery-api/#get-all-entries) section of the Content Delivery Documentation.
    
2.  Click on the "Get all Entries" link to open the query window on the right.
    
3.  Update the parameters to use the following:
    
    *   content\_type\_uid: blog\_post
    *   environment: preview (or development; associated with the token that you'll be using)
    *   locale: en-us
    *   api\_key: (found in the settings / tokens / content delivery token settings page)
    *   access\_token: (found in the settings / tokens / content delivery token settings page)
    
    If you have questions, see the [CDA Postman guide](https://www.contentstack.com/docs/developers/apis/content-delivery-api/#postman-collection) for more details.
    
4.  Execute the request with the "Try" button.
    

Congrats! You just queried the Contentstack Content Delivery API!

#### Key takeaways

- Connect **Using the Content Delivery API documentation** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 08 — Querying the Content Delivery API with the Documentation Walkthrough

<!-- ai_metadata: {"lesson_id":"08","type":"video","duration_seconds":135,"video_url":"https://cdn.jwplayer.com/previews/HTAyw81A","thumbnail_url":"https://cdn.jwplayer.com/v2/media/HTAyw81A/poster.jpg?width=720","topics":["Querying","the","Content","Delivery","API","with"]} -->

#### Video details

#### At a glance

- **Title:** Dev-querying The Content Delivery Api With The Documentation Portal
- **Duration:** 2m 15s
- **Media link:** https://cdn.jwplayer.com/previews/HTAyw81A
- **Publish date (unix):** 1716254996

#### Streaming renditions

- application/vnd.apple.mpegurl
- audio/mp4 · AAC Audio · 113654 kbps
- video/mp4 · 180p · 200p · 152524 kbps
- video/mp4 · 270p · 300p · 182241 kbps
- video/mp4 · 360p · 400p · 212769 kbps
- video/mp4 · 406p · 450p · 233492 kbps
- video/mp4 · 540p · 600p · 296061 kbps

#### Timed text tracks (delivery)

- **thumbnails:** `https://cdn.jwplayer.com/strips/HTAyw81A-120.vtt`

#### Video transcript

```transcript
<!-- PLACEHOLDER: replace with real transcript before publish -->
[00:00] Transcript not attached in source entry.
```

#### Key takeaways

- Connect **Querying the Content Delivery API with the Documentation Walkthrough** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 09 — Using the Postman collection to connect with the Content Delivery API

<!-- ai_metadata: {"lesson_id":"09","type":"text","duration_minutes":1,"topics":["Using","the","Postman","collection","connect","with"]} -->

#### Lesson text

### **Using the Postman collection to connect with the Content Delivery API**

1.  [Download and install Postman](https://www.postman.com/downloads/)
    
2.  [Download the Contentstack Postman Content Delivery collection](https://www.contentstack.com/docs/developers/apis/postman-collections)
    
3.  To obtain the Content Delivery Token, follow these steps in Contentstack: navigate to the "Settings" page, select "Tokens," then choose "Content Delivery." If you haven't created a Delivery Token yet, [create a new Delivery Token](https://www.contentstack.com/docs/developers/create-tokens/create-a-delivery-token/). [Additional information about tokens, including Delivery Tokens, can be found in our documentation](https://www.contentstack.com/docs/developers/create-tokens/#work-with-delivery-tokens) 
    
4.  Open Postman and select the 'Content Delivery API - Contentstack' collection.  Entries, Get all entries
    
5.  Edit the Postman variables and update the values for api\_key and access\_token.  The api\_key is found on the Delivery Token settings page.  The access\_token is the Delivery Token.  These are used in the Headers of the request.  
    Also, add the value of the content\_type\_uid as 'blog\_post', environment as 'preview' and locale as 'en-us'.
    
6.  Send the request.  Contentstack replies with the JSON of all blog\_post entries.

#### Key takeaways

- Connect **Using the Postman collection to connect with the Content Delivery API** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 10 — Using Postman to query the Contentstack Content Delivery API Walkthrough

<!-- ai_metadata: {"lesson_id":"10","type":"video","duration_seconds":204,"video_url":"https://cdn.jwplayer.com/previews/693igszM","thumbnail_url":"https://cdn.jwplayer.com/v2/media/693igszM/poster.jpg?width=720","topics":["Using","Postman","query","the","Contentstack","Content"]} -->

#### Video details

#### At a glance

- **Title:** Dev-using Postman With The Content Delivery Api
- **Duration:** 3m 24s
- **Media link:** https://cdn.jwplayer.com/previews/693igszM
- **Publish date (unix):** 1716254996

#### Streaming renditions

- application/vnd.apple.mpegurl
- audio/mp4 · AAC Audio · 113656 kbps
- video/mp4 · 180p · 200p · 146207 kbps
- video/mp4 · 270p · 300p · 168735 kbps
- video/mp4 · 360p · 400p · 192772 kbps
- video/mp4 · 406p · 450p · 206599 kbps
- video/mp4 · 540p · 600p · 255637 kbps

#### Timed text tracks (delivery)

- **thumbnails:** `https://cdn.jwplayer.com/strips/693igszM-120.vtt`

#### Video transcript

```transcript
<!-- PLACEHOLDER: replace with real transcript before publish -->
[00:00] Transcript not attached in source entry.
```

#### Key takeaways

- Connect **Using Postman to query the Contentstack Content Delivery API Walkthrough** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 11 — Using the JavaScript Content Delivery SDK

<!-- ai_metadata: {"lesson_id":"11","type":"text","duration_minutes":1,"topics":["Using","the","JavaScript","Content","Delivery","SDK"]} -->

#### Lesson text

## **Getting Started using the JavaScript Content Delivery SDK**

To get started with the Content Delivery SDK and **NodeJS**, the first thing you need to do is to install it. You can do this by running the following command in your project directory:

npm install contentstack  

## **Helpful Javascript Resources**

[Javascript SDK on Github](https://github.com/contentstack/contentstack-javascript) 

[Javascript API Reference](https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/javascript-browser/reference/)

  
**Include the JS SDK in your projects**

https://cdn.jsdelivr.net/npm/contentstack@latest/dist/web/contentstack.min.js  

Once you have installed the SDK, you need to initialize it with your API key, delivery token, and environment name. Here's an example of how to do this:

const Contentstack = require('contentstack');  
const Stack = Contentstack.Stack({  
  api\_key: 'your\_api\_key',  
  delivery\_token: 'your\_delivery\_token',  
  environment: 'your\_environment'  
});  

With the SDK initialized, you can start retrieving content from Contentstack's API. The SDK provides several methods for fetching content, depending on your requirements.

If you want to retrieve a single entry, you can use the Entry method, as shown in the following example:

Stack.ContentType('your\_content\_type\_uid').Entry('your\_entry\_uid').fetch()  
  .then(function success(entry) {  
    console.log(entry);  
  }, function error(err) {  
    console.log(err);  
  });  

In this example, your\_content\_type\_uid is the unique identifier of the content type you want to retrieve, and your\_entry\_uid is the unique identifier of the entry you want to retrieve. The fetch() method retrieves the entry and returns it as a JavaScript object.

If you want to retrieve multiple entries, you can use the Query method, as shown in the following example:

const stack = Contentstack.Stack({"api\_key":"bltc2242b759e36fcb9","delivery\_token":"cs1470a664abc4563bd43a604d","environment":"development"});  // use your  api\_key and delivery\_token here from your Stack  
const query = stack.GetEntry('blog\_post').Query();  
  
query.toJSON()  
  .find()  
  .then(  
  (result) => {  
    console.log(result\[0\]);  
  },  
  (error) => {  
    console.error(error);  
  },  
);  
  

In this example, your\_content\_type\_uid is the unique identifier of the content type you want to retrieve. The find() method retrieves all the entries of the content type and returns them as an array of JavaScript objects.

The SDK also provides methods for filtering and sorting entries, as well as retrieving entries with specific fields. You can learn more about these methods in the Contentstack documentation.

There are also SDKs for most popular languages such as .Net, Java, PHP, Python, Ruby, iOS, Android, Dart, etc.

Documentation links:

*   [API Reference](https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/javascript-browser/reference/)
    
*   [JavaScript SDK Github Repo](https://github.com/contentstack/contentstack-javascript)
    
*   [All SDKs](https://www.contentstack.com/docs/developers/sdks/)
    
*   [Query examples](https://www.contentstack.com/docs/developers/web-framework/querying/)  
    

![content-sdk.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt31c71c762d48a421/664d45aa79abeeeb093d23a5/content-sdk.png)

#### Key takeaways

- Connect **Using the JavaScript Content Delivery SDK** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 12 — Using the GraphQL API with Postman

<!-- ai_metadata: {"lesson_id":"12","type":"text","duration_minutes":1,"topics":["Using","the","GraphQL","API","with","Postman"]} -->

#### Lesson text

## **Using the GraphQL API with Postman**

  

### GraphQL

Contentstack's GraphQL API is a powerful tool for developers who want to integrate Contentstack's content management system (CMS) into their web or mobile applications. It provides a flexible and efficient way to retrieve content from Contentstack's content repository using the GraphQL query language.

With Contentstack's GraphQL API, developers can retrieve content from their Contentstack projects using a single API call. The API returns only the data that is requested, which reduces the amount of data transferred and improves performance. The API also supports pagination, filtering, and sorting, which enables developers to retrieve only the content they need and to organize it in a way that best suits their application.

Contentstack's GraphQL API supports all of the content types and fields defined in a Contentstack project, including modular blocks and assets. This means that developers can retrieve any type of content from Contentstack, including text, images, videos, and more.

In addition, Contentstack's GraphQL API is designed to work seamlessly with popular frontend frameworks and libraries, such as React, Vue.js, and Angular. This allows developers to easily integrate Contentstack's content into their applications and to build dynamic and engaging user experiences.  

### **GraphQL API Explorer**

Contentstack has a GraphQL API explorer to query Contentstack's Content Delivery API.  

![graphQL.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt720a9df15d2b3c95/664d46208a0182e22014ca07/graphQL.png)

1.  In the Contentstack UI, navigate to Settings and then GraphQL
    
2.  Build your queries
    
3.  There is also an [Apollo Client JavaScript SDK](https://www.contentstack.com/docs/developers/graphql-api/use-the-graphql-queries-with-apollo-sdks/use-graphql-queries-with-apollo-client-javascript-sdk/) for using the API 
    

## More GraphQL API Resources

*   [GraphQL Postman Collection](https://www.contentstack.com/docs/developers/apis/postman-collections/)
    
*   [GraphQL Sample Apps](https://www.contentstack.com/docs/developers/graphql-api/graphql-sample-apps/)
    
*   [Using GraphQL with the Apollo Client JavaScript SDK](https://www.contentstack.com/docs/developers/graphql-api/use-the-graphql-queries-with-apollo-sdks/use-graphql-queries-with-apollo-client-javascript-sdk/)

#### Key takeaways

- Connect **Using the GraphQL API with Postman** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 13 — CDN and Caching

<!-- ai_metadata: {"lesson_id":"13","type":"text","duration_minutes":1,"topics":["CDN","and","Caching"]} -->

#### Lesson text

# **CDN and Caching**

A Content Delivery Network (CDN) ensures that a cache of your content is stored at various locations around the globe. Consequently, whenever there is a page request, the content is served from the cache of the nearest CDN server, rather than the origin server ensuring quicker content delivery.

## How CDN Cache Works in Contentstack

The CDN is always up-to-date. It ensures that the cache is always fresh through purging old data and caching new data.

When any user requests a piece of content, the nearest CDN server checks if it has a cached copy of the requested content. If not, it checks with the shield server. And, if the shield server does not have the cache of the requested content, it fetches the content from the origin server.

A shield server is an extra layer of caching that reduces the load on the origin server. It is located near the origin server, and it saves the cache of content that it serves to any CDN server. So, if any other CDN server requests the same data, the shield server would serve the cached content.

Contentstack automatically purges content from the internal Contentstack CDN when published.  

Helpful links:

*   [How CDN Cache Management works in Contentstack](https://www.contentstack.com/docs/developers/cdn-and-caching/contentstack-cdn-cache-management/)

#### Key takeaways

- Connect **CDN and Caching** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 14 — Query Examples with the Content Delivery API

<!-- ai_metadata: {"lesson_id":"14","type":"text","duration_minutes":1,"topics":["Query","Examples","with","the","Content","Delivery"]} -->

#### Lesson text

# Query Examples with the Content Delivery API

## **Query by URL**

const getContentByURL = async ({ contentType, slug, refUids, locale, filter }) => {  
  try {  
    const Query = global.Stack  
      .ContentType(contentType)  
      .Query()  
      .language(locale)  
    if (refUids) {  
      let refs = refUids.replace(/ /g, '').split(',')  
      Query.includeReference(refs)  
    }  
    let result = await Query  
      .includeFallback()  
      .where('url', \`/${slug}\`)  
      .toJSON()  
      .includeEmbeddedItems()  
      .addParam('include\_metadata', 'true')  
      .find()  
    if (result && result.length > 0 && result\[0\].length <= 0) { // for trailing slash match  
      result = await Query  
        .includeFallback()  
        .where('url', \`/${slug}/\`)  
        .toJSON()  
        .includeEmbeddedItems()  
        .addParam('include\_metadata', 'true')  
        .find()  
    }  
  
    (global.env === 'preview' || global.env === 'staging-preview' ||global.env === 'development') ? Contentstack.Utils.addEditableTags(result\[0\]\[0\], contentType, true, locale) : ''  
    //metadata key required for \_metadata in cms entry data  
    if(result.length > 0 && result\[0\].length > 0) {  
      result\[0\]\[0\] = {...result\[0\]\[0\], metadata: result\[0\]\[0\]}  
    }  
    if (result) return result\[0\]\[0\]  
  }  
  catch (error) {  
    throw new Error(error)  
  }  
}

  

## **Query by UID**

const getContentByUID= async ({ contentType, entryUid, refUids, locale }) => {  
  try {  
    const Query = global.Stack  
      .ContentType(contentType)  
      .Entry(entryUid)  
      .language(locale)  
      .includeFallback()  
      .includeEmbeddedItems()  
    if (refUids) {  
      let refs = refUids.replace(/ /g, '').split(',')  
      Query.includeReference(refs)  
    }  
    let result = await Query.toJSON().fetch()  
  
    if (result) return result  
  }  catch (error) {  
    return error  
  }  
}

  

## **Example to Get All Entries**

const getEntries = async ({ contentType, refUids, locale }) => {  
  let collectionData  
  try {  
    const Query = global.Stack.ContentType(contentType)  
      .Query()  
      .language(locale)  
    if (refUids) {  
      let refs = refUids.replace(/ /g, '').split(',')  
      Query.includeReference(refs)  
    }  
    let result = await Query  
      .includeFallback()  
      .toJSON()  
      .includeEmbeddedItems()  
      .addParam('include\_metadata', 'true')  
      .find()        
  
    if (result && result.length > 0 && result\[0\].length <= 1) { //for entry type = single  
      (global.env === 'preview' || global.env === 'staging-preview' || global.env === 'development') ? Contentstack.Utils.addEditableTags(result\[0\]\[0\], contentType, true, locale) : ''  
      //metadata key required for \_metadata in cms entry data  
      result\[0\]\[0\] = {...result\[0\]\[0\], metadata: result\[0\]\[0\]}  
      return result\[0\]\[0\]  
    }  
      
    //for entry type = multiple  
    (global.env === 'preview' || global.env === 'staging-preview' || global.env === 'development') ? Contentstack.Utils.addEditableTags(result\[0\]\[0\], contentType, true, locale) : ''  
    if (result) return result  
  }  
  catch (error) {  
    res.status(500).send(\`Internal Server Error\\n: ${error}\`)  
    // throw new Error(error)  
  }  
}

#### Key takeaways

- Connect **Query Examples with the Content Delivery API** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 15 — Using the Images API

<!-- ai_metadata: {"lesson_id":"15","type":"text","duration_minutes":1,"topics":["Using","the","Images","API"]} -->

#### Lesson text

# Using the Contentstack Images API

Welcome, developers, to the Contentstack Images API! As you may know, images are an integral part of any digital experience, and we understand the importance of delivering optimized images quickly and efficiently. That's why we've created the Contentstack Images API, a powerful tool that allows you to manipulate, optimize, and deliver images to your web and mobile applications. Whether you're new to the platform or a seasoned developer, this guide will provide you with everything you need to know to get started with the Contentstack Images API. So let's dive in and explore the possibilities of this powerful tool together!

Here are three advantages to using the Contentstack Images API:

1.  **Performance**: The Contentstack Images API allows you to deliver optimized images at scale, reducing load times and improving the overall performance of your web and mobile applications.
    
2.  **Flexibility**: With the Contentstack Images API, you have the flexibility to resize, and transform images in real-time, giving you the ability to customize images to fit any layout or design.
    

# Trying out the Image Delivery API

The quickest way to get started with the Image Delivery API is to try it out with the [online documentation](https://www.contentstack.com/docs/developers/apis/image-delivery-api/#introduction).  

Resize an image on the fly

Contentstack's Images API resizes images on the server and provides the resized file in the response.  This is highly performant as the resized image is stored in the CDN cache on the Contentstack side.

## **Exercise:  Resize an image with the Contentstack Images API**

1\. Go to the following URL, [https://www.contentstack.com/docs/developers/apis/image-delivery-api/#resize-images](https://www.contentstack.com/docs/developers/apis/image-delivery-api/#resize-images)

2. Update the width of the image and see the image size and dimensions being changed

![CSforDev\_L15\_Response200.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt5b227000df104193/67dc54ed4a89c32ebfa2f78a/CSforDev_L15_Response200.png)

##   
**Exercise: Auto-optimizing images with webp**

1. Navigate to the Automate Optimization section of the documentation, [https://www.contentstack.com/docs/developers/apis/image-delivery-api/#enable-auto-optimization](https://www.contentstack.com/docs/developers/apis/image-delivery-api/#enable-auto-optimization)

2\. Leave the default as webp in the query parameters

![CSforDev\_L15\_AutoOptimize.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta7976efcf6431992/67dc5524460eb47ea2946bed/CSforDev_L15_AutoOptimize.png)

## **Using the Images API in your NextJS Applications**

**Pass the width, height, or auto attributes to the src property in the img tag**

![CSforDev\_L15\_ImagesAPI.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt7e849a1eb5110a73/67dc5540f7eccc98ca90cc79/CSforDev_L15_ImagesAPI.png)

## **Exercise: Use the Images API to resize the home world image**

1.  Update the NextJS code to apply a width param of 150px to the home world image.  This resizes the image on the server-side and improves the performance of the page load.  
![CSforDev\_L15\_ImagesAPIresize.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt2cbba66331047777/67dc5553443bd63ff1f1bec6/CSforDev_L15_ImagesAPIresize.png)

#### Key takeaways

- Connect **Using the Images API** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 16 — Creating the Hero Detail Page

<!-- ai_metadata: {"lesson_id":"16","type":"text","duration_minutes":1,"topics":["Creating","the","Hero","Detail","Page"]} -->

#### Lesson text

# Exercise: Creating the Character Content Type

In this module we will cover the following topics:

*   How to build a Content Type
    
*   Review Field Types
    

Marketing has provided us with requirements to promote our Composable Heroes by creating a section of the site where each hero will have their own detail page and be listed on a gallery page.

In the next few exercises we will define the content type for a Composable Hero and build a hero detail page.  There’s no time to waste, let’s get started!

## Analyze the Page Design

When defining a new Content Type it's important to have the page design available (in photo / HTML format) so we can model the Content Type and define fields for the content elements.  

Analyze the following pages and think of the properties that a superhero character would need.  When analyzing pages we often look for as many representations of the same content as possible, and then we combine all these fields into one Content Type.  In this exercise, let's take a look at these two pages and see what fields they contain.  We will focus on the main page content and ignore the headers and footer.  If you would like to learn more, the Content Modeling course covers the content type fields in more detail.

![CSforDev\_L16\_PageDesign\_1.jpg](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt2c5939936d2d2857/67dc6a95b1a1f33f473eeed0/CSforDev_L16_PageDesign_1.jpg)

![CSforDev\_L16\_PageDesign\_2.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt2c4e42a167b5a160/67dc6adc1bae684bc54c6ad2/CSforDev_L16_PageDesign_2.png)

## Defining the Character Content Type for the Hero

In the previous section we analyzed the hero pages and thinking of what fields to use for defining the pages.  In this section, we will create the Content Type for the Character.  If you wish to copy / paste the code samples later, we would advise you to define the content type with the fields in this exercise.  However, if you wish to use your own field definitions, that's fine, but you will also need to adjust the code samples accordingly.

**Creating the Content Type**

Using the Content Type editor in Contentstack, create a new Content Type with fields for our Character content.  While defining the fields, we will need to consider what content we want to show on the detail page.  

After the exercise, your Content Type should look like this:

![CSforDev\_L16\_ContentTypeCheck.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt781d0a90b92e2c67/67dc6adb0c6f5510a31fc463/CSforDev_L16_ContentTypeCheck.png)

**Steps for the exercise:**  
1.  Create a new Content Type, named ‘Character’ for the composable heroes  
2.  Add the following fields:

**Hero Name** - Use the Title field  
Every Content Type in Contentstack has a Title field.  We can give it a different display name such as 'Name' or 'Character Name', but we cannot remove it.

**URL**  
For the Path, use '/composable-heroes/'  and then select the option to append the Title to the URL.  This is the most common way to define the URL structure.  For Content Types where we know the kind of content each page has (character) and that they will have detail pages, we decide to use '/composable-heroes/' as the URL path and then add the title to the end.  
  
![CSforDev\_L16\_URLproperties.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt0e9a7e511c89f116/67dc6adb5e486d1a4671aa9f/CSforDev_L16_URLproperties.png)

**Image (File)**  
Contentstack has an [Images API](https://www.contentstack.com/docs/developers/apis/image-delivery-api/) and supports uploading any media file, including images, up to 700 MB.  For images, there are additional properties such as min/max on width or height, so the CMS ensures the images used in a field meet the minimum size requirements.  
![CSforDev\_L16\_ImageFile.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt36199e9adb11c8e3/67dc6adb17f7b418a20cf683/CSforDev_L16_ImageFile.png)

**Description (JSON RTE)**

The JSON RTE field stores the content in JSON and the frontend webapp uses a [JSON RTE Serializer](https://github.com/contentstack/json-rte-serializer/) after publishing to transform the JSON to HTML.  There is also an [Automation Hub connector that can transform the RTE JSON to HTML](https://www.contentstack.com/docs/developers/automation-hub-connectors/rte-formatter/).  

The JSON RTE supports custom plugins and you can use the [App SDK](https://www.contentstack.com/docs/developers/developer-hub/get-started-with-building-apps-using-contentstack-app-sdk/) and extend the Rich Text Area with your own customizations.  Examples in the Marketplace include a word count extension and a Cloudinary extension.

![CSforDev\_L16\_Description.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blte8860a9727500de8/67dc6adbf7eccc35bd90ce1a/CSforDev_L16_Description.png)

**Powers (select field, add the powers)**

![CSforDev\_L16\_Powers.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltc8a96a22c1247f99/67dc6adb8fee9a228447d640/CSforDev_L16_Powers.png)

**Contact Info (Group field, email, phone)**

Group fields help us organize content fields and in the UI the editor can collapse / open the group.  They're also helpful when using the [Visibility Rules](https://www.contentstack.com/docs/developers/create-content-types/about-field-visibility-rules/) in Content Types

**Home world (Reference field)**

The Home world has an image and some additional properties, so we use a Reference Field and define a Content Type for the Home World instead of using a select field or defining the fields here.

> **Reference fields should be used when the content you want to include either already exists as a standalone entry (or part of one), or will be used by multiple content entries (either of the same type or not)**

**SEO**

Add a Global Field and choose the SEO Global Field  
![CSforDev\_L16\_SEO.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt2a67ac182732261b/67dc6adb4a89c32df8a2f912/CSforDev_L16_SEO.png)

  

**All Done!**

Congrats - you are done with the Content Type definition.    

**3.  Now, let's try out the new Character Content Type.  Create a new Entry with the Character Content Type and fill in the content and publish to Development**

## Content Type Best Practices

**URL field:**  Best practices/patterns.  Use the /path/:title for most content types, where relevant.  This maps to the Route in the web application and is also important for SEO. Choose this wisely.  
**Image field:**  Consider using the height/width limitations  
**Text fields:**  Consider any validations  
**Modular Blocks:** Think of this as a ‘design system’ of components the user can choose from.   They have the flexibility to add it if they want, or not.  Blocks can also be added at a later time to extend the content type. This can be done in confidence that things will not break if adjustments are made.

If you're using a modern framework such as NextJS or Nuxt, then we can think of having a NextJS Component responsible for rendering the content of one Modular Block.  In this way, the content and design are atomic and can be re-used across multiple pages.  
**Reference fields:**  When re-using content with many entries, we can use a Reference Field and connect the Entries.  We will need to add an additional query parameter to the Content Delivery Queries so that the referenced Entry fields will also be returned.  One example of using a reference field is on a homepage or landing page where we want to also show a listing of articles, products in a promo, etc.    
However, be mindful when implementing Reference fields as they can be easily overused.  When modeling content, it’s best to keep the relationship  as flat as possible and only use reference fields when referring to another type of content that is mostly independent of the model it is being referenced in.  If content fields are only used by the current entry, then it’s better to include them in the content type rather than using a reference field.  Reference field over-use is the most common content modeling pitfalls  and increases the complexity of the system for end users. 

# Create the NextJS Component for the superhero detail page

Next step is to render the Character Entries on a superhero detail page.  This process involves the following steps:

1.  Create a new NextJS Component and import the Contentstack libraries.
    
2.  Use the HTML Provided and add the code to render the Contentstack Character Content Type fields.
    
3.  Run locally and preview the page.
    

Now that we have defined our superheroes using the Character Content Type and added some sample content, it's time to create a detail page to display them on our website. The HTML file for the superhero detail page is provided below. Using Contentstack's Content Delivery API and Next.js, we can create the code to render this page on our website.

## Programming the Character Detail Page

1\. Create a new NextJS Component for the detail page in a folder 'composable-heroes' and using the name \[post\].tsx

2.  Analyze the code for the Detail page and notice how we render text fields, reference fields and group fields.  [The code is available on Github here.](https://github.com/contentstack/contentstack-academy-playground/tree/main/app/composable-heroes)

3.  **Examine the Helper/index.js file** and [**review the code for getting a Single Entry (Character Content Type)**](https://github.com/contentstack/contentstack-academy-playground/blob/89452b765dac23970f24ece7412beefc62bb18ec/helper/index.js#L106).  This function will use the existing method ‘GetEntryByUrl in the /contentstack-sdk/index.js file to query for the Entry content. 

![CSforDev\_L16\_ExamineHelper.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltfe79f5ee8485bddd/67dc6adbc566ee159b5df64c/CSforDev_L16_ExamineHelper.png)

[Content Delivery JS SDK API Ref](https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/javascript-browser/)  
[Examples using the Content Delivery JS SDK in a NextJS Service](https://gist.github.com/robertcurlette-cs/066c818c09c752426056eee7e9fa541c) 

**4.  Call the Character Query function from the NextJS** [composable-heroes/\[post\].tsx file](https://github.com/contentstack/contentstack-academy-playground/blob/89452b765dac23970f24ece7412beefc62bb18ec/pages/composable-heroes/%5Bpost%5D.tsx#L62)

![CSforDev\_L16\_CharacterQuery.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt5330eb37dbb29171/67dc6adbdb243f203c12b94c/CSforDev_L16_CharacterQuery.png)

## [**Code Solution for Composable Hero Detail Page on Github**](https://github.com/contentstack/contentstack-academy-playground/blob/main/app/composable-heroes/%5Bpost%5D/page.tsx)

## Field rendering syntax:

**Text fields - Rendering the title field**

{postData?.title}

**Group fields**

{postData?.contact\_info?.email ?

**Email :** {postData?.contact\_info?.email}

**Images**

![CSforDev\_L16\_RenderImage.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbe51c92c1ac561c8/67dc6adbc5b83e51fa924181/CSforDev_L16_RenderImage.png)

  
**Reference Field**

![CSforDev\_L16\_RenderField.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta737586dbcea3b4a/67dc6adb983a658c2e3b71db/CSforDev_L16_RenderField.png)

**6.  Confirm your code with the Composable Detail Page solution**

**Final Result - Composable Hero Detail Page**

![CSforDev\_L16\_FinalResult.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt9e10f8c799a48670/67dc6adc5e486d1eed71aaa3/CSforDev_L16_FinalResult.png)

#### Key takeaways

- Connect **Creating the Hero Detail Page** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 17 — Creating the Hero Gallery Page

<!-- ai_metadata: {"lesson_id":"17","type":"text","duration_minutes":1,"topics":["Creating","the","Hero","Gallery","Page"]} -->

#### Lesson text

## The Composable Hero Landing Page

Welcome to this tutorial on creating a superhero gallery page using reference fields in NextJS! In this module, we'll walk you through the steps of creating a new content type called "Superhero Gallery Page" and adding heroes to it manually. 

We'll start by showing you how to utilize reference fields to display hero content on the landing page with their images and names. This technique is commonly used in product promotions and article index pages, so it's a valuable skill to learn. 

Next, we'll guide you through the process of creating a new NextJS component and query to retrieve the Landing Page Entry and Reference field Hero Entries. Our NextJS component will loop through all the heroes in the reference field and display their titles, images, and links to their respective detail pages.

Finally, we'll demonstrate how to create a new Landing Page Entry and publish it to the Development environment to see the results of our work.

By the end of this tutorial, you'll have gained valuable knowledge on how to utilize reference fields in NextJS to create reusable content and enhance the user experience on your website. Let's get started!

![CSforDev\_L17\_ComposableHeroes.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt36760c2226f23188/67dc74d1443bd6f8bef1c126/CSforDev_L17_ComposableHeroes.png)

## **Hero Gallery Page Content Type**

![CSforDev\_L17-HeroGalleryPageContentType.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltca3a395e8b43a268/67dc74d25e486ddf7571ab5f/CSforDev_L17-HeroGalleryPageContentType.png)

#### Open the Superhero Gallery Page and examine the properties of each field

![CSforDev\_L17-SuperHeroGalleryPage.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt5d634d5af8ed1ef2/67dc74d120a3dc7d26f81da5/CSforDev_L17-SuperHeroGalleryPage.png)

**Review the following fields below:**

*   Title - Default Title field
    
*   URL - /gallery/:title
    
*   Heading - Text field
    
*   Description - Multi-line text
    
*   Characters - Reference field to the Character Content Type
    

## Part 2: Writing the code to display the list of heroes

**Let's list all the heroes in the reference field on the Gallery page.  Users can manually create a list of heroes and our code will loop over all the heroes in the reference field and render the name, image, and link.**   

### Rendering a list of Characters from a Reference Field

  
**1.  Create a NextJS Component for the Gallery page** and loop through all the heroes in the reference field, rendering the title, image and a link to the detail page.  This involves 2 steps, first writing the query function and then rendering the results.

  
**2.  Querying Contentstack for the Characters in the Reference Field**  
[In the /helpers/index.js file](https://github.com/contentstack/contentstack-academy-playground/blob/main/helper/index.js), review the function to get a list of heroes from the reference field

  
**3.**  [Review the code for the /composable-heroes/index.tsx file](https://github.com/contentstack/contentstack-academy-playground/blob/main/pages/composable-heroes/index.tsx)**.**  

  
**4.  Review the Composable Heroes Gallery Entry**

![CSforDev\_L17-ReviewComposableHeroesGalleryEntry.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta1719b3c553d3aa7/67dc74d28fee9af26547d6d2/CSforDev_L17-ReviewComposableHeroesGalleryEntry.png)  

**5.  From the NextJS application, open the Composable Heroes Gallery Page**

![CSforDev\_L17-NextJSappOpenComposableHeroes.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt987109e80668c33d/67dc74d2c566ee77065df700/CSforDev_L17-NextJSappOpenComposableHeroes.png)

  

**2\. Introduction to using the Query functions of the Content Delivery API**

Contentstack provides certain queries that you can use to fetch filtered results. You can use queries for Entries and Assets API requests.  **Please review the** [Content Delivery Query API documentation](https://www.contentstack.com/docs/developers/apis/content-delivery-api/#queries) **and examine the RegEx, Limit and Only functions.**

**For the first part of the exercise, we can use a simple query to find all the entries with the Content Type of Character.**  

### Postman

**1.  Open Postman and select the Entries/Get Entries call**  
Update the parameters / variables so that:

*   content\_type\_uid = character
    
*   environment = development  
    

![CSforDev\_L17-Postman1.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltfc54a08558f3257d/67dc74d20c6f5573391fc550/CSforDev_L17-Postman1.png)

You should now have a list of the characters published to the development environment.  In the next section, we will use the JavaScript SDK to get the same list and pass it to the NextJS App to render.

  

**3\. Query using Javascript SDK**

In our web application we will mostly use the [Javascript Content Delivery SDK](https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/javascript-browser/reference/).  **Please have a look at the** [documentation for the query methods](https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/javascript-browser/reference/#query)**.**

Other SDKs can be found on the [SDKs documentation page](https://www.contentstack.com/docs/developers/sdks/)

import Contentstack from 'contentstack';  
const Stack = Contentstack.Stack({"api\_key": "api\_key", "delivery\_token": "delivery\_token", "environment": "environment"});  
const result = await Stack.ContentType('character').Query().toJSON().find();

[More information about this is found in the Javascript SDK Docs](https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/javascript-browser/reference/#stack-query)

## Composable Hero Landing Page

The Composable Hero Landing Page uses [Modular Blocks](https://www.contentstack.com/docs/developers/create-content-types/modular-blocks/) to provide a flexible structure for authors to create content and add as many content blocks to the page as they wish and also to re-order the blocks.  

![CSforDev\_L17-ComposableLandingPage.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt20cf9dbe38b2ce7a/67dc74d2dd73e3150dbf2aca/CSforDev_L17-ComposableLandingPage.png)

  

## Open the Superhero Landing Page Entry and review the content

![CSforDev\_L17-OpenSyperheroLandingPage.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbd496f6c2aa7c3fb/67dc74d1632b938d87d497f4/CSforDev_L17-OpenSyperheroLandingPage.png)

##   

## Open the Content Type Definition and examine how the Modular Blocks field is used. 

Notice the fields are greyed out - that is because the Modular Block fields are defined using Global Fields.  This is a best practice.

![CSforDev\_L17-OpenContentTypeDefinition.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltcb805c91070decc1/67dc74d18fee9a015647d6ce/CSforDev_L17-OpenContentTypeDefinition.png)

## Global Field Definitions

![CSforDev\_L17-GlobalFieldDefinitions.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt133ae7c39bec81dd/67dc74d1782bfb40816f4d07/CSforDev_L17-GlobalFieldDefinitions.png)

##   

## Examine the Code used for the Hero Landing Page

The [**code for the Gallery Entry (Page)**](https://github.com/contentstack/contentstack-academy-playground/blob/main/pages/gallery.tsx) loops through all the Modular Blocks on the page and renders each one with its' own NextJS Component.  
![CSforDev\_L17-CodeForGalleryEntry.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt32ad6ea1b6068a60/67dc74d16f68587885fd9e35/CSforDev_L17-CodeForGalleryEntry.png)

## Each block is rendered with its own NextJS Component

*   [Gallery Block](https://github.com/contentstack/contentstack-academy-playground/blob/main/components/gallery.tsx)[  
    ](https://github.com/contentstack/contentstack-academy-playground/blob/main/components/gallery.tsx)![CSforDev\_L17-BlockRenderwithNextJScomp.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt6997b78ab65f5110/67dc74d1bbf93ef9c3586444/CSforDev_L17-BlockRenderwithNextJScomp.png)
    
      
      
    
*   [Hero Banner Block](https://github.com/contentstack/contentstack-academy-playground/blob/main/components/hero-banner.tsx)
    
    ![CSforDev\_L17-HeroBannerBlock.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt57deb882be0262c1/67dc74d1db243fda9112b9df/CSforDev_L17-HeroBannerBlock.png)[  
    ](https://github.com/contentstack/contentstack-academy-playground/blob/main/components/hero-banner.tsx)
    

By adopting this approach, we can isolate the HTML/Code for each block within a single NextJS Component. This simplifies maintenance and enables easy extension of the page in the future by adding a Modular Block and NextJS Component for additional content block types. 

With this method, you can modify the individual content blocks without having to make changes to the entire page structure. This approach makes the codebase more organized and easier to manage, especially when dealing with complex web applications. 

By leveraging this technique, you can increase the scalability and modularity of your website, allowing you to add new features and functionalities with ease.

#### Key takeaways

- Connect **Creating the Hero Gallery Page** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 18 — Design Patterns with Content Types

<!-- ai_metadata: {"lesson_id":"18","type":"text","duration_minutes":1,"topics":["Design","Patterns","with","Content","Types"]} -->

#### Lesson text

### Using Modular Blocks - Advantages

There are several advantages to using Contentstack's modular blocks when designing content types. Here are some of the key advantages:

1\. Flexibility for marketers: Modular blocks allow marketers to easily create and customize content without requiring technical expertise. With modular blocks, marketers can easily use pre-designed content blocks to create engaging content without having to worry about formatting or layout.

2\. Reusability: With Global Fields, Modular blocks can be reused across different content types and pages, which can help to save time and effort when creating new content.

3\. Consistency: Modular blocks ensure consistency in content formatting and layout, which can help to improve the overall user experience.

4\. Granular control: Modular blocks provide developers with granular control over content structure and formatting, which can help to ensure that content is properly organized and optimized for SEO.

5\. Easy maintenance: With modular blocks, it is easy to update and maintain content without having to modify the entire content type or page.

7\. Future-proofing: Modular blocks provide a future-proof solution for content design, as they can be easily updated and modified to meet changing business needs.

## Example:  Using Modular Blocks in the  Starter App

In the Starter App, the Page Content Type uses Modular Blocks to define the various sections of the page.  In this example below, notice how each block or module on the page is a Modular Block.  In this example we have 3 Modular Blocks.

![CSforDev\_L18-ExampleModularBlocks.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt163b2eba984ba5dd/67dc77d9dd73e3394ebf2b15/CSforDev_L18-ExampleModularBlocks.png)

  

**These Blocks are used in the Page Content Type.**

![CSforDev\_L18-BlocksUsedInPageComponent.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltc596ad6019f6b557/67dc77d9c5b83e1789924263/CSforDev_L18-BlocksUsedInPageComponent.png)

  

## **Using Global Fields for Defining Re-Usable Content Structures**

Global Fields in Contentstack promote the re-use of content structures across content types.  They allow us to define a schema of fields and then reference that definition from another content type or modular block.

In the StarterApp website, the **SEO** fields are defined as Global Fields. This makes it easy to manage the SEO fields from one location and re-use the definition across all content types.

![CSforDev\_L18-GlobalFields\_3.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbfba1754f824d5ea/67dc77d96f6858cde5fd9e68/CSforDev_L18-GlobalFields_3.png)

![CSforDev\_L18-SEO\_4.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt868c68695563b3bd/67dc77d9a6d88e2e87052b51/CSforDev_L18-SEO_4.png)

  

## **Using Global Fields for Modular Blocks**

Global fields can  also be used to define field sets for Modular Blocks. This is a great way to re-use structure.  Note, it is currently not possible to nest a Global Field inside another Global Field, so take that into consideration when designing your content types.

## **Resources**

*   [Modular Blocks](https://www.contentstack.com/docs/developers/create-content-types/modular-blocks/)
    
*   [Global Fields](https://www.contentstack.com/docs/developers/global-field/)
    
*   [Limitations of Global Fields](https://www.contentstack.com/docs/developers/global-field/limitations-of-global-field/)
    
*   [Content Modeling Best Practices](https://www.contentstack.com/docs/developers/content-modeling/content-modeling-best-practices/)

#### Key takeaways

- Connect **Design Patterns with Content Types** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 19 — Deploying the Starter App with Contentstack Launch

<!-- ai_metadata: {"lesson_id":"19","type":"text","duration_minutes":1,"topics":["Deploying","the","Starter","App","with","Contentstack"]} -->

#### Lesson text

With Contentstack's launch product, developers can focus on building and updating their applications while leaving the hosting infrastructure to Contentstack.

To assist users with the various functionalities of this product, Contentstack offers a [comprehensive help center](https://www.contentstack.com/docs/developers/launch/) on its website. The help center includes detailed guides and tutorials on [creating projects](https://www.contentstack.com/docs/developers/launch/import-project-using-github/), [setting up deploy hooks](https://www.contentstack.com/docs/developers/launch/deploy-hooks/), and [redeploying applications](https://www.contentstack.com/docs/developers/launch/redeploy-automatically-when-content-is-published-on-CMS/) when content is published. Additionally, the website provides a robust community forum where users can interact with other users, share their experiences, and get support from the Contentstack team.

*   **Host** your website or web app directly from Contentstack, leveraging our high-speed CDN and proven infrastructure.
    
*   **Link** your Contentstack Stacks and front-end environments without copying and pasting API keys.
    
*   **Leverage** the only front-end site hosting solution that’s built explicitly for the Contentstack CMS.
    

## Framework agnostic

Build projects in virtually any common Javascript front-end framework, easily connect to and deploy code directly from a git repository.

*   **Automatic** configuration for Nextjs and Gatsby, with more frameworks on the way
    
*   **Use** virtually any composable Javascript front-end framework with custom build commands.
    
*   **Upload** static site files via Zip for instant deployment for projects that don’t use git.
    
*   **Support** for Edge functions and more **coming soon!**
    

# **Exercise: Deploy the site with Contentstack Launch**

**1.  Open Launch**  
![CSforDev\_L19-img\_1.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt59869ec9f872a769/67dc7979632b93a52ad4983e/CSforDev_L19-img_1.png)

**2.  New Project**

  

**3.  Upload File**

![CSforDev\_L19-img\_2.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt803195694348711a/67dc79af983a650b893b72f7/CSforDev_L19-img_2.png)

  

**4\. Upload the StarterApp project**.  In this example, we will use the NextJS Starter App.  Download the code from the Github repository here: [https://github.com/contentstack/contentstack-nextjs-starter-app](https://github.com/contentstack/contentstack-nextjs-starter-app)

  

**5.  Select your Stack with the Starter App** and then Import Environment Variables

![CSforDev\_L19-img\_3.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt91248dc45e8c64c4/67dc79e5314d6788311b6674/CSforDev_L19-img_3.png)

**6.  Site is being deployed**.  This takes up to 5 minutes.  The URL will be a Contentstack URL with the free trial, however, with a paid plan you will be able to use custom domains.

![CSforDev\_L19-img\_4.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt9de2eeb19d27402b/67dc7a13dd73e3fed6bf2b3b/CSforDev_L19-img_4.png)

  

**7.  Site is deployed**

  

### Learn More About Launch

*   [Developer Documentation](https://www.contentstack.com/docs/developers/launch/)
    
*   [Community Forum](https://community.contentstack.com/search?q=Launch&search_type=tag)
    
*   [Guide for Deploying the StarterApp with Launch](https://www.contentstack.com/docs/developers/launch/quick-start-nextjs/)

#### Key takeaways

- Connect **Deploying the Starter App with Contentstack Launch** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 20 — Importing Content with the CLI and CMA

<!-- ai_metadata: {"lesson_id":"20","type":"text","duration_minutes":1,"topics":["Importing","Content","with","the","CLI","and"]} -->

#### Lesson text

## Introduction to the Content Management API

Our Content Management API (CMA) is a powerful tool that provides a read/write API with a REST interface, as well as SDKs for JavaScript, .NET, and Java. To authenticate with the CMA, we use Tokens. In this exercise, we'll guide you through how to use the CMA with Postman, a popular tool that helps developers use APIs.

Let's get started with the exercise. We'll be using Postman, so first, make sure to download the latest Contentstack Postman collection from here: [https://www.contentstack.com/docs/developers/apis/content-management-api/#install-postman](https://www.contentstack.com/docs/developers/apis/content-management-api/#install-postman)

Also, download and use the Postman Environment Files from Github here: [https://github.com/contentstack/contentstack-postman-collections#environment-files](https://github.com/contentstack/contentstack-postman-collections#environment-files)

![CSforDev\_L20-img-1.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltf68a0bfc44851c8f/67dc7a8d5e486d622a71ac32/CSforDev_L20-img-1.png)

  

The next step is to create a Management Token to use in our Postman query. To do this, go to Settings in the Contentstack UI, then Tokens, Content Management, and create a Management Token. You can follow this guide for more detailed instructions: [https://www.contentstack.com/docs/developers/create-tokens/generate-a-management-token/](https://www.contentstack.com/docs/developers/create-tokens/generate-a-management-token/)

![CSforDev\_L20-img-2.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltc549d1dc354f62fb/67dc7aab983a655a2b3b7306/CSforDev_L20-img-2.png)

  

Now, **open Postman and add the Content Management API Postman Collection**. Select Content Management API - Contentstack, Entries, **Get a single entry**, and you're ready to go!

In Postman, select Content Management API - Contentstack, Entries, Get a single entry

  

**Update the API Key and Access Token**

There are two ways to set the values, using Postman variables like above or hard-coding the values in the Value column.  I prefer to use the Environment variables. [https://github.com/contentstack/contentstack-postman-collections#environment-files](https://github.com/contentstack/contentstack-postman-collections#environment-files)

1.  Set the Environment variable values for your Stack in Postman by selecting the icon in the top-right of Postman to open the Environment variable window.

Specify the following header values:  
\- **api\_key** - This is located in the Settings, Tokens, Management Token page.  You can also see it in the URL of the browser, after the /stack/ part of the URL, http://app.contentstack.com/#!/stack/{api\_key}

\- management\_token - Management token created in step 1

2.  Use the ‘Get a single entry’’ method and add the base\_url, content\_type\_uid (character) and entry uid to the query.  This will retrieve the JSON for the Entry using the backend CMA.  

**\*Note, we do not use this API for our frontend website applications as it is not intended for high load / performance.  Instead, the frontend web applications use the Content Delivery API which is tuned for high performance.**

3.  Run the query and see the JSON result.  
Notice that we have Create / Read / Update / Delete operations for most types.

  
**Using the JSON returned from the Get Entry method, we will create new JSON to use for the Create Entry method in the next exercise.**  
   
**Learn More:**  
Key Features of Management Tokens: [https://www.contentstack.com/docs/developers/create-tokens/key-features/](https://www.contentstack.com/docs/developers/create-tokens/key-features/)

## Creating content with the API:  Using the Content Management API

### Exercise:  Create an entry with the Postman API

In this exercise, we'll guide you through creating a new Entry in Contentstack programmatically using our Content Management API. This method is incredibly useful for quickly migrating content from external systems and avoiding manual entry.

The trickiest part of this process is creating well-formed JSON that contains all the properties and content for the Entry. But don't worry - we've got you covered. In the previous exercise, we used our CMA to retrieve the Entry JSON, and now we'll use a subset of that JSON to create our new Entry.

If you weren't able to retrieve the JSON Entry export in the previous exercise, we've included a sample below. Just make sure to update the UID of the Content Type for it to work.

To get started, let's create the Entry JSON required to make a new Entry. Below is an example JSON, but remember to replace the Content Type UID:

{
  "title": "New Entry Title",
  "url": "/new-entry-url",
  "description": "This is a new Entry created programmatically using the Content Management API.",
  "content\_type\_uid": "your-content-type-uid",
  "metadata": {
    "tags": \["tag1", "tag2"\],
    "author": "John Doe"
  },
  "body": "

This is the body of the new Entry.

" }

Now, in Postman, open the ‘Create an entry’ method and in the body tab, paste the JSON of the new Entry. Please note that the Title property of the Entry needs to be unique.

As we used Postman variables in the previous exercise, you won't need to add any additional settings here, since the api\_key and management token are already specified.

Finally, hit the Send button in Postman to create your new Entry. Head over to the Contentstack UI to confirm that it has been created successfully.

## Exporting Content from Contentstack

Contentstack stores all text content in JSON format.  This makes it very easy to import / export and update content using the Content Management API or the CLI.  In this section we will discuss the three ways to export content from Contentstack:  UI, CM API, and the CLI.

## Exporting with the UI

![CSforDev\_L20-img-3.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt3031a286be14c33e/67dc7af4a71458f9d3b9ac8d/CSforDev_L20-img-3.png)

##   

## [Exporting with Postman](https://www.contentstack.com/docs/developers/apis/postman-collections/)

![CSforDev\_L20-img-4.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltf85b2c24d02d5273/67dc7b2437e25afefd1e3cac/CSforDev_L20-img-4.png)

##   

## [Exporting with the CLI](https://www.contentstack.com/docs/developers/cli/export-content-using-the-cli/)

![CSforDev\_L20-img-5.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltdf993e1837922ae0/67dc7b8ec566ee36ce5df792/CSforDev_L20-img-5.png)

  

## Exporting Content from Contentstack

Contentstack stores all text content in JSON format.  This makes it very easy to import / export and update content using the Content Management API or the CLI.  In this section we will discuss the three ways to export content from Contentstack:  UI, CM API, and the CLI.

#### Exporting with the UI

![CSforDev\_L20-img-6.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt125b7f4295bb35a9/67dc7bbd632b932162d49860/CSforDev_L20-img-6.png)

#### [Exporting with Postman](https://www.contentstack.com/docs/developers/apis/postman-collections/)

![CSforDev\_L20-img-7.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt1b91f0972f174299/67dc7be7a714580b08b9ac9c/CSforDev_L20-img-7.png)

##   

#### [Exporting with the CLI](https://www.contentstack.com/docs/developers/cli/export-content-using-the-cli/)

![CSforDev\_L20-img-8.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt029257333658a4ea/67dc7c0d2d0b98a5affcfe07/CSforDev_L20-img-8.png)

#### Key takeaways

- Connect **Importing Content with the CLI and CMA** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 21 — Working with Roles and Permissions

<!-- ai_metadata: {"lesson_id":"21","type":"text","duration_minutes":1,"topics":["Working","with","Roles","and","Permissions"]} -->

#### Lesson text

## Roles

Contentstack has a robust roles and permissions system with built-in roles such as 'Admin', 'Developer', and 'Content Manager' and the ability to create custom roles for authors and editors.  In this module we will look briefly at the roles and permissions system in Contentstack.

**Built-in Roles**

**Admin:** Admin has full access to all features and functions within Contentstack, including the ability to create, edit, and delete content, manage users and roles, and configure the system settings. Super Admins have the highest level of privileges and can perform any action within the platform.

**Content Manager**: The Content Manager has the ability to create, edit, and delete content, as well as manage users and roles. However, they do not have access to the system settings or the ability to perform advanced tasks such as configuring webhooks or integrations.

**Developer**: The Developer role is designed for users who need to access the Contentstack API and develop custom solutions using the platform. Developers have the ability to create and manage content types, as well as access the API documentation and sample code. However, they do not have the ability to manage users and roles.

  

**Custom Roles**

In Contentstack, custom roles allow users to define and customize the level of access and permissions for specific users or groups of users. This provides greater flexibility and control over how content is managed and published within the system.

To create a custom role, a Super Admin or a user with the "Manage Roles" permission can navigate to the Roles section of the Contentstack dashboard and click on the "Add Role" button. From here, they can give the custom role a name and select the specific permissions that they want to grant to users assigned to that role.

The available permissions can be grouped into three categories:

*   Content: permissions related to creating, editing, and publishing content and images
    
*   Publishing: permissions related to publishing content and environments
    
*   Languages: Permissions relating to localization
    

Once the custom role is created, it can be assigned to specific users or groups of users within the system. Users assigned to the custom role will only have access to the permissions and features that are granted to that role, ensuring that they only have access to the specific tasks and content that they are responsible for. This helps to improve security and streamline workflows within the system.

## Exercise: Creating a custom role

 Here are the steps to create a custom role in Contentstack:

1\. Log in to your Contentstack account and navigate to the “Settings / Users & Roles / Roles” section of the dashboard.

2\. Click on the “New Role” button to create a new custom role.

3\. In the “Role Details” section, enter a name for your custom role.

4\. Next, choose the permissions you want to grant to this role by selecting the options for each permission category (Content, Assets, Languages and Environments).

5\. Under each permission category, you can select or deselect specific permissions that you want to include or exclude for this role.

7\. Once you have selected the permissions you want to grant to the custom role, click the “Save” button to save the role.

8\. To assign users to the custom role, navigate to the “Users” section of the dashboard and select the user(s) you want to assign the role to.

9\. In the “Update User” dialog box, select the “Roles” tab, and then select the custom role you created from the list of available roles.

10\. Click the “Save” button to save the changes.

That's it! You have now created a custom role in Contentstack and assigned it to specific users within your organization.

### Resources

*   [Examples to create custom roles](https://www.contentstack.com/docs/developers/invite-users-and-assign-roles/examples-to-create-custom-roles/)

#### Key takeaways

- Connect **Working with Roles and Permissions** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 22 — Workflow

<!-- ai_metadata: {"lesson_id":"22","type":"text","duration_minutes":1,"topics":["Workflow"]} -->

#### Lesson text

Contentstack's workflow feature is a powerful tool that enables organizations to manage the content creation and publishing process in a streamlined and efficient way. With workflow, content creation and publishing becomes a collaborative process that involves multiple stakeholders, including writers, editors, and approvers. 

The workflow feature allows you to define a series of states that content can go through, from initial creation to final approval and publishing. Each state represents a stage in the content creation process, and can be assigned to different roles or users. For example, you can set up states such as "Draft", "In Review", "Approved", and "Published".

As content moves through the workflow, it can be edited, reviewed, and approved by different users based on their assigned roles. Users can add comments and feedback, and content can be easily tracked and managed throughout the entire process. This ensures that content is thoroughly reviewed and approved before being published, minimizing the risk of errors or inaccuracies.

Contentstack's workflow feature also includes notifications and alerts, which keep everyone involved in the process informed of content changes, updates, and approvals. This helps to keep the process moving smoothly and ensures that everyone is on the same page.

![CSforDev\_L22-img-1.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt655072dfe47556f8/67dc7c8f17f7b4421c0cf7cd/CSforDev_L22-img-1.png)

## Exercise: Creating a Workflow with a Publish Rule

Here's a step-by-step guide on how to use Contentstack's workflow feature to create a publishing rule for production:

Step 1: Log in to your Contentstack account and select the stack you want to work with.

Step 2: Click on the "Settings" button in the top navigation bar.

Step 3: Click on the "Workflows" tab.

Step 4: Click on the "New Workflow" button.

Step 5: Enter the following:  
\- Name:  "Blog Workflow".    
\- Scope (branches): Main.    
\- Specific Content Types: Blog Entry

Step 6: Add the states that content will go through before being published. For example, you could add the states "Draft", "In Review", "Approved", and "Published".

Step 7: Click on the "Enable Workflow" checkbox and the "Save" button to create the workflow.

Step 8: Next, you'll need to create a publishing rule that specifies which content should be published to your production environment. Click on the "Publishing Rules" tab.

Step 9: Click on the "New Publishing Rule" button.

Step 10: Enter a name for your publishing rule, such as "Publish to Production".

Step 11: Under "Content type", select the "Blog Entry" Content Type

Step 12: Under "Language", select "All Languages"

Step 13: Under "Environment", select "Production"

Step 14: Under "Rule Conditions", you can set up conditions that must be met before the content is published. For example, you could require that the content has the "Approved" state before it can be published.

Step 15: Click on the "Save" button to save the publishing rule.

Step 16: Now, whenever content is created or updated, it will go through the workflow you created in step 5. If the content meets the conditions you set up in the publishing rule, it will be published to your production environment automatically.

Congratulations! You have successfully created a publishing rule for production using Contentstack's workflow feature. This will help you streamline your content creation and publishing process and ensure that only approved content is published to your production environment.

## Example: Using Workflow and Webhooks for Automating Translation

In the context of a Contentstack workflow, a webhook trigger can be used to automate the movement of content through the different stages of the workflow or send to an external service such as a translation agency. 

To set up a webhook trigger to use a workflow stage in Contentstack, you would first need to create a workflow and define the stages that content should go through. Once the workflow is set up, you can create a webhook trigger that is triggered when content is created or updated.

In the webhook trigger settings, you can specify the workflow stage that the content should be moved to when the webhook is triggered. For example, you could set up the webhook trigger to move the content from the "Draft" stage to the "In Review" stage when it is created or updated.

Once the webhook trigger is set up, it will automatically move the content through the workflow based on the rules that you have defined. This can help to save time and improve efficiency, as content can be automatically routed to the appropriate stage without requiring manual intervention.  

**Step 1: Set up your workflow in Contentstack**  
First, you'll need to set up your workflow in Contentstack to define the stages that content should go through before it is published. For example, you might create stages for "Draft", "In Review", and "Approved".

**Step 2: Set up a webhook trigger**  
Next, you'll need to set up a webhook trigger that is triggered when content is created or updated. In the webhook trigger settings, you can specify the URL of your 3rd-party translation service, along with any required authentication details.

**Step 3: Define a workflow stage for translation**  
In your workflow, you can define a new stage specifically for translation. For example, you might create a stage called "Translation" that is between the "In Review" and "Approved" stages.

**Step 4: Set up a webhook action to send content to the translation service**  
In the workflow stage for translation, you can set up a webhook action that sends the content to the 3rd-party translation service. You can use the webhook trigger that you set up in step 2 to automatically send the content to the translation service when it enters the "Translation" stage.

**Step 5: Receive and process the translated content**  
Once the content has been sent to the translation service, the service will translate the content into the desired language(s). The translation service can then send the translated content back to Contentstack via another webhook trigger.

**Step 6: Move the translated content to the next stage in the workflow**  
When the translated content is received by Contentstack, you can set up another webhook action that automatically moves the content to the next stage in the workflow. For example, you might move the content from the "Translation" stage to the "Approved" stage when it is received.

Overall, using a Contentstack webhook trigger with workflow to send content to a 3rd-party translation service can help to streamline the translation process and ensure that content is translated efficiently and accurately. 

# Resources

*   [Workflow Documentation](https://www.contentstack.com/docs/developers/set-up-workflows-and-publish-rules/)
    
*   [Translation Integrations](https://www.contentstack.com/docs/developers/how-to-guides/#translation-services)

#### Key takeaways

- Connect **Workflow** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 23 — Webhooks

<!-- ai_metadata: {"lesson_id":"23","type":"text","duration_minutes":1,"topics":["Webhooks"]} -->

#### Lesson text

Contentstack's webhook system is a powerful tool that allows developers to automate the process of receiving real-time notifications of changes made to content within the CMS. A webhook is an HTTP callback that sends a notification to a specified URL whenever a specific event occurs. In the case of Contentstack, the event could be when content is created, updated, deleted, or published.

Developers can create webhooks in Contentstack and specify which events should trigger them. When an event occurs, Contentstack sends an HTTP POST request to the specified URL, containing information about the event and the associated content.

With this information, developers can automate processes such as updating search indexes, notifying team members of content changes, or triggering other third-party services. Additionally, Contentstack allows developers to set up conditional logic to filter webhooks based on specific criteria, such as content types, allowing for even more granular control over webhook behavior.

## Exercise: Using a webhook to call an endpoint on the webhook.site service

Step 1: Go to [webhook.site](https://webhook.site) in your web browser.

Step 2: Click on the "Create a webhook" button on the top right corner of the webpage.

Step 3: In the "Create a new webhook" modal, you'll see a unique webhook URL that you can use to send HTTP requests. Copy this URL to your clipboard.

Step 4: Log in to your Contentstack account and go to the Settings section of your stack.

Step 5: Click on the "Webhooks" tab.

![CSforDev\_L23-img-1.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt9928fe7cfbd4a917/67dc7ce545b2290ec4910d8c/CSforDev_L23-img-1.png)

  

Step 6: Click on the "Add New Webhook" button.

Step 7: In the "Create Webhook" modal, enter a name for your webhook, such as "Webhook.site Test".

  

Step 8: In the "URL" field, paste the webhook URL that you copied from webhook.site in step 3.

![CSforDev\_L23-img-2.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt40127c0aeeac44ff/67dc7d088fee9a424247d751/CSforDev_L23-img-2.png)

Step 9: Under "Webhook Triggers", select "Publish" as the trigger event.

![CSforDev\_L23-img-3.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltaa1169f852f5c558/67dc7d3220a3dc0ca6f81e2c/CSforDev_L23-img-3.png)

Step 10: Click on the "Save" button to save the webhook.

Step 11: Now, whenever you publish content in Contentstack, a webhook notification will be sent to the URL you specified in step 8.

Step 12: To test the webhook, publish a new piece of content in Contentstack.

Step 13: Return to webhook.site and click on the "Inspect" button next to the webhook that you just created. You should see the webhook notification data from Contentstack, including the published content.

Congratulations! You have successfully tested a Contentstack webhook using webhook.site. You can now use webhook.site to test your webhook implementations or receive webhook notifications from other services.

## Learn More

*   [Webhooks Documentation Page](https://www.contentstack.com/docs/developers/set-up-webhooks/)
    
*   [Community Forum](https://community.contentstack.com/search?q=webhooks)

#### Key takeaways

- Connect **Webhooks** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 24 — Automate- Using an HTTP Connector to Send Data to a 3rd Party System

<!-- ai_metadata: {"lesson_id":"24","type":"text","duration_minutes":1,"topics":["Automate","Using","HTTP","Connector","Send","Data"]} -->

#### Lesson text

## Sending HTTP Messages with Automate

An [HTTP Action](https://www.contentstack.com/docs/developers/automation-hub-connectors/http-action/) allows us to send an HTTP call when a trigger event occurs. This enables us to send JSON from an _entry, asset, or release_ to any service that accepts an HTTP POST, GET, PUT, DELETE, or PATCH.  
In this module we will use an _HTTP Action connector_ to send the _entry_ JSON to an external webhook listener. This method can be used to integrate with third-party systems that do not have a pre-built connector but can receive a GET or POST request.

Topics covered:

*   Sending JSON to an external web service
    
*   Using the website http://webhook.site to receive to our HTTP message
    

Please watch the following video to see an example of sending an HTTP message with _automate:_

### **Exercise: Create a new Automation that sends an HTTP Post request to a 3rd party web service when an** _entry_ **is published**

1\. Create a new Automation using a _Contentstack_ Trigger  
2\. Add a new _action_ and use the _HTTP Connector_   
3\. Go to http://webhook.site and create a new webhook listener  
4\. In the Configure Action step, specify the URL of the webhook from above

#### Key takeaways

- Connect **Automate- Using an HTTP Connector to Send Data to a 3rd Party System** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 25 — What is Contentstack Marketplace?

<!-- ai_metadata: {"lesson_id":"25","type":"text","duration_minutes":1,"topics":["What","Contentstack","Marketplace"]} -->

#### Lesson text

The [Contentstack Marketplace](https://www.contentstack.com/docs/developers/marketplace-platform-guides/) is a platform for apps and other resources that help you extend the capabilities of our core CMS and customize its functionalities. It is a one-stop resource to discover, browse, and install tools to enhance the Contentstack experience by connecting to various third-party services in a simple installation. The [apps](https://www.contentstack.com/docs/developers/marketplace-apps/) and resources on Marketplace are created by Contentstack and our partners. 

![CSforDev\_L25-img-1.jpg](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt1039097ff817657d/67dc7dae037e2bbf2122d11f/CSforDev_L25-img-1.jpg)

Contentstack Marketplace is Contentstack’s very own app distribution platform similar to the App Store in Apple, or the Play Store in Android. You can use and install apps from our Marketplace to extend the existing capabilities of your Contentstack web application.

Marketplace Apps allow you to extend the capability of our core CMS and customize its functionalities. With these ready-to-use apps, you can integrate your favorite third-party platforms easily and with minimal effort. These pre-built apps are intended to be quickly and easily installed. Apps like this are built to solve a particular problem, help integrate with a specific software, or provide functionality for a user of Contentstack.

#### Key takeaways

- Connect **What is Contentstack Marketplace?** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 26 — Using Marketplace Apps

<!-- ai_metadata: {"lesson_id":"26","type":"text","duration_minutes":1,"topics":["Using","Marketplace","Apps"]} -->

#### Lesson text

Contentstack’s App Marketplace for Extensions is a platform where users can find and install pre-built extensions that can enhance the functionality of their Contentstack projects. These extensions are developed by Contentstack partners or third-party developers and are designed to simplify and streamline common development tasks, such as integrating with external systems, automating workflows, and adding new features to the CMS.

Here are the key features of Contentstack’s App Marketplace for Extensions:

**1\. Extension Types:** The App Marketplace offers a variety of extensions types, including field types, custom widgets, and integrations. Each extension type has a specific purpose and can be used to enhance the functionality of the CMS in different ways.  This includes Dashboard widgets, full-page apps, custom fields, sidebar widgets, rich-text field extensions and a new field modifier.

**2\. Categories:** The App Marketplace offers extensions across multiple categories, including SEO, localization, analytics, integrations, and more. These categories make it easy for users to find extensions that fit their specific needs.

**3\.** [Developer Documentation](https://www.contentstack.com/docs/developers/developer-hub/get-started-with-building-apps-using-contentstack-app-sdk/)**:** Each extension in the App Marketplace comes with detailed documentation, which provides instructions on how to install, configure, and use the extension.

**4\.  The Developer Hub** allows developers to upload their extensions to Contentstack and test them out. Additionally, developers can create private extensions for their customers and leverage the Developer Hub to make them accessible.

**5\. Submit Your Own Extension:** Developers can submit their own extensions to the App Marketplace. Contentstack reviews each extension to ensure that it meets quality standards before making it available in the marketplace.  Using the Developer Hub you can create

Overall, Contentstack’s App Marketplace for Extensions provides a centralized location for users to find and install extensions that can enhance the functionality of their Contentstack projects. With a wide range of extensions available across multiple categories, users can customize their CMS to fit their specific needs and streamline their workflows.

## Exercise: Installing and Using Apps from the Marketplace

In this module we are going to install two apps from the Marketplace that support developers using Contentstack.

1.  Developer Tools

2.  Content Type Visualizer

## **Installing Developer Tools**

Developer tools allow the developer to view the Entry JSON before it is published.  This is very helpful when building apps and looking for the structure and properties of the content type.

1.  Go to the [Marketplace dashboard](https://app.contentstack.com/#!/marketplace/apps)  ([EU Marketplace Dashboard](https://eu-app.contentstack.com/#!/marketplace/apps))

2.  Select Developer Tools, Install App, and choose the Stack of where to install it  
  
![CSforDev\_L26-img-1.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt9215ef5ffe1e57fd/67dc7e04c9b8d437d5d138c1/CSforDev_L26-img-1.png)

  

## **Installing the Content Type Visualizer**

The Content Type Visualizer is another developer-friendly extension that shows the relationships between Content Types.  It is installed on the Dashboard using the Marketplace.

1.  Go to the [Marketplace dashboard](https://app.contentstack.com/#!/marketplace/apps)  ([EU Marketplace Dashboard](https://eu-app.contentstack.com/#!/marketplace/apps))

2.  Select Content Type Visualizer, Install App, and choose the Stack of where to install it

  

![CSforDev\_L26-img-2.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta4bd50450165e8bd/67dc7e22f7eccc435b90cf28/CSforDev_L26-img-2.png)

#### Key takeaways

- Connect **Using Marketplace Apps** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 27 — Installing the NextJS Starter App with the CLI

<!-- ai_metadata: {"lesson_id":"27","type":"text","duration_minutes":1,"topics":["Installing","the","NextJS","Starter","App","with"]} -->

#### Lesson text

**Installing and Configuring the NextJS Starter App** 

**About Starter Apps**  
In Contentstack, starter apps are pre-built applications that demonstrate the capabilities of Contentstack and provide a starting point for developers learning about and building web applications.

Starter apps are designed to be fully functional, customizable, and extensible, providing developers with a set of best practices and common patterns for building web applications that consume content from Contentstack.

Starter apps in Contentstack are available for a variety of programming languages and frameworks, including NextJS, React, Angular, and Vue.js. Each starter app includes a set of pre-built content types, entries, assets, and environments.

Using starter apps in Contentstack provides several benefits, including:

*   **Rapid prototyping**: Starter apps provide a quick way to prototype and test new ideas, allowing developers to create a fully functional application in a fraction of the time it would take to build from scratch.  
    
*   **Best practices**: Starter apps are built using best practices and industry-standard patterns, providing developers with a solid foundation for building scalable, maintainable, and high-performing applications.
    
*   **Customization**: Starter apps can be fully customized to meet the specific needs of the application being developed, including branding, layout, functionality, and integrations with other systems.
    
*   **Extensibility**: Starter apps can be extended and allowing developers to add new features and functionality as needed.
    

Overall, starter apps in Contentstack provide a powerful and flexible way for developers to jumpstart their projects, reduce development time and costs, and ensure high-quality, scalable, and maintainable applications.

![CSforDev\_L27-img-1.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt3b91aaf33b63ed1a/67dc7e92c9b8d475c0d138e0/CSforDev_L27-img-1.png)

## Three ways to get started with the StarterApps

When starting to develop with Contentstack, we can install and use an existing NextJS Starter App called Logoipsum and this can be set up in several ways:  

1.  The first approach involves using an [automated bootstrap CLI script](https://www.contentstack.com/docs/developers/cli/bootstrap-starter-apps/) to generate a new Stack or load content into an existing Stack. This method includes all the default content and downloads the NextJS app. **We will be using this option for the course.**

2.  The second approach involves installing a Starter App via the Marketplace. This method is useful when you want to try using Contentstack as an Author or Editor and publish content without accessing the frontend code. However, we will not be using this approach in the course.

3.  [Manually import the content with the CLI](https://www.contentstack.com/docs/developers/sample-apps/build-a-starter-website-using-next-js-and-contentstack/#import-content) and download the [StarterApp from the Github repo](https://github.com/contentstack/contentstack-nextjs-starter-app) and manually configure the application.  This does the same thing as step 1, but requires more time.

## **Install the Starter App**

### **Create the Stack**

To get started we will need to create a new Stack in Contentstack for our NextJS Starter app.  To create our Starter App using the Contentstack CMS, we need to follow a few steps. Firstly, we need to create a new Stack and then use a CLI command to import the Starter app content and code. It is crucial to ensure that you have an Empty Stack ready for the StarterApp before proceeding. If you have the role of Organization Owner in Contentstack, then the CLI can create the Stack for you automatically using your login credentials.

**Watch the following video to explain how to install the StarterApp with the CLI**

## **What’s inside the Starter App**

  
The Starter app Stack contains all the Content Types, Entries, Assets, Environments, Tokens, and Roles for a full website.  The following video will explain the Starter app and where everything is located:

# **Architecture**

## **Big Picture Architecture Diagram**

### **Backend**

The Backend of Contentstack is the CMS with the ability to create and publish content.  **The focus here is on editor ease-of-use by providing a simple, powerful and flexible UI for content creation and management.**  In addition to the out of the box functionality, we also provide an ability to extend the interface by creating UI Extensions using our App SDK and connect to 3rd-party applications such as DAM providers, Analytics, E-Commerce platforms and more.

###   

### **Frontend**

The focus on the frontend is high-performance for your website and web application. APIs and SDKs are provided to the developer for using in their applications to perform read-only queries to the content.  The Content Delivery APIs use an internal CDN to cache all queries to the platform which results in higher performance for all your web applications.  This is also where we find the Images API for delivering image assets.

Watch this video that explains the big picture architecture:

![CSforDev\_L27-img-2.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt362bd848bfb23a87/67dc7ec73a0f389c0000e144/CSforDev_L27-img-2.png)

##   

## **Environments**

*   One Stack can publish to multiple Environments.  Think of Environments as “publish destinations”.
    
*   Each Environment has one Delivery Token, otherwise known as an Access Token.  That token is unique per Environment.
    
*   Each Stack has an API key.  There is only 1 API key per Stack and it is unique.
    
*   Most API calls will require both an API token and a Delivery / Access Token.  
    

Watch this video to understand how we use Environments in Contentstack:

The following diagram for Environments illustrates these concepts:

![CSforDev\_L27-img-3.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbae3b547ac725da5/67dc7ef1986725d043888129/CSforDev_L27-img-3.png)

  

  

### Multi-Stack Architecture Diagram  

![CSforDev\_L27-img-4.png](https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltf4b85119eb371741/67dc7f1cc5de53bfe2d2d9c0/CSforDev_L27-img-4.png)

#### Key takeaways

- Connect **Installing the NextJS Starter App with the CLI** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 28 — Helpful Resources

<!-- ai_metadata: {"lesson_id":"28","type":"text","duration_minutes":1,"topics":["Helpful","Resources"]} -->

#### Lesson text

*   [Contentstack Community](https://community.contentstack.com)
    
*   [Developer Documentation Portal](https://www.contentstack.com/docs/developers/)
    

## Helpful Documentation Links

### APIs

*   [APIs Homepage](https://www.contentstack.com/docs/developers/apis/)
    
*   [Postman Collections for APIs](https://www.contentstack.com/docs/developers/apis/postman-collections/)
    
*   [CLI](https://www.contentstack.com/docs/developers/cli/)
    
*   [JavaScript RTE Parsing Utils](https://www.contentstack.com/docs/developers/sdks/utils-sdk/javascript/get-started-with-javascript-utils-library/)
    
*   [JSON RTE Serializer - Github](https://github.com/contentstack/json-rte-serializer/)
    

### Sample Apps / Examples

*   [Sample Apps](https://www.contentstack.com/docs/developers/sample-apps/)
    
*   [Contentstack Typescript Query / API Service](https://github.com/Contentstack-Solutions/contentstack-nextjs-typescript-base/blob/main/lib/services/contentstack-service.ts)
    
*   [https://github.com/Contentstack-Solutions/contentstack-nextjs-typescript-base/blob/main/lib/services/contentstack-service.ts](https://github.com/Contentstack-Solutions/contentstack-nextjs-typescript-base/blob/main/lib/services/contentstack-service.ts)
    
*   [Contentstack Solutions Github Repo](https://github.com/Contentstack-Solutions)
    

### Live Preview

*   [Live Preview Real-world scenarios](https://www.contentstack.com/docs/content-managers/author-content/live-preview-real-world-scenarios/)
    
*   [How Live Preview Works with the SDK](https://www.contentstack.com/docs/developers/set-up-live-preview/how-live-preview-works-with-sdk/)
    
*   [Set up Live Preview](https://www.contentstack.com/docs/developers/set-up-live-preview/)

#### Key takeaways

- Connect **Helpful Resources** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

### Lesson 29 — Contentstack for Developers Quiz

<!-- ai_metadata: {"lesson_id":"29","type":"text","duration_minutes":1,"topics":["LMS","Knowledge check"]} -->

#### Lesson text

**This lesson is a knowledge check hosted in the Academy LMS.** This companion Markdown contains **no quiz questions, answers, scoring rules, or explanations**.

#### Key takeaways

- Connect **Contentstack for Developers Quiz** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

## Resources & references

| Page | Companion Markdown |
| --- | --- |
| /courses/contentstack-for-developers/what-we-ll-build | /academy/md/courses/contentstack-for-developers/what-we-ll-build.md |
| /courses/contentstack-for-developers/getting-started | /academy/md/courses/contentstack-for-developers/getting-started.md |
| /courses/contentstack-for-developers/big-picture-architecture | /academy/md/courses/contentstack-for-developers/big-picture-architecture.md |
| /courses/contentstack-for-developers/architecture-walkthrough | /academy/md/courses/contentstack-for-developers/architecture-walkthrough.md |
| /courses/contentstack-for-developers/environments-walkthrough | /academy/md/courses/contentstack-for-developers/environments-walkthrough.md |
| /courses/contentstack-for-developers/using-the-content-delivery-api | /academy/md/courses/contentstack-for-developers/using-the-content-delivery-api.md |
| /courses/contentstack-for-developers/using-the-content-delivery-api-documentation | /academy/md/courses/contentstack-for-developers/using-the-content-delivery-api-documentation.md |
| /courses/contentstack-for-developers/querying-the-content-delivery-api-with-the-documentation | /academy/md/courses/contentstack-for-developers/querying-the-content-delivery-api-with-the-documentation.md |
| /courses/contentstack-for-developers/using-the-postman-collection-to-connect-with-the-content-delivery-api | /academy/md/courses/contentstack-for-developers/using-the-postman-collection-to-connect-with-the-content-delivery-api.md |
| /courses/contentstack-for-developers/using-postman-to-query-the-contentstack-content-delivery-api-walkthrough | /academy/md/courses/contentstack-for-developers/using-postman-to-query-the-contentstack-content-delivery-api-walkthrough.md |
| /courses/contentstack-for-developers/using-the-javascript-content-delivery-sdk | /academy/md/courses/contentstack-for-developers/using-the-javascript-content-delivery-sdk.md |
| /courses/contentstack-for-developers/using-the-graphql-api-with-postman | /academy/md/courses/contentstack-for-developers/using-the-graphql-api-with-postman.md |
| /courses/contentstack-for-developers/cdn-and-caching | /academy/md/courses/contentstack-for-developers/cdn-and-caching.md |
| /courses/contentstack-for-developers/query-examples-with-the-content-delivery-api | /academy/md/courses/contentstack-for-developers/query-examples-with-the-content-delivery-api.md |
| /courses/contentstack-for-developers/using-the-images-api | /academy/md/courses/contentstack-for-developers/using-the-images-api.md |
| /courses/contentstack-for-developers/creating-the-hero-detail-page | /academy/md/courses/contentstack-for-developers/creating-the-hero-detail-page.md |
| /courses/contentstack-for-developers/creating-the-hero-gallery-page | /academy/md/courses/contentstack-for-developers/creating-the-hero-gallery-page.md |
| /courses/contentstack-for-developers/design-patterns-with-content-types | /academy/md/courses/contentstack-for-developers/design-patterns-with-content-types.md |
| /courses/contentstack-for-developers/deploying-the-starter-app-with-contentstack-launch | /academy/md/courses/contentstack-for-developers/deploying-the-starter-app-with-contentstack-launch.md |
| /courses/contentstack-for-developers/importing-content-with-the-cli-and-cma | /academy/md/courses/contentstack-for-developers/importing-content-with-the-cli-and-cma.md |
| /courses/contentstack-for-developers/working-with-roles-and-permissions | /academy/md/courses/contentstack-for-developers/working-with-roles-and-permissions.md |
| /courses/contentstack-for-developers/workflow | /academy/md/courses/contentstack-for-developers/workflow.md |
| /courses/contentstack-for-developers/webhooks | /academy/md/courses/contentstack-for-developers/webhooks.md |
| /courses/contentstack-for-developers/automate--using-an-http-connector-to-send-data-to-a-3rd-party-system | /academy/md/courses/contentstack-for-developers/automate--using-an-http-connector-to-send-data-to-a-3rd-party-system.md |
| /courses/contentstack-for-developers/what-is-contentstack-marketplace- | /academy/md/courses/contentstack-for-developers/what-is-contentstack-marketplace-.md |
| /courses/contentstack-for-developers/using-marketplace-apps | /academy/md/courses/contentstack-for-developers/using-marketplace-apps.md |
| /courses/contentstack-for-developers/installing-the-nextjs-starter-app-with-the-cli | /academy/md/courses/contentstack-for-developers/installing-the-nextjs-starter-app-with-the-cli.md |
| /courses/contentstack-for-developers/helpful-resources | /academy/md/courses/contentstack-for-developers/helpful-resources.md |
| /courses/contentstack-for-developers/quiz | /academy/md/courses/contentstack-for-developers/quiz.md |

## Supplement for indexing

### Content summary

The Contentstack Developer Onboarding Course is designed to equip learners with comprehensive knowledge on various aspects of the platform, including its architecture, APIs, SDKs, and the process of creating a NextJS web… The Contentstack Developer Onboarding Course is designed to equip learners with comprehensive knowledge on various aspects of the platform, including its architecture, APIs, SDKs, and the process of creating a NextJS web application. Download Playground Here (https://github.com/contentstack/contentstack-academy-playground) You can also install a training instance by visiting our Legacy Academy. Click the Create Training Instance (https://www.contentstack.com/academy/training-instance) button on the home page. Throughout the course, learners will receive detailed instruction on how to utilize C Topics Covered Management and Images Content Delivery API Using the Images API Creating the Hero Detail Page Creating the Hero Gallery Page Design Patterns with Content Types Deploying the Starter App with Contentstack Launch Importing Content with the CLI and CMA Working with Roles and Permissions Workflow Webhooks Automate - Using an HTTP Connector to Send Data to a 3rd Party System What is the Contentstack Apps Marketplace? Using Marketplace Apps Installing the NextJS Starter App with the CLI Helpful Developer Resources Objectives Objectives for the Contentstack Developer Onboarding Course:

### Retrieval tags

- contentstack
- cms
- composable
- headless cms
- learn contentstack
- contentstack-for-developers
- What
- Build
- Getting
- Started
- Big
- Picture
- Architecture
- Walkthrough

### Indexing notes

Chunk at each "### Lesson NN — Title" heading; copy lesson_id and topics from the preceding HTML comment into chunk metadata for RAG filters.
Course slug: contentstack-for-developers. Union of lesson topic tokens: What, Build, Getting, Started, Big, Picture, Architecture, Walkthrough, Environments, Using, the, Content, Delivery, API, documentation, Querying, with, Postman, collection, connect, query, Contentstack, JavaScript, SDK, GraphQL, CDN, and, Caching, Query, Examples, Images, Creating, Hero, Detail, Page, Gallery, Design, Patterns, Types, Deploying, Starter, App, Importing, CLI, Working, Roles, Permissions, Workflow, Webhooks, Automate, HTTP, Connector, Send, Data, Marketplace, Apps, Installing, NextJS, Helpful, Resources, for, Developers, Quiz.
Do not embed or retrieve LMS-only quiz items or mastery exam answer keys from this export.

### Asset references

| Label | URL |
| --- | --- |
| composable-heros.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltd51a0c5b982c72f8/664c027a1983ea9d6dac29b4/composable-heros.png` |
| composable-heros-detail.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltcba8639d82e39f82/664c02a3785339639e9e3d9f/composable-heros-detail.png` |
| rename-sample.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltb3b6b76e3ee547ed/664c033cc9024cafa4ad58b4/rename-sample.png` |
| Video thumbnail: Getting Started | `https://cdn.jwplayer.com/v2/media/HoLoBca0/poster.jpg?width=720` |
| Architecture.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt40df19fbdfa691c4/664c7d55a671fa7891f218bf/Architecture.png` |
| environment.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta9f0e57d8a3c5a6e/664c7d9f79abee8ebd3d1534/environment.png` |
| multi-stack.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltd1dd48a1fcbec491/664c7de28a66292552b1397b/multi-stack.png` |
| Video thumbnail: Architecture Walkthrough | `https://cdn.jwplayer.com/v2/media/gu1hi4sL/poster.jpg?width=720` |
| Video thumbnail: Environments Walkthrough | `https://cdn.jwplayer.com/v2/media/xDslMX1l/poster.jpg?width=720` |
| API-map.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbeecb6f7ab8cf28a/664d437c785339c0e89e4f8e/API-map.png` |
| Video thumbnail: Querying the Content Delivery API with the Documentation Walkthrough | `https://cdn.jwplayer.com/v2/media/HTAyw81A/poster.jpg?width=720` |
| Video thumbnail: Using Postman to query the Contentstack Content Delivery API Walkthrough | `https://cdn.jwplayer.com/v2/media/693igszM/poster.jpg?width=720` |
| content-sdk.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt31c71c762d48a421/664d45aa79abeeeb093d23a5/content-sdk.png` |
| graphQL.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt720a9df15d2b3c95/664d46208a0182e22014ca07/graphQL.png` |
| CSforDev\_L15\_Response200.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt5b227000df104193/67dc54ed4a89c32ebfa2f78a/CSforDev_L15_Response200.png` |
| CSforDev\_L15\_AutoOptimize.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta7976efcf6431992/67dc5524460eb47ea2946bed/CSforDev_L15_AutoOptimize.png` |
| CSforDev\_L15\_ImagesAPI.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt7e849a1eb5110a73/67dc5540f7eccc98ca90cc79/CSforDev_L15_ImagesAPI.png` |
| CSforDev\_L15\_ImagesAPIresize.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt2cbba66331047777/67dc5553443bd63ff1f1bec6/CSforDev_L15_ImagesAPIresize.png` |
| CSforDev\_L16\_PageDesign\_1.jpg | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt2c5939936d2d2857/67dc6a95b1a1f33f473eeed0/CSforDev_L16_PageDesign_1.jpg` |
| CSforDev\_L16\_PageDesign\_2.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt2c4e42a167b5a160/67dc6adc1bae684bc54c6ad2/CSforDev_L16_PageDesign_2.png` |
| CSforDev\_L16\_ContentTypeCheck.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt781d0a90b92e2c67/67dc6adb0c6f5510a31fc463/CSforDev_L16_ContentTypeCheck.png` |
| CSforDev\_L16\_URLproperties.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt0e9a7e511c89f116/67dc6adb5e486d1a4671aa9f/CSforDev_L16_URLproperties.png` |
| CSforDev\_L16\_ImageFile.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt36199e9adb11c8e3/67dc6adb17f7b418a20cf683/CSforDev_L16_ImageFile.png` |
| CSforDev\_L16\_Description.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blte8860a9727500de8/67dc6adbf7eccc35bd90ce1a/CSforDev_L16_Description.png` |
| CSforDev\_L16\_Powers.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltc8a96a22c1247f99/67dc6adb8fee9a228447d640/CSforDev_L16_Powers.png` |
| CSforDev\_L16\_SEO.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt2a67ac182732261b/67dc6adb4a89c32df8a2f912/CSforDev_L16_SEO.png` |
| CSforDev\_L16\_ExamineHelper.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltfe79f5ee8485bddd/67dc6adbc566ee159b5df64c/CSforDev_L16_ExamineHelper.png` |
| CSforDev\_L16\_CharacterQuery.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt5330eb37dbb29171/67dc6adbdb243f203c12b94c/CSforDev_L16_CharacterQuery.png` |
| CSforDev\_L16\_RenderImage.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbe51c92c1ac561c8/67dc6adbc5b83e51fa924181/CSforDev_L16_RenderImage.png` |
| CSforDev\_L16\_RenderField.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta737586dbcea3b4a/67dc6adb983a658c2e3b71db/CSforDev_L16_RenderField.png` |
| CSforDev\_L16\_FinalResult.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt9e10f8c799a48670/67dc6adc5e486d1eed71aaa3/CSforDev_L16_FinalResult.png` |
| CSforDev\_L17\_ComposableHeroes.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt36760c2226f23188/67dc74d1443bd6f8bef1c126/CSforDev_L17_ComposableHeroes.png` |
| CSforDev\_L17-HeroGalleryPageContentType.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltca3a395e8b43a268/67dc74d25e486ddf7571ab5f/CSforDev_L17-HeroGalleryPageContentType.png` |
| CSforDev\_L17-SuperHeroGalleryPage.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt5d634d5af8ed1ef2/67dc74d120a3dc7d26f81da5/CSforDev_L17-SuperHeroGalleryPage.png` |
| CSforDev\_L17-ReviewComposableHeroesGalleryEntry.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta1719b3c553d3aa7/67dc74d28fee9af26547d6d2/CSforDev_L17-ReviewComposableHeroesGalleryEntry.png` |
| CSforDev\_L17-NextJSappOpenComposableHeroes.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt987109e80668c33d/67dc74d2c566ee77065df700/CSforDev_L17-NextJSappOpenComposableHeroes.png` |
| CSforDev\_L17-Postman1.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltfc54a08558f3257d/67dc74d20c6f5573391fc550/CSforDev_L17-Postman1.png` |
| CSforDev\_L17-ComposableLandingPage.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt20cf9dbe38b2ce7a/67dc74d2dd73e3150dbf2aca/CSforDev_L17-ComposableLandingPage.png` |
| CSforDev\_L17-OpenSyperheroLandingPage.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbd496f6c2aa7c3fb/67dc74d1632b938d87d497f4/CSforDev_L17-OpenSyperheroLandingPage.png` |
| CSforDev\_L17-OpenContentTypeDefinition.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltcb805c91070decc1/67dc74d18fee9a015647d6ce/CSforDev_L17-OpenContentTypeDefinition.png` |
| CSforDev\_L17-GlobalFieldDefinitions.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt133ae7c39bec81dd/67dc74d1782bfb40816f4d07/CSforDev_L17-GlobalFieldDefinitions.png` |
| CSforDev\_L17-CodeForGalleryEntry.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt32ad6ea1b6068a60/67dc74d16f68587885fd9e35/CSforDev_L17-CodeForGalleryEntry.png` |
| CSforDev\_L17-BlockRenderwithNextJScomp.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt6997b78ab65f5110/67dc74d1bbf93ef9c3586444/CSforDev_L17-BlockRenderwithNextJScomp.png` |
| CSforDev\_L17-HeroBannerBlock.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt57deb882be0262c1/67dc74d1db243fda9112b9df/CSforDev_L17-HeroBannerBlock.png` |
| CSforDev\_L18-ExampleModularBlocks.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt163b2eba984ba5dd/67dc77d9dd73e3394ebf2b15/CSforDev_L18-ExampleModularBlocks.png` |
| CSforDev\_L18-BlocksUsedInPageComponent.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltc596ad6019f6b557/67dc77d9c5b83e1789924263/CSforDev_L18-BlocksUsedInPageComponent.png` |
| CSforDev\_L18-GlobalFields\_3.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbfba1754f824d5ea/67dc77d96f6858cde5fd9e68/CSforDev_L18-GlobalFields_3.png` |
| CSforDev\_L18-SEO\_4.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt868c68695563b3bd/67dc77d9a6d88e2e87052b51/CSforDev_L18-SEO_4.png` |
| CSforDev\_L19-img\_1.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt59869ec9f872a769/67dc7979632b93a52ad4983e/CSforDev_L19-img_1.png` |
| CSforDev\_L19-img\_2.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt803195694348711a/67dc79af983a650b893b72f7/CSforDev_L19-img_2.png` |
| CSforDev\_L19-img\_3.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt91248dc45e8c64c4/67dc79e5314d6788311b6674/CSforDev_L19-img_3.png` |
| CSforDev\_L19-img\_4.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt9de2eeb19d27402b/67dc7a13dd73e3fed6bf2b3b/CSforDev_L19-img_4.png` |
| CSforDev\_L20-img-1.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltf68a0bfc44851c8f/67dc7a8d5e486d622a71ac32/CSforDev_L20-img-1.png` |
| CSforDev\_L20-img-2.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltc549d1dc354f62fb/67dc7aab983a655a2b3b7306/CSforDev_L20-img-2.png` |
| CSforDev\_L20-img-3.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt3031a286be14c33e/67dc7af4a71458f9d3b9ac8d/CSforDev_L20-img-3.png` |
| CSforDev\_L20-img-4.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltf85b2c24d02d5273/67dc7b2437e25afefd1e3cac/CSforDev_L20-img-4.png` |
| CSforDev\_L20-img-5.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltdf993e1837922ae0/67dc7b8ec566ee36ce5df792/CSforDev_L20-img-5.png` |
| CSforDev\_L20-img-6.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt125b7f4295bb35a9/67dc7bbd632b932162d49860/CSforDev_L20-img-6.png` |
| CSforDev\_L20-img-7.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt1b91f0972f174299/67dc7be7a714580b08b9ac9c/CSforDev_L20-img-7.png` |
| CSforDev\_L20-img-8.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt029257333658a4ea/67dc7c0d2d0b98a5affcfe07/CSforDev_L20-img-8.png` |
| CSforDev\_L22-img-1.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt655072dfe47556f8/67dc7c8f17f7b4421c0cf7cd/CSforDev_L22-img-1.png` |
| CSforDev\_L23-img-1.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt9928fe7cfbd4a917/67dc7ce545b2290ec4910d8c/CSforDev_L23-img-1.png` |
| CSforDev\_L23-img-2.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt40127c0aeeac44ff/67dc7d088fee9a424247d751/CSforDev_L23-img-2.png` |
| CSforDev\_L23-img-3.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltaa1169f852f5c558/67dc7d3220a3dc0ca6f81e2c/CSforDev_L23-img-3.png` |
| CSforDev\_L25-img-1.jpg | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt1039097ff817657d/67dc7dae037e2bbf2122d11f/CSforDev_L25-img-1.jpg` |
| CSforDev\_L26-img-1.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt9215ef5ffe1e57fd/67dc7e04c9b8d437d5d138c1/CSforDev_L26-img-1.png` |
| CSforDev\_L26-img-2.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta4bd50450165e8bd/67dc7e22f7eccc435b90cf28/CSforDev_L26-img-2.png` |
| CSforDev\_L27-img-1.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt3b91aaf33b63ed1a/67dc7e92c9b8d475c0d138e0/CSforDev_L27-img-1.png` |
| CSforDev\_L27-img-2.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt362bd848bfb23a87/67dc7ec73a0f389c0000e144/CSforDev_L27-img-2.png` |
| CSforDev\_L27-img-3.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbae3b547ac725da5/67dc7ef1986725d043888129/CSforDev_L27-img-3.png` |
| CSforDev\_L27-img-4.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltf4b85119eb371741/67dc7f1cc5de53bfe2d2d9c0/CSforDev_L27-img-4.png` |

### External links

| Label | URL |
| --- | --- |
| Contentstack Academy home | `https://www.contentstack.com/academy/` |
| Training instance setup | `https://www.contentstack.com/academy/training-instance` |
| Academy playground (GitHub) | `https://github.com/contentstack/contentstack-academy-playground` |
| Contentstack documentation | `https://www.contentstack.com/docs/` |
| composable-heros.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltd51a0c5b982c72f8/664c027a1983ea9d6dac29b4/composable-heros.png` |
| composable-heros-detail.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltcba8639d82e39f82/664c02a3785339639e9e3d9f/composable-heros-detail.png` |
| rename-sample.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltb3b6b76e3ee547ed/664c033cc9024cafa4ad58b4/rename-sample.png` |
| Architecture.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt40df19fbdfa691c4/664c7d55a671fa7891f218bf/Architecture.png` |
| environment.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blta9f0e57d8a3c5a6e/664c7d9f79abee8ebd3d1534/environment.png` |
| multi-stack.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltd1dd48a1fcbec491/664c7de28a66292552b1397b/multi-stack.png` |
| Content Delivery API Documentation | `https://www.contentstack.com/docs/developers/apis/content-delivery-api/` |
| API-map.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/bltbeecb6f7ab8cf28a/664d437c785339c0e89e4f8e/API-map.png` |
| Get Entries | `https://www.contentstack.com/docs/developers/apis/content-delivery-api/#get-all-entries` |
| CDA Postman guide | `https://www.contentstack.com/docs/developers/apis/content-delivery-api/#postman-collection` |
| Download and install Postman | `https://www.postman.com/downloads/` |
| Download the Contentstack Postman Content Delivery collection | `https://www.contentstack.com/docs/developers/apis/postman-collections` |
| create a new Delivery Token | `https://www.contentstack.com/docs/developers/create-tokens/create-a-delivery-token/` |
| Additional information about tokens, including Delivery Tokens, can be found in our documentation | `https://www.contentstack.com/docs/developers/create-tokens/#work-with-delivery-tokens` |
| Javascript SDK on Github | `https://github.com/contentstack/contentstack-javascript` |
| Javascript API Reference | `https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/javascript-browser/reference/` |
| All SDKs | `https://www.contentstack.com/docs/developers/sdks/` |
| Query examples | `https://www.contentstack.com/docs/developers/web-framework/querying/` |
| content-sdk.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt31c71c762d48a421/664d45aa79abeeeb093d23a5/content-sdk.png` |
| graphQL.png | `https://images.contentstack.io/v3/assets/bltebc53cfaf0dd6403/blt720a9df15d2b3c95/664d46208a0182e22014ca07/graphQL.png` |
| Apollo Client JavaScript SDK | `https://www.contentstack.com/docs/developers/graphql-api/use-the-graphql-queries-with-apollo-sdks/use-graphql-queries-with-apollo-client-javascript-sdk/` |
