בעת פיתוח פרויקט web מורכב — חנות מקוונת עם אלפי מוצרים או פורטל רב-לשוני — אנו נתקלים לעתים קרובות במגבלות של CMS מסורתי. WordPress או Bitrix דורשות תוספים לשדות מותאמים אישית, ושאילתות מורכבות מתחילות לפגר. זה מוביל לשבועות של פיתוח מותאם אישית ולבעיות ביצועים. הצוות שלנו משתמש ב-Sanity — CMS headless הכתוב ב-TypeScript, שבו סכמת התוכן מתוארת בקוד, ושאילתות מבוצעות באמצעות השפה העצמאית GROQ. גישה זו מעניקה גמישות של פתרונות ארגוניים עם מהירות טעינה של SPA. זמני טעינת הדף מופחתים ב-40% בהשוואה ל-CMS מונוליטי, ומספר בקשות ה-API יורד פי 2-3 בזכות שאילתות GROQ פרוג'קטיביות.
אנו מפתחים על Sanity מאז השקתו והטמענו 10+ פרויקטים — מדפי נחיתה ועד מרקטפלייסים. כל פרויקט עובר בדיקת קוד ובדיקת עומסים. אנו מבטיחים איכות: מודלי תוכן נשארים ניתנים להרחבה גם לאחר ההשקה.
אילו בעיות אנו פותרים עם Sanity?
מורכבות של מודל תוכן. ב-Sanity, אנו מתארים סוגי מסמכים ב-TypeScript: עבור כל שדה אנו מגדירים סוג, ולידציה ויחסים. לדוגמה, עבור מאמר — כותרת, slug, מחבר (reference), תמונה, קטגוריות (מערך של references), וגוף בפורמט Portable Text. הסכמה מנוהלת ב-Git, קלה לתחזוקה ואינה דורשת מיגרציות.
ביצועי שאילתות. GROQ (Graph-Relational Object Queries) מאפשרת בחירת שדות ויחסים נדרשים בלבד, תוך הימנעות משאילתות N+1. שאילתה מורכבת עם סינון, מיון ופאג'ינציה מתבצעת במילישניות. בהשוואה ל-REST APIs של מתחרים, GROQ מהירה פי 2-3 עבור בחירות עמוקות.
שיתוף פעולה בזמן אמת. Sanity Studio הוא עורך React שמסנכרן שינויים באופן מיידי. שני עורכים יכולים לערוך בו-זמנית את אותו מסמך ללא התנגשויות. זה מאיץ את הפקת התוכן ב-30% ומפחית את מספר הגרסאות.
כיצד אנו מגדירים את Sanity עבור הפרויקט שלך?
התהליך מתחיל באנליטיקה: אנו חוקרים את מבנה התוכן שלך, דרישות העיצוב ומקרי השימוש. לאחר מכן אנו מתכננים את סכמת הנתונים — מגדירים סוגי מסמכים, שדות, ולידציה ויחסים. אנו מגדירים את Studio: התאמת מבנה התפריט, תוספים מותאמים אישית (למשל, ל-SEO או מנהל מדיה). אנו משתלבים עם ה-frontend שבחרת — לרוב עם Next.js App Router, תוך שימוש ב-next-sanity עבור תמונות CDN ו-ISR.
דוגמה לסכמת מסמך מינימלית:
// schemas/post.ts
import { defineType, defineField } from 'sanity'
export const postType = defineType({
name: 'post',
title: 'Статья',
type: 'document',
fields: [
defineField({
name: 'title',
title: 'Заголовок',
type: 'string',
validation: rule => rule.required().min(5).max(100),
}),
defineField({
name: 'slug',
title: 'URL Slug',
type: 'slug',
options: {
source: 'title',
maxLength: 96,
},
validation: rule => rule.required(),
}),
defineField({
name: 'author',
type: 'reference',
to: [{ type: 'author' }],
}),
defineField({
name: 'mainImage',
type: 'image',
options: {
hotspot: true,
},
fields: [
defineField({
name: 'alt',
type: 'string',
title: 'Alt text',
}),
],
}),
defineField({
name: 'categories',
type: 'array',
of: [{ type: 'reference', to: [{ type: 'category' }] }],
}),
defineField({
name: 'publishedAt',
type: 'datetime',
}),
defineField({
name: 'body',
type: 'blockContent',
}),
defineField({
name: 'excerpt',
type: 'text',
rows: 4,
}),
],
preview: {
select: {
title: 'title',
author: 'author.name',
media: 'mainImage',
},
prepare: ({ title, author, media }) => ({
title,
subtitle: author ? `by ${author}` : '',
media,
}),
},
})הגדרת Studio כוללת התאמת מבנה ותוספים:
// sanity.config.ts
import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
import { visionTool } from '@sanity/vision'
import { postType } from './schemas/post'
import { authorType } from './schemas/author'
import { categoryType } from './schemas/category'
export default defineConfig({
name: 'default',
title: 'My Site CMS',
projectId: process.env.SANITY_STUDIO_PROJECT_ID!,
dataset: 'production',
plugins: [
structureTool({
structure: S =>
S.list()
.title('Контент')
.items([
S.documentTypeListItem('post').title('Статьи'),
S.documentTypeListItem('author').title('Авторы'),
S.divider(),
S.documentTypeListItem('category').title('Категории'),
]),
}),
visionTool(),
],
schema: {
types: [postType, authorType, categoryType]
},
}) מדוע Sanity מנצחת את המתחרים?
Sanity עולה על חלופות בזכות הארכיטקטורה שלה: כל הנתונים מאוחסנים ב-Content Lake הענני, שמתרחב אוטומטית ונשמר במטמון ב-CDN. תמונות עוברות דרך תמונת CDN מובנית עם תמיכה ב-WebP ואופטימיזציה אוטומטית. שאילתות GROQ מאפשרות הקרנות בצד הלקוח, מה שמפחית את עומס השרת. בניגוד ל-Strapi, ל-Sanity אין צוואר בקבוק של נקודת קצה REST אחת — ניתן לבקש כל שדה באופן סלקטיבי.
תיעוד Sanity: GROQ מספקת דרך גמישה לשאילת תוכן מובנה עם הקרנות ומסננים.
| שכבה | טכנולוגיה |
|---|---|
| CMS | Sanity 3.x |
| Studio | מוטמע ב-Next.js או פריסה נפרדת |
| Frontend | Next.js App Router |
| תמונות | Sanity Image CDN |
| חיפוש | GROQ / Algolia |
| פריסה | Vercel (Next.js) + sanity.io (Studio) |
| קריטריון | Sanity | Strapi | Directus |
|---|---|---|---|
| סוג | ענן בלבד | אירוח עצמי / ענן | אירוח עצמי / ענן |
| שפת שאילתות | GROQ (דמוית SQL) | REST / GraphQL | REST / GraphQL |
| שיתוף פעולה בזמן אמת | מובנה | דרך תוספים | מוגבל |
| התאמת עורך | מלא (React) | מוגבל | חלקי |
מה כלול בעבודה?
- עיצוב סכמת נתונים — הגדרת סוגי מסמכים, שדות, ולידציה והפניות.
- הגדרת Studio — מבנה תפריט מותאם אישית, תוספים (vision, dashboard), אייקונים.
- אינטגרציית Frontend — לקוח המשתמש ב-
// schemas/post.ts import { defineType, defineField } from 'sanity' export const postType = defineType({ name: 'post', title: 'Статья', type: 'document', fields: [ defineField({ name: 'title', title: 'Заголовок', type: 'string', validation: rule => rule.required().min(5).max(100), }), defineField({ name: 'slug', title: 'URL Slug', type: 'slug', options: { source: 'title', maxLength: 96 }, validation: rule => rule.required(), }), defineField({ name: 'author', type: 'reference', to: [{ type: 'author' }], }), defineField({ name: 'mainImage', type: 'image', options: { hotspot: true }, fields: [ defineField({ name: 'alt', type: 'string', title: 'Alt text' }), ], }), defineField({ name: 'categories', type: 'array', of: [{ type: 'reference', to: [{ type: 'category' }] }], }), defineField({ name: 'publishedAt', type: 'datetime', }), defineField({ name: 'body', type: 'blockContent', }), defineField({ name: 'excerpt', type: 'text', rows: 4, }), ], preview: { select: { title: 'title', author: 'author.name', media: 'mainImage' }, prepare: ({ title, author, media }) => ({ title, subtitle: author ? `by ${author}` : '', media, }), }, }), תמיכה ב-CDN, ISR, revalidation. - תיעוד — תיאור סכמה, דוגמאות שאילתות GROQ, מדריך לעורכים.
- הדרכת צוות — ביצוע סשן על עבודה עם Studio ו-GROQ.
- קוד ב-GitHub — עם CI/CD לפריסה אוטומטית של Studio ו-frontend.
דוגמה לרשימת בדיקה לפני השקה
- בדוק סכמה לתלות מעגלית
- אמת את כל המסמכים עם
// sanity.config.ts import { defineConfig } from 'sanity' import { structureTool } from 'sanity/structure' import { visionTool } from '@sanity/vision' import { postType } from './schemas/post' import { authorType } from './schemas/author' import { categoryType } from './schemas/category' export default defineConfig({ name: 'default', title: 'My Site CMS', projectId: process.env.SANITY_STUDIO_PROJECT_ID!, dataset: 'production', plugins: [ structureTool({ structure: S => S.list() .title('Контент') .items([ S.documentTypeListItem('post').title('Статьи'), S.documentTypeListItem('author').title('Авторы'), S.divider(), S.documentTypeListItem('category').title('Категории'), ]), }), visionTool(), ], schema: { types: [postType, authorType, categoryType] }, }) - הגדר הרשאות גישה לעורכים
- בדוק שאילתות על מערך נתונים בייצור
- ניטור ביצועים באמצעות Sanity Metrics
תהליך
- אנליזה — חקר אסטרטגיית תוכן, הגדרת סוגי מסמכים ויחסים.
- עיצוב — יצירת סכמת נתונים, הגדרת Studio.
- פיתוח — כתיבת קוד frontend, הגדרת שאילתות ו-middleware.
- בדיקות — אימות ביצועים, תצוגה נכונה, בדיקת עומסים.
- פריסה — עלייה לאוויר, הגדרת ניטור.
לוחות זמנים ועלות
פרויקט בסיסי עם 3-5 סוגי מסמכים ו-frontend של Next.js אורך 2-3 שבועות. פרויקט מורכב עם תוספי Studio מותאמים אישית ו-Visual Editing אורך 4-6 שבועות. העלות מחושבת באופן אישי לאחר הבריף. אנו נעריך את הפרויקט שלך — פשוט צור קשר. קבל ייעוץ על Sanity ולמד כיצד ארכיטקטורת headless מאיצה פיתוח.







