# How to connect content data to front-end components

Once you have a component library, the next step of building a headless platform is connecting your content models to your front-end components. Your website will probably have templated and non-templated pages. &#x20;

The process for building a templated page is relatively straightforward. Dynamically building a non-templated page is more complex as page content and layout will vary, depending on what the content author has selected.&#x20;

## Templated pages&#x20;

Authors will see pre-defined content fields when composing a templated page. They won't be able to reorder components or otherwise modify the layout of the page.&#x20;

Let's take a blog post as an example. Users can input the title, date, summary, and body of the blog post.&#x20;

<figure><img src="https://882838265-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq7UE1cAwz12WuyrFSyXF%2Fuploads%2FeXPZZQOTS8er5cZP93Nq%2Fblog3.png?alt=media&#x26;token=514106ab-2f3f-4b31-9ffa-8e2ae2d26a39" alt="" width="514"><figcaption><p>A templated page has pre-specified content fields and the page layout is hard-coded. Authors can't reorder components or add different fields.</p></figcaption></figure>

Sanity would return a JSON object that looks like this:

{% code overflow="wrap" %}

```javascript
{
  "blogTitle": "Headless CMS essentials: Live Preview, featuring Sanity.io",
  "content": 
  "publishDate": "2023-03-22",
  "slug": "headless-live-preview",
  "summary": "By using a live preview in your headless CMS, content authors can have the best of both worlds: a familiar, visual editing experience combined with improved performance, flexibility, and scalability.",
  //... additonal fields have been omitted for brevity
}
```

{% endcode %}

To generate the blog post as a page, you need to map the JSON fields to the right components and map the keys from the JSON file to the appropriate place in the page template.&#x20;

```jsx
const BlogPost = ({ data }) => {

  const {
    blogTitle,
    content,
    publishDate,
    summary,
  } = data.page

  return (
    <StyledBlogPostPage>
      <StyledArticle>
        <StyledReadTime>
          {publishDate}
        </StyledReadTime>
        <h1>{blogTitle}</h1>
        <StyledSummary>
          <p>{summary}</p>
        </StyledSummary>
        <article>{content}</article>
      </StyledArticle>
    </StyledBlogPostPage>
  )
}
```

The result is a static HTML file of our blog post page.

<figure><img src="https://882838265-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq7UE1cAwz12WuyrFSyXF%2Fuploads%2FYcqTWAGFoDMkb5mfo8Si%2Fimage.png?alt=media&#x26;token=6b3350fb-339c-4465-91af-300f6cec9ab7" alt="" width="375"><figcaption></figcaption></figure>

## Non-templated pages

Authors can choose from a selection of components and page modules when composing a non-templated page. They can add and move content around and change the page layout.&#x20;

To build a non-templated page, we need to dynamically connect the JSON data from the CMS to our front-end components. The magic is in a single function we call **`buildComponent`**.&#x20;

You'll likely see different implementations across various frameworks and starter repos. We'll walk through our general approach by explaining how we can do this in Next.js.

### How to use `buildComponent` in Next.js

Let's look at this example JSON containing CMS content data:

{% code title="Sample JSON from CMS" overflow="wrap" %}

```json
{
  "_key": "6288f6544a9e",
  "_type": "Quote", // Content model name should match component name
  // Content model fields should match props in components:
  "attribution": "Lance Martel, CIO, Staples Canada",
  "quotation": "Rangle gave us permission to prioritize the customer because true innovation is anchored by the customer…and how we drive better experiences for them."
}
```

{% endcode %}

Import all the components you need to dynamically build a given page. These should be your **CMS module** components from your component library.

{% code title="buildComponent.jsx" %}

```jsx
import {
  Accordion,
  Footer,
  GalleryCarousel,
  HeroBanner,
  Quote,
  // ... all other components
} from '../component-library'
```

{% endcode %}

Map the content models in your CMS to the front-end components in your component library.&#x20;

{% hint style="success" %}
**Name your content models and components so their field names and prop names match, respectively.**&#x20;

This is critical for matching content data from your CMS to the appropriate components in your component library, to dynamically generate a non-templated page.
{% endhint %}

If the name of a content model in your JSON doesn't match the name of its corresponding component, you'll need to explicitly define a map object to pair the names of your content model and component.

{% code title="buildComponent.jsx" overflow="wrap" %}

```jsx
const componentsMap = {
  Accordion,
  Footer,
  GalleryCarousel,
  MainHero: HeroBanner, // explicitly map content models to components if their names don't match
  Quote,
  // ... all other components
}

const componentSelector = (componentType) => {
  return components[componentType]
}
```

{% endcode %}

Pass the component names and props from the CMS to generate the dynamic component.

{% code title="buildComponent.jsx" overflow="wrap" lineNumbers="true" %}

```jsx
export const buildComponent = ({_type, ...props}) => {
  if (!_type) {
    throw new Error('Object does not have a '_type' property')
  }

  const Component = componentsMap[_type]
  if (!Component) {
    throw new Error(`No component is registered for type:'${_type}`)
  }
  return <Component {...props} />
}
```

{% endcode %}

When we put everything together, `buildComponent.jsx` looks like this:

{% code title="buildComponent.jsx" overflow="wrap" lineNumbers="true" %}

```jsx
import {
  Accordion,
  Footer,
  GalleryCarousel,
  HeroBanner,
  Quote,
} from '../component-library'

const componentsMap = {
  Accordion,
  Footer,
  GalleryCarousel,
  HeroBanner,
  Quote,
}

const componentSelector = (componentType) => {
  return components[componentType]
}

export const buildComponent = ({_type, ...props}) => {
  if (!_type) {
    throw new Error('Object does not have a '_type' property')
  }

  const Component = componentsMap[_type]
  if (!Component) {
    throw new Error(`No component is registered for type:'${_type}`)
  }
  return <Component {...props} />
}
```

{% endcode %}

You can now use this function whenever you need to dynamically create components on a page template.&#x20;

<pre class="language-jsx" data-title="[...slug].jsx" data-overflow="wrap" data-line-numbers><code class="lang-jsx"><strong>import { buildComponent } from '../util/buildComponent.jsx'
</strong><strong>
</strong><strong>const Page = ({ data }) => {
</strong>  const { modules } = data.page
  return (
    &#x3C;div>
      {modules.map(module => buildComponent(module))}
    &#x3C;/div>
  )
}
</code></pre>
