The all-in-one social media toolkit for Sanity Studio.
Create stunning graphics, schedule posts, manage templates, and more — without ever leaving your CMS.
Warning
Early Release: The installation as a standalone npm plugin has not been tested yet. This tool was originally built directly inside a Sanity Studio project and has been extracted into this repository. If you run into issues, please open an issue.
|
|
npm install sanity-social-media-studio// sanity.config.ts
import { defineConfig } from 'sanity'
import { socialMediaStudioTool } from 'sanity-social-media-studio'
export default defineConfig({
// ...
plugins: [
socialMediaStudioTool(),
],
})import {
socialMediaTemplateType,
lateApiSettingsType,
} from 'sanity-social-media-studio'
export default defineConfig({
// ...
schema: {
types: [
socialMediaTemplateType,
lateApiSettingsType,
],
},
})import {
generateSocialGraphicsAction,
generateNewsSocialGraphicsAction,
generateAfterShowSocialGraphicsAction,
} from 'sanity-social-media-studio'
export default defineConfig({
// ...
document: {
actions: (prev, context) => {
if (context.schemaType === 'concert') {
return [...prev, generateSocialGraphicsAction]
}
if (context.schemaType === 'post') {
return [...prev, generateNewsSocialGraphicsAction]
}
if (context.schemaType === 'aftershowStory') {
return [...prev, generateAfterShowSocialGraphicsAction]
}
return prev
},
},
})The plugin requires backend API routes for graphics rendering and social media posting.
Social Graphics Endpoint
// app/api/social-graphics/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { renderSocialGraphic } from 'sanity-social-media-studio/lib'
export async function POST(req: NextRequest) {
const body = await req.json()
const buffer = await renderSocialGraphic(body)
return new NextResponse(buffer, {
headers: { 'Content-Type': 'image/png' },
})
}Late API Proxy (Social Media Scheduling)
The posting feature uses Late as the scheduling backend. The API key is configured directly within the plugin's Settings tab and stored as a Sanity document — no environment variable needed.
You need to set up a proxy route that reads the key from Sanity and forwards requests to the Late API:
// app/api/late/[...path]/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { createClient } from '@sanity/client'
const sanityClient = createClient({
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
dataset: process.env.NEXT_PUBLIC_SANITY_DATASET || 'production',
useCdn: false,
apiVersion: '2024-01-01',
})
export async function POST(
req: NextRequest,
{ params }: { params: { path: string[] } }
) {
const settings = await sanityClient.fetch(
`*[_type == "lateApiSettings"][0]{ apiKey }`
)
const path = params.path.join('/')
const response = await fetch(`https://api.getlate.dev/${path}`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${settings.apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(await req.json()),
})
const data = await response.json()
return NextResponse.json(data)
}NEXT_PUBLIC_SANITY_PROJECT_ID=your_project_id
NEXT_PUBLIC_SANITY_DATASET=productionNote: The Late API key is managed within the plugin's Settings tab in Sanity Studio — not via environment variables.
| Style | Description |
|---|---|
| Industrial | Bold, dark, high-contrast with industrial textures |
| Minimal | Clean, minimalist with subtle typography |
| Gradient | Vibrant gradient backgrounds with modern feel |
| Bold | Large, impactful text with strong colors |
| Neon | Glowing neon effects on dark backgrounds |
| Platform | Post Types | Max Characters |
|---|---|---|
| Feed, Story, Reel, Carousel | 2,200 | |
| Post | 63,206 | |
| Threads | Post | 500 |
| X (Twitter) | Tweet | 280 |
| Placeholder | Description |
|---|---|
{title} |
Content title |
{date} |
Event date |
{time} |
Event time |
{location} |
Event location / city |
{venue} |
Venue name |
{band} |
Band / artist name |
{url} |
Link URL |
{price} |
Ticket price |
View project structure
src/
├── index.ts # Plugin entry (definePlugin)
├── lib/
│ ├── types.ts # Core types
│ ├── styles.ts # 5 built-in graphic styles
│ ├── renderer.ts # Server-side canvas renderer
│ └── index.ts
├── tools/
│ ├── SocialMediaStudioToolV2.tsx # Main plugin UI (6 tabs)
│ ├── SocialMediaStudioTool.tsx # Graphics Studio tab
│ └── ConcertDayGenerator.tsx # Concert day generator
├── components/
│ ├── studio/ # Graphics Studio UI
│ │ ├── ContentSelectionPanel.tsx
│ │ ├── FormatStylePanel.tsx
│ │ ├── TextContentPanel.tsx
│ │ ├── DesignSettingsPanel.tsx
│ │ ├── LogoSettingsPanel.tsx
│ │ ├── PreviewActionsPanel.tsx
│ │ ├── PreviewCanvas.tsx
│ │ ├── StyleThumbnail.tsx
│ │ ├── Slider.tsx
│ │ └── constants.ts
│ └── social-media/ # Social posting UI
│ ├── types.ts
│ ├── InstagramFormatSelector.tsx
│ ├── DeviceMockup.tsx
│ ├── SettingsTab.tsx
│ └── DraftsTemplatesTab.tsx
├── schemas/
│ ├── socialMediaTemplate.ts
│ ├── lateApiSettings.ts
│ └── index.ts
└── actions/
├── generateSocialGraphicsAction.ts
├── generateNewsSocialGraphicsAction.ts
├── generateAfterShowSocialGraphicsAction.ts
└── index.ts
| Dependency | Version |
|---|---|
| Sanity Studio | v3+ |
| React | 18 or 19 |
| @sanity/ui | v2+ |
| @sanity/icons | v3+ |
| Node.js | 18+ |
| @napi-rs/canvas | (optional) — server-side rendering |
| Late | (optional) — social media scheduling |
git clone https://github.com/netz-sg/sanity-social-media-studio.git
cd sanity-social-media-studio
npm install
npm run build # Production build
npm run dev # Watch modeContributions are welcome! Please open an issue or submit a pull request.
- Fork the repository
- Create your feature branch —
git checkout -b feature/amazing-feature - Commit your changes —
git commit -m 'Add amazing feature' - Push to the branch —
git push origin feature/amazing-feature - Open a Pull Request




