Discussing syncing external data with Sanity and adding new fields to the schema.
This is absolutely possible and a pretty common pattern! You're essentially looking to create a one-way sync from your existing system to Sanity, where Sanity acts as an "enrichment layer" for your tags. Let me break down your questions:
1. Is this possible?
Yes, very straightforward. The schema mutation you're describing (adding an image field in Sanity that doesn't exist in your source system) is actually one of the main benefits of this pattern. Here's how it works:
Your Sanity schema would look something like:
{
name: 'tag',
type: 'document',
fields: [
{name: 'label', type: 'string', readOnly: true},
{name: 'slug', type: 'slug', readOnly: true},
{name: 'image', type: 'image'} // Editorial addition
]
}The sync process from your external system would only touch label and slug, leaving image completely under editorial control. You can use the Sanity client to create or update documents.
Key trap to avoid: Use createOrReplace() carefully or use patch() instead. With createOrReplace(), you'll completely replace the document, which would wipe out the image if editors added one. Better approach:
await client
.patch(externalTag.id)
.set({label: externalTag.label, slug: {current: externalTag.slug}})
.commit()This way, only the fields you explicitly set are updated, preserving the editorial image field.
2. Is this advisable?
Yes, this is a well-established pattern at Sanity. In fact, Sanity Connect for Shopify works exactly this way - syncing product data from Shopify while allowing editors to enrich it with additional fields in Sanity.
Benefits of this approach:
- Separation of concerns: Your admin system remains the source of truth for tag management
- Editorial enrichment: Content teams can add context (images, descriptions, etc.) without touching the operational system
- Single source for frontend: Your frontend can query everything from Sanity in one GROQ query instead of joining data from multiple sources
Implementation recommendations:
- Mark synced fields as read-only in your schema so editors don't accidentally change them
- Use your external ID as the Sanity
_idto make syncing deterministic (e.g.,_id: externalTag.id) - Consider using Sanity Functions (if you're on a Growth plan or higher) to handle the sync. They're serverless functions within Sanity that can respond to events in your external system, eliminating the need for separate infrastructure
- Set up a webhook from your external system to trigger syncs when tags change, or use a scheduled cron job if webhooks aren't available
Additional variables to consider:
- Deletion handling: What happens when a tag is deleted in your external system? You'll need to decide whether to delete it from Sanity or just mark it as inactive
- Reference integrity: If other Sanity documents reference these tags, deleting them could break things. Consider using weak references or keeping soft-deleted tags around
- Initial sync: You'll need a one-time bulk import script to populate existing tags
- Conflict resolution: What happens if someone manually changes a synced field in Sanity? Your sync should overwrite it, but you might want logging to catch these cases
This pattern is battle-tested and gives you the best of both worlds - operational control where it matters and editorial flexibility where you need it. The guide on integrating external data sources provides more detailed examples of sync implementations if you need them!
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.