
Sanity CMS-guide: Så publicerar vi på 10 språk
Vi har publicerat över 400 innehållsposter på 4 webbplatser och 10 språk via Sanity CMS. Det här är vad vi lärt oss — från schemadesign till automatiserad flerspråkig publicering.
Sanity CMS är en headless innehållsplattform byggd kring strukturerat innehåll, ett realtids-Content Lake och en anpassningsbar React-baserad editor kallad Sanity Studio. Den använder GROQ för frågor, Portable Text för rikt innehåll och schema-as-code för innehållsmodellering. Den här guiden täcker installation, schemadesign, GROQ, Portable Text, flerspråkig arkitektur och prissättning.
Vad är Sanity CMS?
Sanity är en strukturerad innehållsplattform — vad teamet på Sanity.io kallar ett "content operating system." Till skillnad från traditionella CMS:er som lagrar HTML-blobbar i en databas lagrar Sanity varje innehållsdel som strukturerad JSON i ett hanterat backend kallat Content Lake. Du frågar det med GROQ eller GraphQL och renderar innehållet i vilket frontend som helst: Next.js, React Native, Svelte, en mobilapp, ett CLI-verktyg — vad som helst.
Företagen som använder det spänner hela skalan. Nike, Figma, Puma och Cloudflare kör Sanity i enterprise-skala. Startups använder det för att gratisnivån faktiskt går att använda på riktigt (mer om prissättning senare). Vi använder det för att inget annat gav oss flexibiliteten att bygga en helt automatiserad publiceringsprocess för 10 språk.
Content Lake-arkitekturen
Content Lake är Sanity:s hanterade backend. Tänk på det som ett hostat dokumentlager som synkroniseras i realtid mellan alla anslutna klienter. När en redaktör ändrar ett stycke i Sanity Studio ser en annan redaktör det direkt — ingen spara-knapp, inga sammanslagningskonflikter, inga databasmigreringar.
Under huven lagras dokument som strukturerad JSON med typade fält. Varje mutation spåras genom en transaktionslogg, så du får fullständig versionshistorik som standard. Realtidssynken använder en lyssnare-baserad arkitektur (beskriven i Sanity:s GitHub-arkitekturdokumentation) som skickar ändringar till alla prenumeranter via RxJS observables.
Vad gör det annorlunda från, säg, en PostgreSQL-databas med ett REST-API? Content Lake hanterar innehållsmodellering, åtkomstkontroll, CDN-cachelagring, bildtransformationer och realtidssamarbete som en enda hanterad tjänst. Du kör inga migreringar. Du hanterar inga repliker. Du definierar bara scheman och frågar innehåll.
Sanity Studio: Din anpassningsbara editor
Sanity Studio är ett open source React-program som fungerar som ditt redigeringsgränssnitt. Det är inte en hostad adminpanel — det är en React-app som lever i din kodbas. Du kan anpassa varje aspekt av det: anpassade inputkomponenter, villkorliga fält, dokumentåtgärder, structure builder-mönster och plugins.
Realtidssamarbete är inbyggt. Flera redaktörer kan arbeta på samma dokument samtidigt med närvaroindikatorer och live-uppdateringar. Om du har använt Google Docs är upplevelsen liknande — du ser andra personers markörer och ändringar i realtid.
Vi deployar vår Studio med npx sanity deploy, vilket hostar den på Sanity:s CDN på en anpassad subdomän. Du kan också egenhostra den eftersom den bara är en React-app. Vi rankade Sanity högt i vår jämförelse av headless CMS till stor del på grund av Studio:s flexibilitet.
Hur du installerar ett Sanity-projekt
För att installera Sanity CMS installerar du CLI med npm create sanity@latest, väljer en projektmall, konfigurerar dina schemafiler och kör npx sanity dev för att starta Studio lokalt. Hela processen tar under 5 minuter.
Förutsättningar och installation
Du behöver Node.js 18+ och npm (eller pnpm). Det är allt. Kör init-kommandot:
npm create sanity@latest
# Du kommer att få frågor om:
# - Inloggningsmetod (Google, GitHub, e-post)
# - Projektnamn
# - Dataset-namn (standard: "production")
# - Projektmall (blogg, e-handel, tom)
# - TypeScript? (rekommenderat: ja)CLI:t ställer upp ett projekt med allt du behöver. Så här ser projektstrukturen ut:
Projektstruktur förklarad
my-sanity-project/
├── schemas/ # Dina innehållsscheman (här kommer du att lägga tid)
│ ├── index.ts # Schemaregister — importerar och exporterar alla typer
│ ├── post.ts # Dokumenttypsdefinitioner
│ └── blockContent.ts # Rich text / Portable Text-konfiguration
├── sanity.config.ts # Huvudkonfiguration — plugins, Studio-struktur, dataset
├── sanity.cli.ts # CLI-konfiguration — projekt-ID, dataset
├── package.json
└── tsconfig.jsonFilen sanity.config.ts är din startpunkt. Här är en minimal variant:
// sanity.config.ts
import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
import { visionTool } from '@sanity/vision'
import { schemaTypes } from './schemas'
export default defineConfig({
name: 'default',
title: 'My Blog',
projectId: 'your-project-id',
dataset: 'production',
plugins: [structureTool(), visionTool()],
schema: { types: schemaTypes },
})Plugin-et visionTool() ger dig en GROQ-lekplats inbyggd i Studio — du kommer att använda den hela tiden under utvecklingen.
Deploya din Studio
Starta lokalt med npx sanity dev (körs på localhost:3333). När du är redo att dela med redaktörer deployar du till Sanity:s CDN:
npx sanity deploy
# Frågar efter ett värdnamn, t.ex. "my-blog"
# Deployar till https://my-blog.sanity.studioProtips: kör npx sanity@latest schema deploy efter varje schemaändring. Det laddar upp ditt schema till Sanity:s API, vilket aktiverar funktioner som GraphQL-API:et och schemamedveten verktygslåda (inklusive MCP-servern som vi tar upp senare).
Schemadesign i Sanity CMS
Sanity-scheman definieras som JavaScript- eller TypeScript-objekt i din kodbas. Varje schema specificerar en dokumenttyp med fält, valideringsregler och anpassade inputkomponenter. Ändringar i scheman sker direkt — inga databasmigreringar krävs. Det här är "schema-as-code"-metoden, och det är det som övertygade oss att välja Sanity framför Contentful.
Fälttyper och validering
Sanity levereras med en rik uppsättning fälttyper. Här är de vi använder mest:
| Fälttyp | Användningsfall | Exempel |
|---|---|---|
string | Kort text, titlar, slugs | Inläggstitel, författarnamn |
text | Flerradig klartext | Utdrag, beskrivningar |
number | Heltal, flyttal | Lästid, sorteringsordning |
boolean | Växlar | Utvalt-flagga, draftstatus |
array | Listor, rich text (Portable Text) | Brödinnehåll, taggar |
reference | Länkar till andra dokument | Författare, kategori |
image | Bilder med metadata | Omslagsbild med alt-text |
slug | URL-vänliga strängar | Autogenererad från titel |
object | Nästlade fältgrupper | SEO-fält (metaTitle + metaDescription) |
date / datetime | Datum | Publiceringsdatum |
Varje fält stöder validering via en validation-callback. Du kan tvinga fram obligatoriska fält, min/max-värden, regex-mönster och anpassade regler:
defineField({
name: 'seoDescription',
title: 'Meta Description',
type: 'string',
validation: (Rule) =>
Rule.required()
.min(145)
.max(160)
.warning('Meta description should be 145-160 characters'),
})Anpassade blocktyper (våra produktionsexempel)
Här blir Sanity intressant — och där 0 av 6 konkurrerande guider visar någon kod. I vårt produktionsschema definierar vi fem anpassade blocktyper inuti body-arrayen: block (standardtext), table, codeBlock, chartBlock och inlineImage.
Här är vår codeBlock-definition:
// schemas/objects/codeBlock.ts
import { defineType } from 'sanity'
export const codeBlock = defineType({
name: 'codeBlock',
title: 'Code Block',
type: 'object',
fields: [
{
name: 'language',
title: 'Language',
type: 'string',
options: {
list: [
{ title: 'JavaScript', value: 'javascript' },
{ title: 'TypeScript', value: 'typescript' },
{ title: 'Python', value: 'python' },
{ title: 'Bash', value: 'bash' },
{ title: 'JSON', value: 'json' },
{ title: 'GROQ', value: 'groq' },
],
},
},
{
name: 'code',
title: 'Code',
type: 'text',
},
],
})Och här är hur body-fältet refererar till alla våra anpassade typer tillsammans:
// schemas/fields/body.ts
defineField({
name: 'body',
title: 'Body',
type: 'array',
of: [
{ type: 'block' }, // Standard Portable Text (stycken, rubriker, listor)
{ type: 'table' }, // @sanity/table-plugin
{ type: 'codeBlock' }, // Vår anpassade kodblock
{ type: 'chartBlock' }, // Datavisualisering (stapel, linje, cirkel)
{ type: 'inlineImage' }, // Bilder med alt-text och bildtexter
],
})Det ger våra redaktörer en rik innehållsverktygslåda och håller samtidigt varje element typat och sökbart. Ett chartBlock är inte bara en ogenomskinlig HTML-embed — det är strukturerad data med fält för chartType, title, dataPoints och dataLabels. Det spelar roll när du försöker rendera samma innehåll på webben, i e-post och på mobil.
Bästa praxis för schemaorganisation
Håll scheman modulära. Vi delar upp våra i filer efter typ: schemas/documents/post.ts, schemas/objects/codeBlock.ts, schemas/objects/chartBlock.ts. Importera dem alla i schemas/index.ts:
// schemas/index.ts
import { post } from './documents/post'
import { codeBlock } from './objects/codeBlock'
import { chartBlock } from './objects/chartBlock'
import { inlineImage } from './objects/inlineImage'
export const schemaTypes = [post, codeBlock, chartBlock, inlineImage]Den viktigaste insikten vi fick från att arbeta med strukturerat innehåll: ditt schema ÄR din innehållsmodell. Om du tänker på det som context engineering för ditt innehållsteam fattar du bättre designbeslut. Varje fält du lägger till bör fylla ett syfte — antingen för redaktörer, för rendering eller för sökning.
GROQ: Sanity:s frågespråk
GROQ (Graph-Relational Object Queries) är Sanity:s open source-frågespråk för att filtrera, sammanfoga och projicera JSON-dokument. Grundsyntaxen är *[filter]{projektion} — välj alla dokument som matchar ett filter och forma sedan utdata. Det är mer kortfattat än GraphQL för Sanity-specifika frågor och, i vår erfarenhet, snabbare att lära sig.
Grundläggande frågor: Filter och projektion
Den enklaste frågan hämtar alla dokument av en typ:
// Hämta alla inlägg — bara titel och slug
*[_type == "post"]{
title,
"slug": slug.current
}
// Filtrera efter språk, expandera författarreferens
*[_type == "post" && language == "en"]{
title,
"slug": slug.current,
"authorName": author->name,
"authorImage": author->image,
"categoryTitle": category->title,
publishedAt
}Operatorn -> följer referenser. author->name betyder "följ författarreferensen och returnera namnfältet." Inga separata frågor, inga N+1-problem, inga JOIN:ar — det är allt ett uttryck.
Sammanfogningar, sortering och paginering
För våra bloggindexsidor behöver vi ordnade, paginerade inlägg med expanderade referenser:
// Paginerade inlägg med fullständig metadata
*[_type == "post" && language == "en"] | order(publishedAt desc) [0...10] {
title,
"slug": slug.current,
excerpt,
publishedAt,
readTime,
"author": author->{name, image},
"category": category->{title, "slug": slug.current},
"coverImage": coverImage{
"src": asset->url,
alt
}
}[0...10] ger dig de första 10 resultaten (nollindexerat, exklusivt slut). | order(publishedAt desc) sorterar nyast först. Projektionen formar utdata för att inkludera exakt vad ditt frontend behöver — inget mer.
Du kan testa alla dessa frågor interaktivt med Vision-plugin:et inuti Sanity Studio. Det är ovärderligt under utvecklingen. För fler mönster, se GROQ cheat sheet.
GROQ vs GraphQL
Sanity stöder både GROQ och GraphQL. När ska du använda vilket?
GROQ är Sanity:s ursprungsspråk. Det hanterar sammanfogningar, projektioner och beräknade fält i en enda frågesträng. Det är vad Content Lake är optimerat för.
GraphQL är tillgängligt efter att du har deployat ditt schema (npx sanity@latest schema deploy). Använd det när du behöver standardiserad verktygslåda — till exempel om ditt frontend redan använder Apollo Client, eller om ditt team kan GraphQL men inte GROQ.
Vi använder GROQ uteslutande. Det är mer expressivt för Sanity-data och Vision-plugin:et gör felsökning av frågor trivialt.
Portable Text: Rich-innehåll på rätt sätt
Portable Text är Sanity:s specifikation för strukturerad rich text. I stället för att lagra innehåll som HTML-strängar lagrar det en array av typade block — stycken, rubriker, bilder, kodavsnitt, tabeller — vart och ett som ett JSON-objekt. Det gör innehållet renderbart i vilket ramverk, vilken plattform och vilket format som helst.
Datastrukturen
Så här ser ett stycke och ett kodblock ut som Portable Text-JSON:
[
{
"_type": "block",
"_key": "a1b2c3",
"style": "normal",
"markDefs": [],
"children": [
{
"_type": "span",
"_key": "d4e5f6",
"text": "Here's an example of our pipeline config:",
"marks": []
}
]
},
{
"_type": "codeBlock",
"_key": "g7h8i9",
"language": "typescript",
"code": "export default defineConfig({ ... })"
}
]Varje block har en _type och en _key. Standardtextblock använder "block" med barn-spans (som stöder markeringar som fetstil, kursiv och länkar). Anpassade block — som våra codeBlock, chartBlock, table och inlineImage — använder sin egen _type och bär strukturerade fält.
Varför spelar det här roll? För att HTML är ett renderingsformat, inte ett lagringsformat. Om du lagrar <h2>Title</h2><p>Some <strong>text</strong></p> i din databas har du låst dig till webbrendering. Du kan inte på ett rent sätt extrahera det för en mobilapp, ett e-postnyhetsbrev, en PDF eller en AI-agents kontextfönster. Portable Text separerar innehåll från presentation. Portable Text-specifikationen är open source — det är inte ett Sanity-beroende.
Anpassade block i produktion
Vår pipeline konverterar Markdown till Portable Text med ett Python-skript (scripts/md_to_portable_text.py). Konverteraren hanterar standardblock, plus våra fyra anpassade typer:
table— använder@sanity/table-plugin-schemats. Rader och celler lagras som strukturerad data.codeBlock— språk och kod som separata fält, vilket möjliggör syntaxmarkering vid rendering.chartBlock— diagramtyp, titel, axeletiketter, serienamn och datapunkter som strukturerad JSON. Frontend:et renderar dessa med Chart.js.inlineImage— alt-text, källa och valfri bildtext som separata fält.
Den här strukturen gör att vi kan fråga efter alla kodexempel i vår blogg (*[body[]._type == "codeBlock"]), hitta inlägg med diagram, eller extrahera alla bilder med saknad alt-text — allt genom GROQ.
Rendera Portable Text
På frontend:et använder du @portabletext/react (eller Svelte/Vue-ekvivalenterna). Du registrerar anpassade komponenter för varje blocktyp:
import { PortableText } from '@portabletext/react'
const components = {
types: {
codeBlock: ({ value }) => (
<pre className={`language-${value.language}`}>
<code>{value.code}</code>
</pre>
),
chartBlock: ({ value }) => <Chart data={value} />,
inlineImage: ({ value }) => (
<figure>
<img src={value.src} alt={value.alt} />
{value.caption && <figcaption>{value.caption}</figcaption>}
</figure>
),
},
}
// I din komponent:
<PortableText value={post.body} components={components} />Det är hela renderingspipelinen. Komponenten PortableText hanterar standardblock (stycken, rubriker, listor, markeringar) automatiskt. Du definierar bara anpassade komponenter för dina anpassade typer.
Flerspråkigt innehåll med Sanity CMS
Sanity stöder flerspråkigt innehåll via lokalisering på dokumentnivå (separata dokument per språk länkade av en kanonisk referens) eller lokalisering på fältnivå (översatta fält inom ett dokument). Dokumentnivå fungerar bättre för SEO och storskalig publicering — det är vad vi använder i vår 10-språkiga pipeline.
Lokalisering på dokument- vs. fältnivå
| Aspekt | Dokumentnivå | Fältnivå |
|---|---|---|
| Metod | Separat dokument per språk | Alla översättningar i ett dokument |
| SEO | Varje dokument har sin egen URL/slug | En URL, svårare att servera per-språk-sidor |
| Frågekomplexitet | Enkla filter: language == "de" | Nästlad fältåtkomst: title.de |
| Innehållsstorlek | Små, fokuserade dokument | Ett stort dokument med alla språk |
| Bäst för | Blogginlägg, sidor, SEO-drivet innehåll | Små UI-strängar, etiketter, metadata |
| Vårt omdöme | Vi använder det för allt | Bara för delade UI-strängar |
Vi valde lokalisering på dokumentnivå för att varje översättning får sin egen slug, sin egen URL och sin egen metadata. Den svenska versionen av ett inlägg om Supabase vs Firebase får slugen supabase-firebase-jamforelse — riktig svenska, inte ett URL-parameter-hack.
Vår 10-språkiga pipeline-arkitektur
Så här fungerar vår automatiserade pipeline: vi skriver ett inlägg på engelska och översätter det sedan till 9 ytterligare språk (tyska, franska, holländska, spanska, turkiska, italienska, svenska, norska, arabiska). Varje översättning går igenom Markdown-konvertering, Portable Text-generering och Sanity API-publicering.
Arkitekturen ser ut så här:
- Skriva — Engelska Markdown med YAML-frontmatter
- Översätta — AI-översättning till 9 språk (verifierad för fullständighet och diakritiska tecken)
- Konvertera — Python-skript konverterar varje
.md-fil till Portable Text-JSON - Publicera — API-anrop till Sanity: skapa dokument, ladda upp bilder, patcha referenser
Varje dokument har ett language-fält och en canonicalPost-referens som pekar på det engelska originalet. Här är GROQ-frågan för att hämta ett inlägg och alla dess översättningar:
// Hämta ett inlägg och alla dess översättningar
*[_type == "post" && slug.current == "sanity-cms-guide" && language == "en"][0]{
title,
language,
"translations": *[
_type == "post" &&
canonicalPost._ref == ^._id
]{
title,
language,
"slug": slug.current
}
}Schemasidan är okomplicerad — ett language-fält med en enum av stödda språk:
defineField({
name: 'language',
title: 'Language',
type: 'string',
options: {
list: [
{ title: 'English', value: 'en' },
{ title: 'German', value: 'de' },
{ title: 'French', value: 'fr' },
{ title: 'Dutch', value: 'nl' },
{ title: 'Spanish', value: 'es' },
{ title: 'Turkish', value: 'tr' },
{ title: 'Italian', value: 'it' },
{ title: 'Swedish', value: 'sv' },
{ title: 'Norwegian', value: 'no' },
{ title: 'Arabic', value: 'ar' },
],
},
validation: (Rule) => Rule.required(),
})En fallgrop vi lärde oss på det hårda sättet: publicera det engelska dokumentet först och patcha sedan canonicalPost-referenser på översättningar med det publicerade dokument-ID:t — inte drafts.-prefixet. Sanity behandlar draft- och publicerade dokument som separata entiteter internt.
För mer information om hur den här pipelinen kopplas till Model Context Protocol, se nästa avsnitt.
Sanity AI-funktioner: MCP, Canvas och Agent Context
Sanity positionerar sig som innehållsoperativsystemet för AI-eran. Viktiga AI-funktioner inkluderar en MCP-server för att AI-agenter ska kunna läsa och skriva innehåll, Canvas för AI-assisterad redigering inuti Studio och Agent Context för produktions-AI-agenter som ska kunna fråga strukturerat innehåll med schemamedvetenhet.
MCP-serverintegration
Sanity MCP-servern låter AI-agenter — Claude Code, Cursor, Windsurf och andra — interagera med din Sanity-arbetsyta programmatiskt. Agenter kan läsa scheman, köra GROQ-frågor, skapa dokument och hantera innehåll utan anpassade API-omslag.
Vi använder Sanity MCP-servern dagligen i vår innehållspipeline. Våra AI-agenter frågar schemat för att förstå dokumentstrukturen, hämtar befintliga inlägg för att hitta möjligheter till interna länkar och publicerar nya dokument. MCP-protokollet ger agenter schemamedvetenhet — de vet vilka fält som finns, vilka typer de förväntar sig och vilka valideringsregler som gäller. Om du bygger AI-agenter för företag är det här ett kraftfullt mönster.
Agent Context för produktions-AI
Agent Context är en separat funktion för produktionsklassade AI-integrationer. Till skillnad från MCP-servern (som är utformad för utvecklarverktyg) ger Agent Context skrivskyddad, avgränsad åtkomst för AI-agenter som behöver fråga ditt innehåll vid körning — tänk chatbottar, rekommendationsmotorer eller system för innehållspersonalisering.
Skillnaden spelar roll: MCP är för byggtid och redaktionella arbetsflöden (schemamedvetna utvecklingsverktyg), medan Agent Context är för körning av innehållsåtkomst med korrekt autentisering och rate limiting.
Sanity:s strukturerade innehåll ger det en riktig fördel här. En WordPress-sajt lagrar innehåll som HTML-blobbar — en AI-agent måste tolka HTML för att förstå innehållet. Sanity lagrar typade JSON-dokument med definierade scheman. En agent kan fråga *[_type == "product" && category == "electronics"]{name, price, features} och få tillbaka ren, strukturerad data. Ingen skrapning, ingen tolkning, ingen gissning.
Hur vi använder Sanity på Techsy
Det här är inte ett hypotetiskt avsnitt. Vi kör Sanity CMS på 4 produktionswebbplatser och publicerar på 10 språk med en automatiserad pipeline vi byggt under det senaste året. Här är arkitekturen.
Vår innehållspipeline-arkitektur
Pipelinen går från research till publicerat inlägg på alla 10 språk:
- Research — nyckelordsanalys, identifiering av konkurrentluckor, SERP-mönster
- Brief — strukturerad skrivspecifikation med sektionsvägledning, ordantal, interna länkar
- Skriva — producera engelska Markdown med YAML-frontmatter
- Konvertera — Python-skript omvandlar Markdown till Portable Text-JSON med våra 5 anpassade blocktyper
- Publicera — API-anrop till Sanity:
createOrReplace-dokument, ladda upp bilder till Sanity CDN, patcha författar-/kategori-referenser - Översätta — AI-översättning till 9 språk, verifierat för fullständighet
- Publicera översättningar — samma konvertera/publicera-flöde per språk, med
canonicalPost-referens patchad till det engelska originalet
Det anpassade schemat stöder typerna block, table, codeBlock, chartBlock och inlineImage — alla definierade som produktions-Sanity-schemaobjekt med valideringsregler. Bland de AI-verktyg för startups vi testat har den här Sanity-baserade pipelinen varit den mest pålitliga för strukturerat innehåll i stor skala.
Lärdomar från 400+ publicerade poster
Några saker vi önskar att någon hade berättat för oss:
Ordningen för referenspatching spelar roll. Sanity-referenser kan inte peka på dokument som inte finns ännu. Publicera det engelska inlägget först och skapa sedan översättningar med canonicalPost som pekar på det engelska dokumentets publicerade ID. Vi bröt det här flera gånger i början.
Schemadistribution är per arbetsyta. Om du kör flera Sanity-projekt (vi kör 4) måste du distribuera scheman till var och en separat: npx sanity@latest schema deploy per projektkonfiguration.
Gratisnivån är på riktigt. Vi körde två av våra fyra sajter på gratisplanen i månader. 20 användare, 500 000 API-förfrågningar/månad, 100 000 CDN-förfrågningar — det räcker för en riktig produktionssajt, inte bara ett lekprojekt.
Portable Text-konvertering är flaskhalsen. Markdown till Portable Text är inte trivialt. Nästlade listor, tabeller inuti blockquotes, kodblock med specialtecken — kantfall överallt. Vi har itererat på vårt konverteringsskript i månader.
Behöver du hjälp med att ställa in Sanity för ditt projekt? Vi har byggt flerspråkiga innehållspipelines för 4 produktionssajter. Få en gratis konsultation
Sanity CMS-prissättning
Sanity erbjuder tre planer: Free (20 användare, 500 000 API-förfrågningar/månad), Growth ($15/användare/månad med avancerade roller och schemalagda utkast) och Enterprise (anpassad prissättning med SLA och efterlevnadsfunktioner). Gratisnivån är den mest generösa på marknaden för headless CMS.
| Funktion | Free | Growth ($15/anv./mån) | Enterprise |
|---|---|---|---|
| Användare | 20 | 50 | Obegränsat |
| API-förfrågningar | 500K/mån | 2,5M/mån | Anpassat |
| CDN-förfrågningar | 100K/mån | 500K/mån | Anpassat |
| Roller | Bara admin | Admin, Developer, Editor, Contributor | Anpassade roller |
| Samarbete | Realtidsredigering | + Schemalagd publicering, utkast | + Arbetsflöden |
| Support | Community | E-post | Dedikerad + SLA |
| Efterlevnad | — | — | SOC 2, HIPAA |
På gratisnivån kör vi två av våra sajter utan att nå gränserna. Growth-planen till $15/användare/månad lade till rollbaserad åtkomst (viktigt när vi fick icke-tekniska redaktörer) och schemalagd publicering. Tittare är gratis på Growth, vilket är en trevlig detalj — du straffas inte för att ge intressenter läsåtkomst.
Hur jämför det sig med konkurrenter?
| Funktion | Sanity Free | Contentful Free | Strapi Cloud Free | Payload Cloud |
|---|---|---|---|---|
| Användare | 20 | 1 | 1 | 1 |
| Innehållstyper | Obegränsat | 48 | Obegränsat | Obegränsat |
| API-anrop | 500K/mån | Inkluderat | Inkluderat | Inkluderat |
| Anpassade typer | Ja | Begränsat | Ja | Ja |
| Pris för att växa | $15/anv./mån | $300/mån | $29/mån | $50/mån |
Sanity:s gratisnivå med 20 användare är exceptionell. Contentful begränsar dig till 1 användare på gratis och hoppar till $300/månad för deras Team-plan. Om du är en startup eller ett litet team låter Sanity:s gratisplan dig köra riktiga produktionsbelastningar utan att spendera något.
Sanity erbjuder också ett startup-program som ger berättigade startups ett år med gratis Growth-åtkomst. Värt att ansöka om om du kvalificerar dig.
Vanliga frågor
Vad är Sanity CMS och hur fungerar det?
Sanity CMS är en headless innehållsplattform som lagrar strukturerade JSON-dokument i ett hanterat backend kallat Content Lake. Du redigerar innehåll via Sanity Studio (en anpassningsbar React-app), frågar det med GROQ eller GraphQL och renderar det i vilket frontend-ramverk som helst. Innehåll synkroniseras i realtid mellan alla anslutna klienter.
Är Sanity CMS gratis?
Ja. Sanity:s gratisnivå inkluderar 20 användare, 500 000 API-förfrågningar per månad och 100 000 CDN-förfrågningar — den mest generösa gratisplanen bland headless CMS-plattformar. Growth-planen kostar $15 per användare och månad och lägger till rollbaserad åtkomst, schemalagd publicering och högre gränser. Enterprise-prissättning är anpassad.
Vad är skillnaden mellan Sanity och Contentful?
Sanity använder schema-as-code (scheman lever i din kodbas), GROQ för sökning och ett helt anpassningsbart open source-Studio. Contentful använder GUI-baserad innehållsmodellering, GraphQL och en hostad editor med mindre anpassning. Sanity:s gratisnivå inkluderar 20 användare mot Contentful:s 1. Contentful har en större plugin-marknadsplats.
Är Sanity CMS bra för nybörjare?
Sanity Studio är intuitivt för innehållsredaktörer — redigeringsupplevelsen kräver inga tekniska kunskaper. Att sätta upp scheman kräver däremot kunskaper i JavaScript eller TypeScript. Sanity tillhandahåller utmärkt dokumentation, projektmallar och en community Slack med aktivt stöd. Börja med npm create sanity@latest och en bloggmall.
Kan jag egenhostra Sanity?
Sanity Studio kan egenhostas fullt ut eftersom det är en open source React-applikation. Du kan deploya det till Vercel, Netlify eller vilken statisk hostingleverantör som helst. Content Lake-backend:et är en hanterad tjänst — det finns inget alternativ för att egenhostra datalagret. Det är en avvägning: du slipper all infrastrukturhantering men har ingen kontroll över data på plats.
Vilken typ av databas använder Sanity?
Sanity:s Content Lake är inte en traditionell SQL- eller NoSQL-databas. Det är ett hanterat dokumentlager som lagrar innehåll som strukturerad JSON med ett GROQ-frågelager ovanpå. Du interagerar inte med den underliggande databasen direkt — du interagerar via Sanity:s API:er. Dokument har inbyggd fullständig versionshistorik och realtidssynk.
Är Sanity CMS open source?
Sanity Studio är open source under MIT-licensen — du kan forka det, anpassa det och egenhostra det. Content Lake-backend:et är proprietär SaaS. GROQ-frågespråksspecifikationen är också open source, publicerad på GitHub. Portable Text-specifikationen är open source också, underhållen på portabletext.org.
Vad är Portable Text i Sanity?
Portable Text är Sanity:s specifikation för strukturerad rich text. I stället för att lagra innehåll som HTML-strängar representerar det stycken, rubriker, bilder och anpassade block som typade JSON-objekt i en array. Det gör innehållet portabelt mellan ramverk och plattformar. Du kan definiera anpassade blocktyper som kodavsnitt, diagram och tabeller med sina egna strukturerade fält.
Vad är GROQ och hur skiljer det sig från GraphQL?
GROQ (Graph-Relational Object Queries) är Sanity:s ursprungliga frågespråk. Dess syntax — *[filter]{projektion} — är mer kortfattad än GraphQL för Sanity-data, med inbyggt stöd för sammanfogningar via operatorn -> och beräknade fält. GraphQL är också tillgängligt för team som föredrar standardiserad verktygslåda eller redan använder Apollo Client.
Hur hanterar Sanity flerspråkigt innehåll?
Sanity stöder lokalisering på dokumentnivå (separata dokument per språk länkade av kanoniska referenser) och lokalisering på fältnivå (översatta fält inom ett dokument). Dokumentnivå är bättre för SEO eftersom varje översättning får sin egen URL och metadata. Vi använder lokalisering på dokumentnivå för att publicera på 10 språk med automatiserade översättnings- och publiceringsflöden.