# How to Define an Arc XP Content Source

Source: https://dev.arcxp.com/pagebuilder-engine/how-to-guides/components-and-content/how-to-define-an-arc-xp-content-source/

Now that you’ve seen a generic content source, let’s take a quick look at the special capabilities built into PageBuilder Engine for authenticating specifically against an Arc XP content source.

## Special Environment Variables
  
### `CONTENT_BASE`

Oftentimes, you will have multiple content sources that all share the same base domain. For example, if you are querying Arc XP’s Content API, you may have a domain like `https://api.client-name.arcpublishing.com` that many of your content sources share. For this reason, PageBuilder Engine allows you to define special `CONTENT_BASE` environment variable that, when present, allows your `resolve` function to return a URL “path” rather than a fully qualified URL, and prefixes the `CONTENT_BASE` before those paths.

### `ARC_ACCESS_TOKEN`

If you’ve tried to access any of the Arc XP APIs directly, you’ve probably discovered that a simple GET request by itself won’t work. Retrieving data from the Arc APIs requires authentication, most commonly through the use of access tokens. For that reason, PageBuilder PageBuilder Engine provides a special environment variable `ARC_ACCESS_TOKEN` reserved specifically for using these access tokens. When used in conjunction with `CONTENT_BASE`, this enables content fetching from Arc XP Content API and other sources with as little friction as possible.

Both of these variables will be _automatically_ set for you in deployed sandbox and production environments. However, to get up and running, you’ll need to include them in your local development environment.

## Configuring variables for local development

When developing locally, you’ll need to set both variables in your `.env` file, as we’ve \[seen previously\](how-to-use-environment-variables-and—secrets-.html “How To Use Environment Variables and “Secrets"").

These variables _should not_ be stored in your environment secrets, as they should not be deployed.

`CONTENT_BASE` will normally look something like this: `https://api.sandbox.thepost.arcpublishing.com`, where `thepost` is replaced with the name of your organization. This determines which environment (for example, sandbox or production) your local PageBuilder Engine will pull data from.

`ARC_ACCESS_TOKEN` will be your personal Arc XP access token, which you can provision by going to Developer Center within Arc XP. Note that this _must_ be generated from the same environment you specified in `CONTENT_BASE`. For example, if you use a sandbox `CONTENT_BASE` like `https://api.sandbox.thepost.arcpublishing.com/`, you should provision your access token from the sandbox version of Developer Center.

Once you have obtained both values, you should add both to your local `.env` file. An example file might look like:

/.env

```
CONTENT_BASE=https://api.sandbox.thepost.arcpublishing.com
ARC_ACCESS_TOKEN=OL1A6U9BPL82SVDPTO6HGP5GUVMUTQR3wltBydEMBqJxkvxsB8ld2RksnP8+AvNKuPHh1ecC
```

> **Note:**
> 
> The above values for `CONTENT_BASE` and `ARC_ACCESS_TOKEN` are not real, and will not work.

## Defining Arc content sources through `resolve`

Let’s say I have my `CONTENT_BASE` environment variable set to the values above, and I want to define a content source for “stories” on the `api.client-name.arcpublishing.com` domain. In that case, my `resolve` function might look like this:

```js
const resolve = function resolve (query) {
  const website = query['arc-site']
  const requestUri = `/content/v4/stories/?website=${website}&website_url=${query.website_url || query.uri}`

  return (query.hasOwnProperty('published'))
    ? `${requestUri}&published=${query.published}`
    : requestUri
}
```

As you can see, the `requestUri` string that we return in this case is not a fully qualified URL, but instead just a path (denoted by the starting `/` character). In this case, PageBuilder Engine will see that this string is not a full URL and will prefix this path with the value of the `CONTENT_BASE` variable before making its request - so we don’t have to retype the domain in every content source that shares this domain. On top of that, the `ARC_ACCESS_TOKEN` has also been added in the appropriate HTTP header to the request. Once everything is configured, `resolve` content sources will Just Work.

There is nothing preventing you from still returning fully qualified URLs from other content sources - using `CONTENT_BASE` is purely to keep your code DRY.

## Defining Arc XP content sources through `fetch`

Things are a little different once we get to `fetch` content sources. Since `fetch` content sources allow you to manage the requests yourself, you must inject `CONTENT_BASE` and `ARC_ACCESS_TOKEN` at the appropriate places.

You can import the variables into your content source with:

```js
import { CONTENT_BASE, ARC_ACCESS_TOKEN } from 'fusion:environment'
```

You’ll also need to append `CONTENT_SOURCE` to the request URI and attach the `ARC_ACCESS_TOKEN` as a bearer authentication token.

```js
import axios from 'axios'
import { CONTENT_BASE, ARC_ACCESS_TOKEN } from 'fusion:environment'

// Add other required fields here which are not present above
const includedFields = [
  'website_url',
  'headlines.basic',
  'credits.by',
  'display_date'
].join()

const fetch = (query) => {
  const website = query['arc-site']
  return axios(`${CONTENT_BASE}/content/v4/search/published?website=${website}&q=*&_sourceInclude=${includedFields}`, {
    headers: {
      Authorization: ARC_ACCESS_TOKEN
    }
  }).then((content) => {
      return content
  }).catch((e) => {
      // Never return Axios exception object, that may contain sensitive information that can be exposed in the logs
      throw new Error("API fetch error")
  })
}

export default {
  fetch,
  params: {}
}
```

## In sandbox, production, and other non-local environments

Special environment variables such as `CONTENT_BASE` and `ARC_ACCESS_TOKEN` will be set automatically for all deployments in the PageBuilder Deployer. Your content source code will work exactly the same, and no special configuration is necessary.

## Presenting ANS content in your features

Arc XP content is stored in Arc XP Native Specification (ANS) format. When you work with Arc XP Content APIs, you receive ANS objects that include different content\_element types. Your features are responsible for rendering those elements in reader-facing experiences. This requires a clear understanding of each element type and how it should be displayed safely in the browser.

While many ANS elements are predictable, such as text, images, or lists, ANS can also contain raw HTML. This can come from raw\_html blocks created in Composer, from power-ups, or from past imports and integrations. If you render this HTML using mechanisms like dangerouslySetInnerHTML, you are explicitly trusting the stored content. That content may include unexpected or harmful markup.

Customers are responsible for knowing what content exists in their organization and how it was created. This includes legacy content, third-party integrations, and any system that can write HTML into ANS fields. Before rendering HTML directly, you should validate the source, understand who controls it, and decide whether additional sanitization is required. Arc XP does not filter or rewrite HTML at render time. The safety of reader-facing output is owned by the implementation.

## Handling redirects

If you are using the fetch method implementation in your content sources, you have to handle redirects. See [Handling redirects in content sources](https://dev.arcxp.com/pagebuilder-engine/developer-docs/handling-redirects-in-content-sources/).

## Learn More

For complete details on how access tokens work, see [Accessing Arc XP APIs](https://dev.arcxp.com/api/accessing-arcxp-apis).

For a complete reference on content sources, see the [Content Source API Reference](https://dev.arcxp.com/pagebuilder-engine/developer-docs/content-source-api/).
