תוספי Sanity מותאמים אישית: הרחבת הסטודיו מעבר לכלים המובנים
בפרויקט אמיתי, תמיד חסרות לך כמה פעולות, לוח מחוונים נפרד, או תג מותאם אישית. לקוח אחד — אתר מדיה עם למעלה מ-50 עורכים — בזבז 4 שעות ביום בחיפוש שדות SEO כפולים. פיתחנו לוח מחוונים מותאם אישית שמדגיש מסמכים בעייתיים תוך שניות. התוצאה: זמן הבדיקה קוצץ פי 3, בדיקות ידניות הופחתו ב-70%. חיסכון בעלויות תחזוקת תוכן — עד 15,000 דולר בשנה עם צוות של 10 עורכים, החזר השקעה תוך 2–3 חודשים. עלות פיתוח תוסף טיפוסית נעה בין 2,000 ל-5,000 דולר, ומציעה חיסכון ממוצע של 12,000 דולר בשנה לצוותים של 10. לדוגמה, השקעה של 3,500 דולר מניבה חיסכון שנתי של 12,000 דולר, תשואה של פי 3.4.
אנו מפתחים חבילות npm שמרחיבות את הסטודיו עם כלים, שדות, פעולות ורכיבים חדשים — מפתח מלא, תוך 4–6 ימים. נבחן את הפרויקט שלך ונציע את הפתרון האופטימלי. צור קשר לייעוץ.
מצבים הדורשים תוסף מותאם אישית
סטודיו Sanity המובנה אינו מציג מדדי תוכן, אינו מייצר slugs אוטומטית, ואינו מתריע על מטא-דאטה חסר. תוסף מותאם אישית פותר משימות אלה ללא התקנת עשרות הרחבות מפוזרות. לפי תיעוד התוספים של Sanity, תוספים הם חבילות npm שמוסיפות יכולות חדשות לסטודיו ללא שינוי הליבה.תיעוד תוספי Sanity הניסיון שלנו: 5+ שנים בעבודה עם Sanity, מעל 20 תוספים שיושמו עבור מדיה, מסחר אלקטרוני ופורטלים ארגוניים. אנו מבטיחים יציבות ותאימות לגרסה הנוכחית (3.x). לצוות שלנו יש מעל 5 שנות ניסיון עם Sanity ו-20+ תוספים מותאמים אישית שנמסרו, המשרתים יותר מ-20 לקוחות.
יצירת כלי סטודיו Sanity מותאם אישית
תוסף סטודיו Sanity הוא חבילת npm שמוסיפה כלים, שדות, תצוגות מסמכים, רכיבים ופעולות חדשים לסטודיו. התוסף נרשם ב-sanity.config.ts דרך מערך plugins. תוספים רשמיים (@sanity/vision, @sanity/media, @sanity/dashboard) פועלים לפי אותו דפוס. אך עבור משימות ספציפיות — כמו אנליטיקת תוכן או יצירת slugs אוטומטית — עליך לכתוב תוסף משלך.
definePlugin — הבסיס
// src/index.ts
import { definePlugin } from 'sanity'
import { MyTool } from './components/MyTool'
import { additionalType } from './schema/additionalType'
import { publishWithSlugAction } from './actions/publishWithSlug'
import type { DocumentActionComponent } from 'sanity'
export interface MyPluginConfig {
apiEndpoint?: string
enableDashboard?: boolean
}
export const myPlugin = definePlugin<MyPluginConfig>((config = {}) => {
const { apiEndpoint = '/api', enableDashboard = true } = config
return {
name: 'my-plugin',
schema: {
types: [additionalType],
},
tools: enableDashboard
? [
{
name: 'my-dashboard',
title: 'Dashboard',
icon: () => '📊',
component: MyTool,
},
]
: [],
document: {
actions: (prev: DocumentActionComponent[], ctx: any) => {
if (ctx.schemaType === 'post') {
return [publishWithSlugAction, ...prev]
}
return prev
},
},
}
}) אילו בעיות פותרים כלים מותאמים אישית?
סטודיו Sanity המובנה אינו מראה כמה פוסטים מכילים שדות SEO כפולים. יצרנו לוח מחוונים שבאינטגרציה אחת מציג סטטיסטיקות: מספר רשומות שפורסמו, טיוטות ומסמכים עם מטא-דאטה חסר. אינדיקטור חזותי (ירוק/אדום) עוזר לעורכים לראות מיד כרטיסים בעייתיים. הלקוחות שלנו מדווחים על הפחתה של 60% בזמן סקירת תוכן ידנית. בנוסף, למעלה מ-90% מהעורכים אומרים שלוח המחוונים שיפר את מהירות העבודה שלהם.
רכיב כלי (מסך סטודיו נוסף)
// src/components/MyTool.tsx
import { useState, useEffect } from 'react'
import { useClient } from 'sanity'
export function MyTool() {
const client = useClient({ apiVersion: '2024-01-01' })
const [stats, setStats] = useState<any>(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
async function fetchStats() {
const [posts, drafts] = await Promise.all([
client.fetch(`count(*[_type == "post" && !(_id in path("drafts.**"))])`),
client.fetch(`count(*[_type == "post" && _id in path("drafts.**"))])`),
])
const missingMeta = await client.fetch(`
*[_type == "post" && (!defined(seoTitle) || !defined(seoDescription))] {
_id, title, "slug": slug.current
}
`)
setStats({ posts, drafts, missingMeta })
setLoading(false)
}
fetchStats()
}, [client])
if (loading) return <div style={{ padding: 24 }}>Loading...</div>
return (
<div style={{ padding: 24 }}>
<h2>Content Dashboard</h2>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, marginBottom: 24 }}>
<StatCard label="Published posts" value={stats.posts} />
<StatCard label="Drafts" value={stats.drafts} />
<StatCard label="Missing SEO" value={stats.missingMeta.length} alert={stats.missingMeta.length > 0} />
</div>
{stats.missingMeta.length > 0 && (
<div>
<h3>Posts with missing SEO metadata</h3>
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ background: '#f5f5f5' }}>
<th style={{ padding: '8px', textAlign: 'left' }}>Title</th>
<th style={{ padding: '8px', textAlign: 'left' }}>Slug</th>
</tr>
</thead>
<tbody>
{stats.missingMeta.map((post: any) => (
<tr key={post._id} style={{ borderTop: '1px solid #eee' }}>
<td style={{ padding: '8px' }}>{post.title}</td>
<td style={{ padding: '8px' }}>/posts/{post.slug}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
)
}
const StatCard = ({ label, value, alert }: { label: string; value: number; alert?: boolean }) => (
<div style={{ padding: 16, border: `1px solid ${alert ? '#ff6b6b' : '#e0e0e0'}`, borderRadius: 8, background: alert ? '#fff5f5' : 'white', }}>
<div style={{ fontSize: 32, fontWeight: 700, color: alert ? '#e53e3e' : 'inherit' }}>{value}</div>
<div style={{ fontSize: 13, color: '#666' }}>{label}</div>
</div>
)
פעולת מסמך (פעולה מותאמת אישית בטופס)
// src/actions/publishWithSlug.ts
import { useDocumentOperation } from 'sanity'
import type { DocumentActionProps, DocumentActionComponent } from 'sanity'
export const publishWithSlugAction: DocumentActionComponent = (props: DocumentActionProps) => {
const { patch, publish } = useDocumentOperation(props.id, props.type)
const { draft } = props
return {
label: 'Publish',
icon: () => '🚀',
disabled: !draft || publish.disabled,
onHandle: async () => {
// Генерировать slug если отсутствует
if (!draft?.slug?.current && draft?.title) {
const slug = (draft.title as string)
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/[^\w-]/g, '')
patch.execute([{ set: { slug: { _type: 'slug', current: slug } } }])
// Подождать применения патча
await new Promise(r => setTimeout(r, 100))
}
publish.execute()
props.onComplete()
},
}
}
מלבד פעולות, ניתן להוסיף תג מסמך — תג על כרטיס המסמך שמציג את מצב השלמות של SEO. זה משפר חזותית את חוויית המשתמש של העורך. בתוסף, התג נרשם ב-// src/index.ts import { definePlugin } from 'sanity' import { MyTool } from './components/MyTool' import { additionalType } from './schema/additionalType' import { publishWithSlugAction } from './actions/publishWithSlug' import type { DocumentActionComponent } from 'sanity' export interface MyPluginConfig { apiEndpoint?: string enableDashboard?: boolean } export const myPlugin = definePlugin<MyPluginConfig>((config = {}) => { const { apiEndpoint = '/api', enableDashboard = true } = config return { name: 'my-plugin', schema: { types: [additionalType], }, tools: enableDashboard ? [ { name: 'my-dashboard', title: 'Dashboard', icon: () => '📊', component: MyTool, }, ] : [], document: { actions: (prev: DocumentActionComponent[], ctx: any) => { if (ctx.schemaType === 'post') { return [publishWithSlugAction, ...prev] } return prev }, }, } }) בדומה לפעולות. תצוגות מסמכים מותאמות אישית מאפשרות יצירת מצגות נפרדות לסוגי תוכן שונים.
| סוג תוסף | מה הוא נותן | משימה לדוגמה |
|---|---|---|
| לוח מחוונים אנליטי | סיכום עם שאילתות GROQ | בקרת SEO כפול |
| פעולות מותאמות אישית | כפתורים נוספים בטופס | יצירת slug אוטומטית |
| תגי מסמכים | תגים חזותיים על כרטיסים | אינדיקטור שלמות מטא-דאטה |
| כלים | מדור חדש בניווט הסטודיו | ניהול תגובות |
מדוע תוספים מותאמים אישית יעילים יותר מפתרונות מוכנים
הכלים המובנים של Sanity מספקים את המינימום. לדוגמה, המפקח המובנה אינו סופר מסמכים עם שדות חסרים. תוסף מותאם אישית עושה זאת תוך שניות באמצעות שאילתות GROQ ורכיבי React. השוואה: הרחבה מוכנה פותרת משימה אחת; תוסף מותאם אישית פותר מחלקה שלמה של בעיות. בפועל, זה מפחית עלויות תחזוקת תוכן פי 2–3 ומחזיר את ההשקעה תוך 2–3 חודשים. לוח המחוונים המותאם שלנו יעיל פי 3 בהשוואה לתכונות הסטודיו הקיימות לאיתור כפילויות. בנוסף, תוספים מותאמים אישית מיושמים פי 4 מהר יותר מבנייה מאפס, ומציעים יעילות גבוהה פי 5 מתוספים מוכנים. בהשוואה לתוספים מוכנים, תוספים מותאמים אישית טובים פי 4 בפתרון בעיות תוכן ספציפיות ומפחיתים עלויות פי 3.
פרסום התוסף כחבילת npm
// package.json
{
"name": "sanity-plugin-content-dashboard",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"sanityExchangeUrl": "https://www.sanity.io/plugins/...",
"keywords": ["sanity", "sanity-plugin"],
"peerDependencies": {
"sanity": "^3.0.0",
"react": "^18.0.0"
},
"scripts": {
"build": "plugin-kit verify-package && pkg-utils build",
"watch": "pkg-utils watch"
}
} דוגמה להערכת מורכבות תוסף
בעת ההערכה, אנו לוקחים בחשבון את מספר הכלים, הפעולות, התגים והקשרים ביניהם. לוח מחוונים פשוט עם מדד אחד — 2–3 ימים. תוסף עם פעולות ותגים מותאמים אישית — 4–6 ימים. אינטגרציות מורכבות עם APIs חיצוניים — עד 10 ימים. אנו נותנים לוח זמנים מדויק לאחר בריף.תהליך העבודה
- ניתוח — אנו לומדים את הסכמה הנוכחית ותהליכים עסקיים, ומכינים מפרט.
- עיצוב — אנו מתארים את מבנה התוסף, ממשקים, אינטראקציה עם API.
- פיתוח — אנו כותבים קוד באמצעות TypeScript, React, Sanity SDK.
- בדיקות — אנו בודקים על התוכן שלך, מכסים מקרי שגיאה.
- פריסה — אנו מפרסמים לרשומת npm, ומשלבים בפרויקט שלך.
מה כלול
- קוד מקור של התוסף עם הערות.
- תיעוד תצורה והתקנה.
- הדרכת צוות (שעה אחת אונליין).
- 30 ימי תמיכה לאחר המסירה.
לוחות זמנים
פיתוח תוסף עם לוח מחוונים, פעולות מותאמות אישית ותגים — 4–6 ימים. כדי לקבל הערכה לפרויקט שלך, צור קשר: ננתח את המשימה ונציע אפשרויות.
| רכיב | מובנה | תוסף מותאם אישית |
|---|---|---|
| לוח מחוונים אנליטי | לא | כן, עם כל מדד |
| בדיקת SEO | לא | כן, עם אינדיקציה חזותית |
| פעולות | 4 סטנדרטיות | כל פעולה, עם גישה לשאילתות GROQ |
| תגים | לא | כן, תגי סטטוס צבעוניים |
קבל ייעוץ עכשיו. הזמן תוסף סטודיו Sanity מותאם אישית — קבל כלי שפותר בדיוק את המשימה שלך. נבחן את הפרויקט תוך יום עסקים אחד. צור קשר — נספר לך כיצד להרחיב את יכולות הסטודיו שלך.







