Everything *[NYC] 2026: see what we announced. →
Skip to content

Post to Mastodon

Official(made by Sanity team)

Spread the word on Mastodon when publishing a blog post

By Simon MacDonald & Ken Jones Pizza


schemaTypes/post.ts

defineField({
  name: 'mastodonPost',
  title: 'Mastodon Post Content',
  type: 'text',
  description: 'Content to post on Mastodon when this post is published',
})

index.ts

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

// 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({
      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

  1. Log into your Mastodon instance: Go to your Mastodon instance (e.g., mastodon.social, mastodon.online, etc.) and sign in with your account.
  2. Access Development Settings: Click Preferences, then in the sidebar, click "Development" and "New Application".
  3. Create Application: Give it a descriptive name (e.g., "Sanity Auto-Post"), leave Redirect URI as default, and select write:statuses.
  4. Get Access Token: After creating the application, copy the "Your access token" and note your instance URL.
  5. Environment Variables: Add 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

Contributors

Simon MacDonald

Simon MacDonald

Software Engineer, Comic Enthusiast, Coffee Lover, Human Goodreads and Staff Software Engineer at Sanity. He/Him

Visit Simon MacDonald's profile
Ken Jones Pizza

Ken Jones Pizza

Designer who spends most of his time coding

Visit Ken Jones Pizza's profile