> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chatfeatured.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sanity Integration

> Publish articles from ChatFeatured into your Sanity dataset

The Sanity integration writes ChatFeatured articles into a Sanity dataset as documents of the type you choose, usually `post`. You connect with a project ID, a dataset name and an API token, confirm which fields an article fills in, and then save drafts, publish, or schedule from the article editor, the agent, or MCP.

**Status:** Available | **Setup time:** 10 minutes | **Complexity:** Intermediate

## Before you start

<Warning>
  **You need an API token with Editor permissions.** Viewer tokens can read your dataset but can't create documents. Only project administrators can create tokens.
</Warning>

Sanity is headless: your content lives in Sanity, and your own site (often Next.js on Vercel) renders it. That has two consequences for this integration:

* ChatFeatured fills in fields on **your** schema, so you confirm a field mapping when you connect. ChatFeatured suggests one by reading your newest document of that type.
* Sanity doesn't know where your posts appear on your site. Give ChatFeatured your **site URL** and **post URL pattern** so it can track each published post's live page.

***

## Setup

### Step 1: Find your project ID and dataset

1. Go to [sanity.io/manage](https://www.sanity.io/manage) and open your project.
2. The **project ID** is shown under the project name. It's also the `projectId` in your `sanity.config.ts`.
3. Open **Datasets** and note the dataset your site reads from. It's usually `production`.

### Step 2: Create an API token

1. In the same project, go to **API → Tokens** and click **Add API token**.
2. Name it "ChatFeatured".
3. Under **Permissions**, choose **Editor**.
4. Click **Save** and copy the token. Sanity shows it only once.

<Warning>
  Treat this token like a password. It can create, change, and delete every document in the project's datasets. Don't paste it into a shared document or a support ticket.
</Warning>

Tokens don't expire. You only need a new one if you delete this token in Sanity.

### Step 3: Connect in ChatFeatured

1. In ChatFeatured, go to **Integrations → Sanity**.
2. Enter your **project ID** and **dataset**, paste the **API token**, and click **Check connection**.

ChatFeatured confirms the token can read and write the dataset, then lists the document types in it.

### Step 4: Confirm the field mapping

1. Pick the **document type** articles should be created as.
2. Check the **field mapping**. Each row names the field on your schema that an article value goes into. Clear a row to skip that field.
3. Pick the **body format**. Use Portable Text if your body field is block content (the Sanity default). Use HTML or Markdown if it's a string field your site renders.
4. For Portable Text, tick **what your body field allows**. See [Matching your body field](#matching-your-body-field) below.
5. If your schema has an author reference, pick a **default author**.
6. Add your **site URL** and **post URL pattern**, for example `https://www.example.com` and `/blog/{slug}`. The form shows the URL a post will be tracked at.
7. Optionally add your **Studio URL**, for example `https://your-project.sanity.studio`, so published articles link straight to the document.
8. Click **Connect dataset**.

<Info>
  If the dataset has no documents of that type yet, ChatFeatured fills in the field names from Sanity's blog template (`title`, `slug`, `body`, `publishedAt`, `mainImage`, `author`). The type doesn't need any documents to connect. Check the field names against your schema before connecting.
</Info>

### Matching your body field

Sanity Studio won't display a body field that contains a block type, style, list, or mark its schema doesn't declare. It shows "Invalid Portable Text value" in place of the whole body. So ChatFeatured only sends what you tell it your body field allows, and turns everything else into something Sanity's blog template accepts:

| Setting | When it's off |
| - | - |
| Numbered lists | Sent as bulleted lists |
| H5 and H6 headings | Sent as H4 |
| Inline code, underline, strikethrough | Sent as plain text |
| Images | Left out |
| Code blocks (`@sanity/code-input`) | Sent as plain paragraphs |
| Tables (`@sanity/table`) | Sent as one line per row, with the header row in bold |

When you connect, ChatFeatured ticks anything your newest document already uses. Sanity's blog template allows none of these except images. A body field declared as a plain `{ type: 'block' }` allows the first three, and code blocks and tables need their plugins added to the field's `of` array.

### Connecting more than one dataset

Repeat Step 3 and Step 4 for each dataset. Each connection is a separate publish destination, and you pick one at publish time. A dataset can only be connected once.

***

## Publishing articles

From the article editor, click **Publish** (or **Schedule**) and choose your Sanity connection.

| Option | What happens in Sanity |
| - | - |
| **Save as draft** | A draft document is created for your team to review and publish in Studio. |
| **Publish now** | The document is published. |
| **Schedule** | A draft is saved right away, and ChatFeatured publishes it at the time you set. Reschedule or cancel it from the article's **Reschedule** button. |

### Updating a published article

Edit the article in ChatFeatured and publish again. This updates the same Sanity document instead of creating a new one. Fields ChatFeatured doesn't map, such as categories your team set in Studio, are kept.

<Note>
  Publishing works like Sanity's own Publish button: unpublished edits open in Studio for that document are replaced by the version you publish from ChatFeatured.
</Note>

### What gets sent

| ChatFeatured | Sanity |
| - | - |
| Title | Your title field |
| Slug | Your slug field, as a Sanity slug |
| Content | Your body field, as Portable Text, HTML, or Markdown |
| Excerpt | Your excerpt field |
| Meta description | Your meta description field (nested paths like `seo.description` work) |
| Publish date | Your publish date field, set when the post first goes live |
| Featured image | Your image field, uploaded to your Sanity media |
| Author | A reference to the author document you picked |

In Portable Text, headings, paragraphs, quotes, lists, and links map to standard Sanity blocks and marks, limited to what your body field allows (see [Matching your body field](#matching-your-body-field)). Images inside the article are uploaded to your Sanity media and added as `image` blocks. Code blocks use the `code` type from [`@sanity/code-input`](https://www.sanity.io/plugins/code-input) and tables the `table` type from [`@sanity/table`](https://www.sanity.io/plugins/sanity-plugin-table).

### Live URL tracking

Once a post is published, ChatFeatured records its URL from your site URL and post URL pattern, and starts attributing AI citations of that page to the article. Drafts and scheduled posts aren't tracked until they're published. Without a site URL, publishing still works, but there's no live page to track.

***

## Publishing with the agent and MCP

Sanity works the same way through automation as it does in the editor.

* **The agent**: ask it to publish an article and it offers your Sanity connections alongside your other destinations.
* **MCP**: `list_integrations` returns each Sanity connection with its project, dataset, document type, and available authors (with their ids). `publish_article` accepts the connection's `integrationId`, and `sanityAuthorId` to override the default author.

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Sanity says the API token is invalid or revoked">
    The token was deleted in Sanity. Create a new Editor token, then edit the connection in ChatFeatured and paste it.
  </Accordion>

  <Accordion title="The Sanity API token can't write to this dataset">
    The token has Viewer permissions. Create a token with **Editor** permissions and use that one.
  </Accordion>

  <Accordion title="This API token belongs to a different Sanity project">
    Tokens only work in the project they were created in. Check the project ID, or create a token in the project you're connecting.
  </Accordion>

  <Accordion title="This Sanity project has no dataset called ...">
    Check the dataset name under **Datasets** in [sanity.io/manage](https://www.sanity.io/manage). Dataset names are case-sensitive.
  </Accordion>

  <Accordion title="Studio shows an unknown field on published documents">
    A mapped field doesn't exist on your schema. Edit the connection and correct the field name, or clear it to stop writing that field.
  </Accordion>

  <Accordion title="Studio shows &#x22;Invalid Portable Text value&#x22; on the body">
    The connection sends something your body field doesn't declare, such as a numbered list or a table. Edit the connection, untick that item under **What your body field allows**, and publish the article again. Or add it to your schema and leave it ticked.
  </Accordion>

  <Accordion title="The live URL is wrong or missing">
    Edit the connection and check the site URL and post URL pattern. The pattern must contain `{slug}`. Publish the article again to record the corrected URL.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.