|
| 1 | +# Auto-Tag Function |
| 2 | + |
| 3 | +[Explore all examples](https://github.com/sanity-io/sanity/tree/main/examples) |
| 4 | + |
| 5 | +## Problem |
| 6 | + |
| 7 | +Content creators spend significant time manually tagging blog posts, leading to inconsistent tagging across content libraries and reduced productivity in editorial workflows. |
| 8 | + |
| 9 | +## Solution |
| 10 | + |
| 11 | +This Sanity Function automatically generates 3 relevant tags for blog posts by analyzing content using AI, intelligently reusing existing tags from other posts to maintain vocabulary consistency. |
| 12 | + |
| 13 | +## Benefits |
| 14 | + |
| 15 | +- **Saves 2-3 minutes per post** by eliminating manual tagging |
| 16 | +- **Improves content discoverability** through consistent tag application |
| 17 | +- **Maintains tag vocabulary** by prioritizing reuse of existing tags |
| 18 | +- **Scales automatically** as your content library grows |
| 19 | +- **Reduces editorial overhead** for content teams |
| 20 | + |
| 21 | +## Compatible Templates |
| 22 | + |
| 23 | +This function is built to be compatible with any of [the official "clean" templates](https://www.sanity.io/exchange/type=templates/by=sanity). We recommend testing the function out in one of those after you have installed them locally. |
| 24 | + |
| 25 | +### Adding the tags field to your schema |
| 26 | + |
| 27 | +If you're using the [nextjs-clean template](https://github.com/sanity-io/sanity-template-nextjs-clean), you'll need to add a `tags` field to your post schema: |
| 28 | + |
| 29 | +1. Open `studio/src/schemaTypes/documents/post.ts` |
| 30 | +2. Add this field to the `fields` array: |
| 31 | + |
| 32 | +```typescript |
| 33 | +defineField({ |
| 34 | + name: 'tags', |
| 35 | + title: 'Tags', |
| 36 | + type: 'array', |
| 37 | + of: [{ type: 'string' }], |
| 38 | + description: 'Tags will be automatically generated when you publish a post', |
| 39 | +}), |
| 40 | +``` |
| 41 | + |
| 42 | +3. Deploy your updated schema: |
| 43 | + |
| 44 | +```bash |
| 45 | +# /studio |
| 46 | +npx sanity schema deploy |
| 47 | +``` |
| 48 | + |
| 49 | +## Implementation |
| 50 | + |
| 51 | +**Important:** Run these commands from the root of your project (not inside the `studio/` folder). |
| 52 | + |
| 53 | +1. **Initialize the example** |
| 54 | + |
| 55 | + Run this if you haven't initialized blueprints: |
| 56 | + |
| 57 | + ```bash |
| 58 | + npx sanity blueprints init |
| 59 | + ``` |
| 60 | + |
| 61 | + You'll be prompted to select your organization and Sanity studio. |
| 62 | + |
| 63 | + Then run: |
| 64 | + |
| 65 | + ```bash |
| 66 | + npx sanity blueprints add function --example auto-tag |
| 67 | + ``` |
| 68 | + |
| 69 | +2. **Add configuration to your blueprint** |
| 70 | + |
| 71 | + ```ts |
| 72 | + // sanity.blueprint.ts |
| 73 | + import {defineBlueprint, defineDocumentFunction} from '@sanity/blueprints' |
| 74 | + |
| 75 | + export default defineBlueprint({ |
| 76 | + resources: [ |
| 77 | + defineDocumentFunction({ |
| 78 | + type: 'sanity.function.document', |
| 79 | + name: 'auto-tag', |
| 80 | + src: './functions/auto-tag', |
| 81 | + memory: 2, |
| 82 | + timeout: 30, |
| 83 | + event: { |
| 84 | + on: ['publish'], |
| 85 | + filter: "_type == 'post' && !defined(tags)", |
| 86 | + projection: '{_id}', |
| 87 | + }, |
| 88 | + }), |
| 89 | + ], |
| 90 | + }) |
| 91 | + ``` |
| 92 | + |
| 93 | +3. **Install dependencies** |
| 94 | + |
| 95 | + Install dependencies in the project root: |
| 96 | + |
| 97 | + ```bash |
| 98 | + npm install |
| 99 | + ``` |
| 100 | + |
| 101 | +4. **Make sure you have a schema deployed** |
| 102 | + |
| 103 | +From the studio folder, run: |
| 104 | + |
| 105 | +```bash |
| 106 | +# In the studio/ folder |
| 107 | +npx sanity schema deploy |
| 108 | +``` |
| 109 | + |
| 110 | +## Testing the function locally |
| 111 | + |
| 112 | +You can test the auto-tag function locally using the Sanity CLI before deploying it to production. |
| 113 | + |
| 114 | +### Simple Testing Command |
| 115 | + |
| 116 | +Test the function with an existing document ID from your dataset: |
| 117 | + |
| 118 | +```bash |
| 119 | +npx sanity functions test auto-tag --document-id <insert-document-id> --dataset production --with-user-token |
| 120 | +``` |
| 121 | + |
| 122 | +Replace `<insert-document-id>` with an actual document ID from your dataset and `production` with your dataset name. |
| 123 | + |
| 124 | +### Interactive Development Mode |
| 125 | + |
| 126 | +Start the development server for interactive testing: |
| 127 | + |
| 128 | +```bash |
| 129 | +npx sanity functions dev |
| 130 | +``` |
| 131 | + |
| 132 | +### Testing Tips |
| 133 | + |
| 134 | +- **Use real document IDs** - Document functions require IDs that exist in your dataset |
| 135 | +- **Use Node.js v22.x** locally to match production runtime |
| 136 | +- **Test edge cases** like posts without content or with existing tags |
| 137 | +- **Check function logs** in CLI output for debugging |
| 138 | +- **Test without AI calls** first by setting `noWrite: true` in the function |
| 139 | +- **Create test content** - If you don't have posts without tags, create some test documents first |
| 140 | + |
| 141 | +## Requirements |
| 142 | + |
| 143 | +- A Sanity project with Functions enabled |
| 144 | +- A schema with a `post` document type containing: |
| 145 | + - A `content` field with portable text (for content analysis) |
| 146 | + - A `tags` array field (for storing generated tags) |
| 147 | +- Access to Sanity's AI capabilities |
| 148 | +- Node.js v22.x for local development |
| 149 | + |
| 150 | +## Usage Example |
| 151 | + |
| 152 | +When a content editor publishes a new blog post without tags, the function automatically: |
| 153 | + |
| 154 | +1. **Triggers** on the publish event for post documents without existing tags |
| 155 | +2. **Analyzes** the post's content field using AI |
| 156 | +3. **Retrieves** existing tags from other published posts for vocabulary consistency |
| 157 | +4. **Generates** 3 relevant tags, prioritizing reuse of existing tags when appropriate |
| 158 | +5. **Applies** the tags directly to the published document |
| 159 | + |
| 160 | +**Result:** Content creators get consistent, relevant tags without manual effort, improving content organization and discoverability. |
| 161 | + |
| 162 | +## Customization |
| 163 | + |
| 164 | +### Adjust Tag Generation |
| 165 | + |
| 166 | +Modify the AI instruction to change tagging behavior: |
| 167 | + |
| 168 | +```typescript |
| 169 | +instruction: `Based on the $content, create 5 relevant tags instead of 3. Focus on technical topics and use camelCase format.` |
| 170 | +``` |
| 171 | + |
| 172 | +### Change Target Field |
| 173 | + |
| 174 | +Update the target path to save tags to a different field: |
| 175 | + |
| 176 | +```typescript |
| 177 | +target: { |
| 178 | + path: 'categories', // Instead of 'tags' |
| 179 | +} |
| 180 | +``` |
| 181 | + |
| 182 | +### Filter Different Document Types |
| 183 | + |
| 184 | +Modify the blueprint filter to target different content types: |
| 185 | + |
| 186 | +```typescript |
| 187 | +filter: "_type == 'article' && !defined(keywords)" |
| 188 | +``` |
0 commit comments