Capture Tone of Voice Function

Official(made by Sanity team)

By Ken Jones Pizza

AI-Powered Tone Analysis for Consistent Brand Voice

schemaTypes/post.ts

defineField({
  name: 'toneOfVoice',
  title: 'Tone of Voice',
  type: 'text',
  readOnly: () => true, // This is optional
  description: 'Tone of voice analysis will be automatically generated when you publish a post',
}),

functions/capture-tone-of-voice/index.ts

import {createClient} from '@sanity/client'
import {documentEventHandler} from '@sanity/functions'

export const handler = documentEventHandler(async ({context, event}) => {
  const {local} = context // local is true when running locally
  const {data} = event

  const client = createClient({
    ...context.clientOptions,
    apiVersion: 'vX',
    useCdn: false,
  })

  try {
    const result = await client.agent.action.generate({
      // Set `noWrite` to `false` to write the tone of voice to the document
      noWrite: local ? true : false, // if local is true, we don't want to write to the document, just return the result for logging
      instructionParams: {
        content: {
          type: 'field',
          path: 'content',
        },
      },
      instruction: `Examine the $content. Explain the tone of voice for the post.`,
      target: {
        path: 'toneOfVoice',
      },
      conditionalPaths: {
        defaultReadOnly: false,
      },
      documentId: data._id,
      schemaId: '_.schemas.default',
      forcePublishedWrite: true,
    })
    console.log(
      local
        ? 'Generated tone analysis (LOCAL TEST MODE - Content Lake not updated):'
        : 'Generated tone analysis:',
      result.toneOfVoice,
    )
  } catch (error) {
    console.error('Error occurred during tone of voice generation:', error)
  }
})

sanity.blueprint.ts

import {defineBlueprint, defineDocumentFunction} from '@sanity/blueprints'

export default defineBlueprint({
  resources: [
    defineDocumentFunction({
     type: 'sanity.function.document',
     name: 'capture-tone-of-voice',
     src: './functions/capture-tone-of-voice',
     memory: 2,
     timeout: 60,
     event: {
       on: ['create', 'update'],
        filter:
             "_type == 'post' && (delta::changedAny(content) || (delta::operation() == 'create' && defined(content)))",
        projection: '{_id}',
     },
   }),
  ],
})

This Sanity Function solves a fundamental content strategy challenge: understanding and maintaining consistent tone across your content library. Content creators often lack objective feedback on their writing style, making it difficult to ensure brand voice consistency and optimize content engagement.

Quick Start

View full instructions and source code.

Initialize blueprints if you haven't already: npx sanity blueprints init

Then: npx sanity blueprints add function --example capture-tone-of-voice

Then deploy: npx sanity blueprints deploy

How It Works

When a content editor publishes a new blog post, the function automatically:

  • Triggers on the publish event for post documents
  • Analyzes the post's content field to identify tone characteristics
  • Generates objective tone assessment using AI
  • Stores the analysis in a dedicated toneOfVoice field
  • Provides immediate insights into writing style and voice

Key Benefits

  • Provides objective feedback on content tone and style
  • Helps maintain consistent brand voice across all content
  • Enables data-driven content strategy decisions
  • Reduces subjective editorial discussions about tone
  • Scales tone analysis as your content library grows
  • Improves content creator awareness of their writing style

Technical Implementation

The function uses Sanity's AI capabilities to provide sophisticated tone analysis of portable text content. It's built with:

  • Event-driven architecture (triggers on document publish)
  • AI-powered tone identification and explanation
  • Dedicated schema field for storing analysis results
  • Simple, customizable implementation for different content types

Perfect For

  • Content teams needing objective tone feedback
  • Brands requiring consistent voice across multiple creators
  • Editorial workflows focused on audience engagement optimization
  • Organizations building comprehensive content style guides

The function is compatible with any Sanity project and can be easily customized to focus on specific tone characteristics or content types relevant to your brand strategy.

Contributor

Official Recipes by Sanity

First Published Timestamp Function

Featured contribution
Official(made by Sanity team)

Automatically track when content was first published with a timestamp that sets once and never overwrites, providing reliable publication history for analytics and editorial workflows.

Knut Melvær
Go to First Published Timestamp Function

Automatically tag blog posts

Featured contribution
Official(made by Sanity team)

AI-powered automatic tagging for Sanity blog posts that analyzes content to generate 3 relevant tags, maintaining consistency by reusing existing tags from your content library.

Go to Automatically tag blog posts