Simon MacDonald
Software Engineer, Comic Enthusiast, Coffee Lover, Human Goodreads and Staff Software Engineer at Sanity. He/Him
Spread the word on Mastodon when publishing a blog post
defineField({
name: 'mastodonPost',
title: 'Mastodon Post Content',
type: 'text',
description: 'Content to post on Mastodon when this post is published',
})import {env} from 'node:process'
import {Client, MastodonStrategy} from '@humanwhocodes/crosspost'
import {documentEventHandler} from '@sanity/functions'
const {MASTODON_TOKEN = '', MASTODON_HOST = ''} = env
interface NotificationData {
slug: {
current: string
}
mastodonPost: string
title: string
}
export const handler = documentEventHandler<NotificationData>(async ({event}) => {
const {data} = event
const {title, mastodonPost, slug} = data
try {
const mastodon = new MastodonStrategy({
accessToken: MASTODON_TOKEN,
host: MASTODON_HOST,
})
const client = new Client({
strategies: [mastodon],
})
const postContent = `${title}
${mastodonPost}
${slug.current}`
await client.post(postContent)
console.log('Successfully sent post to Mastodon')
} catch (error) {
console.error('Error posting to Mastodon:', error)
throw error
}
})// sanity.blueprint.ts
import 'dotenv/config'
import process from 'node:process'
import {defineBlueprint, defineDocumentFunction} from '@sanity/blueprints'
const {MASTODON_TOKEN, MASTODON_HOST} = process.env
if (typeof MASTODON_TOKEN !== 'string' || typeof MASTODON_HOST !== 'string') {
throw new Error('MASTODON_TOKEN and MASTODON_HOST must be set')
}
export default defineBlueprint({
resources: [
defineDocumentFunction({
type: 'sanity.function.document',
name: 'mastodon-post',
src: './functions/mastodon-post',
memory: 1,
timeout: 10,
event: {
on: ['create'],
filter: "_type == 'post' && defined(mastodonPost)",
projection: '{title, mastodonPost, slug}',
},
env: {
MASTODON_TOKEN: MASTODON_TOKEN,
MASTODON_HOST: MASTODON_HOST,
},
}),
],
})The Problem
Content teams want to automatically share their published articles on Mastodon to reach decentralized social media audiences. Manually cross-posting to multiple social platforms is time-consuming and often forgotten, leading to missed opportunities for content promotion across the fediverse.
The Solution
This Sanity Function automatically posts to Mastodon when content is published using the @humanwhocodes/crosspost library. When a post is published, the function creates a Mastodon post containing the title, mastodonPost, and slug, helping maintain consistent presence across decentralized social networks.
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 mastodon-post
Then deploy: npx sanity blueprints deploy
Mastodon Setup
More detailed instructions in the GitHub README
mastodon.social, mastodon.online, etc.) and sign in with your account.write:statuses.MASTODON_TOKEN and MASTODON_HOST to your .env file.How It Works
When a post is published, the function automatically:
• Posts the title, mastodonPost, and slug to Mastodon
• Uses the @humanwhocodes/crosspost library to handle posting
• Ensures consistent presence across decentralized social networks
Key Benefits
• Automates fediverse sharing by posting to Mastodon on content publish
• Saves time by eliminating manual cross-posting tasks
• Reaches decentralized audiences by sharing on Mastodon instances
• Ensures consistency with automatic posting of title, mastodonPost, and link
• Reduces missed opportunities by never forgetting to share published content
Technical Implementation
The function uses the @humanwhocodes/crosspost library to automate posting to Mastodon. It's built with:
• Event-driven architecture (triggers on publish)
• Integration with Mastodon API using access tokens
• Error handling and logging for reliable operation
Perfect For
• Content teams looking to expand their reach to decentralized social media
• Workflows that benefit from automated social media posting
• Teams managing multiple social media platforms
• Projects that require consistent content promotion across the fedivers
Software Engineer, Comic Enthusiast, Coffee Lover, Human Goodreads and Staff Software Engineer at Sanity. He/Him
Designer who spends most of his time coding
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.
Go to First Published Timestamp FunctionAI-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 postsOn document publish, send a Slack notification so your team is informed
Go to Notify your team via Slack on publishCreate, preview, and send Klaviyo campaigns without ever leaving Sanity Studio"
Go to Klaviyo campaigns without leaving your Studio