# Understanding Arc XP Native Specification (ANS)

Source: https://dev.arcxp.com/concepts/content-model-ans/understanding-arc-native-specification-ans/

Core concepts and architecture of Arc XP's content model specification

Purpose 

Learn the fundamentals of Arc XP’s standardized content model

Audience 

Developers working with Arc XP content programmatically

## What is ANS?

The Arc XP Native Specification (ANS) is Arc XP’s foundational content model that standardizes how content is structured, stored, and distributed across the platform. ANS is a JSON-based blueprint that represents all content within the Arc XP ecosystem.

See the latest version of the ANS:   
  
[ ANS Schema GitHub repository ](https://github.com/washingtonpost/ans-schema) 

### Key Benefits

ANS provides the following key benefits in the Arc XP ecosystem:

- Standardized representation of multiple content types (articles, images, videos)
- Consistent metadata structure across the platform
- Flexible content transformation and delivery
- Seamless integration between Arc XP components
- Robust content syndication and distribution support

## Document Types

ANS documents comprise two main categories: **Primary Documents** and **Secondary Documents**. The following section provides an overview of each category.

### Primary Documents

Primary documents are top-level documents containing other ANS documents within their properties. Primary documents include:

- Stories (articles)
- Galleries
- Videos

### Secondary Documents

Secondary documents are embedded as properties within primary documents. Secondary documents include:

- Images
- Authors
- Sections
- Collections
- Document Redirect (1)
- Tags (2)
- Distributors (2)
- Geographic Restrictions (2)

> **Note:**
> 
> (1) Supports a primary document but child objects are not written in the parent’s ANS. Document redirects are not the same as what is in a story’s `related_content.redirect` ANS field; this field stores a story’s forward redirect URL.
> 
> (2) When supporting a primary document, information about this kind of Arc XP object uses a unique syntax, different from the reference syntax of the others.

## Architecture

Arc XP Systems and ANS interact through **APIs and Services** and **Content Pipelines**.

### APIs and Services

Arc XP APIs are designed to accept JSON data that adheres to the ANS schema. These APIs create objects that Arc XP applications can access and manipulate. Essentially, ANS serves as the language through which content is defined and managed within the Arc XP ecosystem, and integrates with various components through different APIs:

| COMPONENT   | ROLE                                        |
| ----------- | ------------------------------------------- |
| Content API | Provides normalized access to ANS documents |
| Draft API   | Manages content creation and updates        |
| Photo API   | Handles image-specific operations           |
| Video API   | Manages video content                       |
| Author API  | Controls author profiles                    |

### Content Pipeline

The content pipeline in the Arc XP ecosystem consists of the following phases:

1. **Creation**:  
a. Creators author and upload content in Composer, Photo Center, or Video Center  
b. Backend creates and stores the ANS documents  
c. Backend resolves references
2. **Processing**: The backend does the following:  
a. Validates content against the schema  
b. Manages references  
c. Updates cache
3. **Delivery**: PageBuilder does the following:  
a. Resolves content sources  
b. Transforms content  
c. Optimizes cache

To illustrate, let’s consider an article, termed as a story in ANS. This story comprises of text paragraphs, an embedded image, and an author.

![Story in ANS](https://dev.arcxp.com/images/content/ans-story.png)

The following JSON provides a simplified view of the story in its ANS format. Some of the metadata has been excluded for readability.

```json
{
  "_id": "GT68FH2GYMZCMDCIYWMPITIDUB5",
  "canonical_website": "arcxpsite",
  "content_elements": [
    {
      "_id": "PY4FH2GYMZCMDCIYWMPITICVA4",
      "content": "Beginning in late July or early August of 2024,...",
      "type": "text"
    },
    {
      "_id": "LGANVKR4NFHKTFLEND7BJHEACE",
      "content": "For years, the Mount Blue Sky Scenic Byway...",
      "type": "text"
    },
    {
      "referent": {
        "id": "MUMQSJXQFRE3HAKLMTK3T3R4QU",
        "type": "image",
        "referent_properties": {
          "subtitle": "Colorado's Front Range"
        }
      },
      "type": "reference",
      "_id”: “MUMQSJXQFRE3HAKLMTK3T3R4QU"
    },
    {
      "_id": "BA3ELFFQUVC65LVVAKSS35HWXM",
      "content": "The main focus of the project...",
      "type": "text"
    }
  ],
  "credits": {
    "by": [
      {
        "referent": {
          "id": "brianpreece",
          "type": "author"
        },
        "type": "reference"
      }
    ]
  },
  "headlines": {
    "basic": "Iconic Mountain-Top Highway is About to Close for 2 Years"
  },
  "type": "story",
  "version": "0.10.10"
}
```

## Data Representation

### Normalized ANS

Normalized ANS writes the composited objects into the JSON properties using a reference syntax shorthand. It is called reference syntax because the JSON that represents the composited object contains a key of `type: reference` with the `id` and `type` of the target object.

A normalized document is used to process standard create and update operations and mirrors the most recently saved state of a single document by a creator. It contains only the essential properties needed to describe the content.

- Uses reference syntax shorthand for embedded objects
- Contains essential properties only
- Reduces redundancy
- Improves performance
- Used for `create` and `update` operations
- Represents the latest saved state

![Normalized ANS](https://dev.arcxp.com/images/content/normalized_ans.jpeg)

The left side shows an author written into the `credits.by` field as a reference in a parent object. On the right, the same `credits.by` field is denormalized when the Content API returns the parent object.

### Denormalized ANS

A denormalized document contains the complete content body as intended for consumer viewing. The content retrieved from Arc XP undergoes a process where references are substituted with the complete representation of the composited objects, which results in denormalized ANS.

- Contains complete, expanded (inflated) content
- Replaces references with full object details
- Used in view layers: Browsers, apps, and feeds
- Includes all child objects in their full form

## Elements

### Core Elements

Every ANS document includes the following fundamental elements or properties:

```json
{
   "_id": "unique-identifier",
   "type": "content-type",
   "version": "ans-version",
   "headlines": {
     "basic": "Main headline"
   },
   "content_elements": [],
   "credits": {},
   "taxonomy": {},
   "additional_properties": {}
}
```

> **Note:**
> 
> The exact structure varies by content type, but all documents share these basic building blocks.

### Content Elements

The `content_elements` array is the primary method for expressing content structure in stories. The sequence of content elements reflects the logical order of content within a story, dictating what the consuming application should see and in what order.

The following snippet exemplifies text and image elements inside the `content_elements` array.

```json
{
  "content_elements": [
    {
      "type": "text",
      "content": "Article text here..."
    },
    {
      "type": "image",
      "referent": {
        "id": "IMAGE_ID",
        "type": "image"
      }
    }
  ]
}
```

> **Content elements recap:**
> 
> - Maintain strict ordering
> - Support multiple types such as, text, images, videos
> - Allow custom element types
> - Define the consumer-facing content sequence

### Rendering Content Elements Safely

When rendering ANS content elements in your reader-facing site (i.e: PageBuilder Features), handle each type according to its expected content:

| Type      | Expected Content | Rendering Guidance                                                    |
| --------- | ---------------- | --------------------------------------------------------------------- |
| text      | Plain text only  | **Strip HTML** before rendering. Never use dangerouslySetInnerHTML.   |
| raw\_html | Intentional HTML | Safe to render as HTML. This is the designated type for HTML content. |
| image     | Image reference  | Render as image element.                                              |
| video     | Video reference  | Render as video player.                                               |
| list      | Structured list  | Render as list; sanitize any text within list items.                  |
| header    | Heading text     | Strip HTML; render as heading element.                                |
| quote     | Quote content    | Strip HTML from text fields.                                          |

> **XSS vulnerability risk:**
> 
> Arc XP does not sanitize content at ingest, read or render time. Content imported from legacy systems, third-party integrations, or migrations may contain unexpected HTML in `text` fields. If you render such content using `dangerouslySetInnerHTML`, you expose your site to persistent XSS vulnerabilities. Always sanitize or strip HTML from non-`raw_html` content elements.

For implementation details in PageBuilder, see [Presenting ANS content in your features](https://dev.arcxp.com/pagebuilder-engine/developer-docs/how-to-define-an-arc-xp-content-source/#presenting-ans-content-in-your-features).

### Reference System

ANS uses a reference system to manage relationships between documents. The following snippet exemplifies a reference content type:

```json
{
  "type": "reference",
  "referent": {
    "id": "UNIQUE_ID",
    "type": "image",
    "referent_properties": {
      "caption": "Custom caption for this usage"
    }
  }
}
```

> **Note:**
> 
> Each document supports a maximum of 300 denormalized references.
> 
> ANS references:
> 
> - Maintain positional order
> - Support customized properties per usage
> - Enable automatic propagation of updates

### Referent Updates

A referent update occurs in Arc XP when a referenced document undergoes modification. For example, a story contains a reference to an image in its `content_elements` ANS key. If the image’s caption is updated in Photo Center and saved, the next time the parent story’s inflated version is requested, the denormalized image in the story contains the updated caption of the child image. If that same image is used in 1000 stories or galleries, then all 1000 objects update with the same caption change.

Arc XP employs a caching strategy that could cause these updates to take longer to show in the view layer to the consumer. To learn more, see [Caching at Arc XP](https://dev.arcxp.com/caching/overview/).

> **Note:**
> 
> Some Arc XP objects do not cause a referent update. References to Site Service sections do not update in parent objects until the parent object itself undergoes a save event.

### Inline Entities

Used for lightweight, embedded content that doesn’t need independent storage. In those scenarios, you can use inline entities instead of references.

An inline entity is like a pre-resolved reference, included identically in both normalized and denormalized documents. It acts as a second object that travels with the containing parent object, which you cannot reference or edit independently. A common example of inline entities is authors, which you store in `credits.by` within ANS.

Use inline entities only for authors, tags, and distributors. For example, use inline entities when you need to record an author, tag, or distributor that does not need to be available globally in Arc XP. Instead, frame its use with syntax that ties it directly to the context of the parent object, as shown in the following example:

```json
{
  "_id": "DEFGHIJKLMNOPQRSTUVWXYZABC",
  "type": "story",
  "version": "0.10.9",
  "headlines": {
    "basic": "Man Bites Cat"
  },
  "credits": {
    "by": [
      {
        "type": "author",
        "name": "Dr. Suess"
      }
    ]
  }
}
```

### Custom Referent Properties

ANS reference syntax allows for a property in the referent field called `referent_properties`. This property allows you to customize and overwrite the original properties of a child object when it is used in a parent, but only for that one particular use. You write this kind of customized overwrite using a referent custom property, `referent.referent_properties.{property of child object to overwrite}`.

In the previous example of a fully inflated parent story from Content API, the image’s caption is contained in the object.

```json
{
  "content_elements": [
    {
      "type": "reference",
      "referent": {
        "id": "MUMQSJXQFRE3HAKLMTK3T3R4QU",
        "type": "image",
        "referent_properties": {
          "caption": "In this story, use this caption for the image instead of the default: Road closure... etc.",
          "subtitle": "This is an overwritten subtitle field"
        }
      }
    }
  ]
}
```

Inside of `referent_properties`, you can add some native properties of the child object that you want customized for its use in the parent content. `referent_properties` customizations are limited to fields that represent captions, titles, descriptions, headlines, and custom user-added fields in the `additional_properties` key. The values written in `referent_properties` do not feed back and change the original information on the source material. They are exclusive to only a single use in the parent content.

The following table provides a list of ANS fields that you are likely to nest child Arc XP objects in, resulting in reference syntax when writing create or update ANS.

| ANS FIELD                                  | ANS OBJECT TYPE        | DESCRIPTION                                                                                         |
| ------------------------------------------ | ---------------------- | --------------------------------------------------------------------------------------------------- |
| content\_elements                          | storygallery           | Content elements are an ordered list of variably-typed elements, including text, images, and videos |
| promo\_items                               | storygallery           | Lists of promotional content                                                                        |
| credits                                    | storygalleryvideoimage | Authors attributed to the content                                                                   |
| related\_content                           | storyvideo             | Lists of content items this object is related to                                                    |
| taxonomy.primary\_sectiontaxonomy.sections | galleryvideo           | Holds Site Service sections                                                                         |
| website\_primary\_sectionwebsite\_sections | story                  | Holds Site Service sections                                                                         |

> **Recap:**
> 
> - Customize the original properties of a child object
> - Does not update or change the original information on the source material

### Additional Properties

Several ANS types include a field named `additional_properties`. This field is reserved for custom use and must be valid JSON, but its specific use is undefined by ANS. This is an advanced field that should be used only after fully understanding its implications.

The following snippet exemplifies an object with custom fields inside the `additional_properties` field.

```json
{
  "additional_properties": {
    "custom_field": "value",
    "organization_data": {}
  }
}
```

> **Caution:**
> 
> Data within `additional_properties` is not searchable in Content API. See [Searchable Text Fields](https://dev.arcxp.com/publishing-platform/developer-docs/content-api/content-api-query-reference/#searchable-text-fields) for more information.

## Best Practices

To ensure reliable content rendering and management, Arc XP recommends adhering to the following best practices:

### Reference Management

- Use references for reusable content
- Monitor reference limits
- Consider cache implications

### Content Structure

- Maintain consistent taxonomy
- Use appropriate content types
- Follow schema guidelines

### Performance

- Optimize reference usage
- Implement efficient caching
- Monitor payload sizes

## Limitations

ANS offers a complete and extensible schema, but it also has the following limitations:

- Limits denormalized references to 300 for each document
- Requires schema validation
- Has complex cache invalidation
- Adds overhead to content transformation

> **Caution:**
> 
> Exceeding reference limits can lead to incomplete content resolution.

## Further Reading

- [Content API Documentation](https://dev.arcxp.com/api/public-content-retrieval/content-api/)
- For more detailed information on how to construct ANS when creating or updating an Arc XP object, refer to the following articles:

  - [How To Write The Minimum Ans For A Viable Video Document](https://dev.arcxp.com/concepts/content-model-ans/how-to-write-the-minimum-ans-for-a-viable-video-document/)
  - [How To Write The Minimum Ans For A Viable Image Document](https://dev.arcxp.com/concepts/content-model-ans/minimum-ans-for-a-viable-image-document/)
  - [How To Write The Minimum Ans For A Viable Gallery Document](https://dev.arcxp.com/concepts/content-model-ans/minimum-ans-for-a-viable-gallery-document/)
