# Sanity

## Sanity Integration

Connect Cuppa to Sanity to automatically export your AI-generated content directly to your Sanity CMS. This is perfect for teams building headless websites with custom frontends.

### What You Can Do

* **Export projects** to Sanity with one click
* **Map your fields** to match your document schema
* **Auto-publish** content automatically after generation
* **Bulk export** articles efficiently with batching

***

### Prerequisites

Before connecting, you'll need:

1. A **Sanity account** and project
2. A **Project ID** and **Dataset** name
3. An **API Token** with write permissions
4. A **Document type** defined in your schema (e.g., "post" or "article")

***

### Step 1: Get Your Sanity Credentials

#### Finding Your Project ID and Dataset

1. Go to your [Sanity Dashboard](https://sanity.io/manage)
2. Select your project
3. Your **Project ID** is shown in the URL and project info (looks like `abc123xy`)
4. Your **Dataset** is typically `production` or `staging` — find it in Project Settings → Datasets

#### Creating an API Token

1. In the Sanity Dashboard, go to your project
2. Navigate to **API** → **Tokens**
3. Click **"Add API Token"**
4. Configure your token:
   * **Name**: "Cuppa Integration" (or any descriptive name)
   * **Permissions**: Select **"Editor"** or **"Deploy Studio"** (needs write access)
5. Click **"Add Token"**
6. **Copy the token** — you won't see it again!

> 💡 **Tip**: "Editor" permissions are recommended. "Viewer" permissions won't work because Cuppa needs to create documents.

***

### Step 2: Understand Your Sanity Schema

Before connecting, identify the document type you want to export to. In your Sanity Studio code, look at your schema definitions:

```javascript
// Example schema definition (sanity/schemas/post.js)
export default {
  name: 'post',        // This is your document type
  title: 'Blog Post',
  type: 'document',
  fields: [
    { name: 'title', type: 'string' },
    { name: 'slug', type: 'slug' },
    { name: 'body', type: 'text' },  // or 'blockContent'
    { name: 'excerpt', type: 'text' },
    // ... other fields
  ]
}
```

Note the **field names** (not titles) — you'll need these for mapping.

***

### Step 3: Connect Sanity in Cuppa

1. Go to **Team Settings** → **Integrations**
2. Find **Sanity** and click **Connect**
3. Enter your credentials:
   * **Project ID**: Your Sanity project ID (e.g., `abc123xy`)
   * **Dataset**: Usually `production` or your dataset name
   * **API Token**: The token you created
   * **API Version**: Use a recent date format like `2024-01-01`
   * **Document Type**: The `_type` for your documents (e.g., `post`, `article`)
4. **Map your fields**: Tell Cuppa which schema fields should receive each content field
5. Click **Connect**

***

### Step 4: Export Content to Sanity

#### Export a Single Project

1. Open any project in Cuppa
2. Click the **"Export"** button
3. Select **"Export to Sanity"**
4. Choose which articles to export (or all)
5. Click **Export**

#### Bulk Export

For large exports, Cuppa automatically:

* Batches documents (up to 100 per request)
* Handles rate limiting
* Shows you progress as it exports

> ⚡ **Fast**: Sanity's API is efficient. Bulk exports are typically quick!

***

### Field Mapping Reference

When setting up your integration, you map Cuppa fields to your Sanity schema field names:

| Cuppa Field      | Description           | Example Sanity Field       |
| ---------------- | --------------------- | -------------------------- |
| `title`          | Article title         | `title`                    |
| `slug`           | URL-friendly slug     | `slug.current`             |
| `content`        | Full HTML content     | `body` or `content`        |
| `excerpt`        | Short summary         | `excerpt` or `description` |
| `target_keyword` | Primary keyword       | `keyword` or `seoKeyword`  |
| `language`       | Content language      | `language`                 |
| `image`          | Featured image URL    | `featuredImage`            |
| `date`           | Article creation date | `publishedAt`              |

> 💡 **Tip**: Sanity stores slugs as objects with a `current` property. Map to `slug.current` for proper handling.

***

### Content Format Notes

#### HTML Content

Cuppa exports content as HTML. How Sanity handles this depends on your field type:

* **Text fields**: Store HTML as-is (rendered as plain text in Studio)
* **Rich text (Portable Text)**: You may need to convert HTML to blocks — consider using a custom import script

If you need Portable Text, you can:

1. Export to a plain text field in Sanity
2. Use a Sanity plugin or custom function to convert HTML to blocks

#### Images

Cuppa exports image URLs. Sanity can handle external URLs, but for full asset management:

* Store the URL in a string field
* Or upload images to Sanity's asset pipeline separately

***

### Troubleshooting

#### "Connection failed" error

* Double-check your Project ID — it's case-sensitive
* Verify your Dataset name is correct
* Ensure your API Token has Editor (write) permissions
* Check the API Version format (should be `YYYY-MM-DD`)

**Token permission requirements:**

* Editor or higher (Viewer is read-only)
* Dataset-specific tokens work; project-wide tokens also work

#### "Document type not found" error

* Make sure the document type exists in your Sanity schema
* The type name is case-sensitive
* Deploy your Sanity Studio if you recently added the schema

#### "Field validation failed" error

* Check that your field names match your schema exactly
* Field names are case-sensitive
* Required fields must be mapped

#### Content not appearing in Sanity Studio

* Check your Dataset — documents might be in `staging` instead of `production`
* Verify the `_type` matches your schema
* Look in the correct document type filter in Studio
* Try running a GROQ query: `*[_type == "post"]`

#### "Unauthorized" or 403 errors

* Your token may have expired or been revoked
* Generate a new token with Editor permissions
* Make sure the token is for the correct project

#### Rate limit errors

* Sanity has generous rate limits (typically 25 requests/second)
* Cuppa batches documents to stay well under limits
* If you hit limits, wait a moment and retry

#### "Invalid API Version" error

* API Version must be a date in `YYYY-MM-DD` format
* Use a recent date like `2024-01-01`
* Don't use version numbers like `v1` or `v2`

#### Documents created but fields are empty

* Check your field mapping — field names must match exactly
* Sanity field names are case-sensitive
* Verify the field types are compatible (text to text, etc.)

***

### FAQ

**Can I export to multiple Sanity projects?** Currently, each Cuppa team can connect to one Sanity project. Update your integration settings to switch between projects.

**Does it update existing documents or create new ones?** Cuppa creates new documents each time. To update existing content, delete the documents in Sanity first, then re-export.

**Can I export to both production and staging datasets?** Update your integration settings to change the dataset. You can only connect to one dataset at a time.

**What about Portable Text / Block Content?** Cuppa exports HTML, which can be stored in text fields. For Portable Text, you'll need to convert HTML to blocks — consider using the `@sanity/block-tools` package in a custom script.

**Can I map to nested fields?** Yes! Use dot notation for nested fields, e.g., `slug.current` or `author.name`.

**Do I need CORS configuration?** No. Cuppa communicates with Sanity server-side, so CORS isn't required.

**What about image assets?** Cuppa exports image URLs as strings. For full Sanity asset management, you'd need to upload images through Sanity's asset API separately.

**Is there a document limit?** There's no Cuppa limit. Sanity plans have different document limits:

* Free: 100,000 documents
* Team: 1,000,000 documents
* Business: Higher limits

**Can I trigger Sanity webhooks?** Yes! Documents created via API trigger Sanity webhooks and GROQ-powered subscriptions, just like documents created in Studio.

**What about draft/published states?** Sanity doesn't have built-in draft states like WordPress. Documents are "published" when created. For draft workflows, use a custom `draft` field in your schema.

**Can I use this with Next.js Preview Mode?** Yes! Documents created by Cuppa can be previewed in Next.js using Sanity's preview tokens and your normal preview setup.

**Why doesn't my schema show in Cuppa?** Sanity schemas are defined in your Studio code, not returned by the API. You need to know your field names from your schema files. Cuppa doesn't auto-discover schema fields.

**How do I handle multi-language content?** Use Sanity's `@sanity/language-filter` plugin and create language-specific documents. Export to different document types or use a language field.

***

### API Version Note

The API Version (`apiVersion`) tells Sanity which version of the API to use. Using a date-based version ensures consistent behavior:

* **Format**: `YYYY-MM-DD` (e.g., `2024-01-01`)
* **Best practice**: Use a recent past date
* **Why**: Sanity releases API changes on specific dates; pinning a version prevents unexpected changes

***

### Need Help?

* Check our [Help Center](https://learn.cuppa.ai)
* Contact support at <support@cuppa.ai>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://learn.cuppa.ai/integrations/sanity.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
