
Sanity CMS-guide: Sådan bruger vi det til at udgive på 10 sprog
Vi har publiceret over 400 indholdselementer på tværs af 4 websteder og 10 sprog via Sanity CMS. Her er hvad vi har lært, lige fra skemadesign til automatiseret flersproget udgivelse.
Sanity CMS er en headless indholdsplatform bygget omkring struktureret indhold, en realtids Content Lake og en tilpasselig React-baseret editor kaldet Sanity Studio. Den bruger GROQ til forespørgsler, Portable Text til rige indhold og schema-as-code til indholdsmodellering. Denne guide dækker opsætning, skemadesign, GROQ, Portable Text, flersproget arkitektur og prissætning.
Hvad er Sanity CMS?
Sanity er en platform for struktureret indhold, som teamet hos Sanity.io kalder et "indholdsstyresystem". I modsætning til traditionelle CMS'er, der gemmer HTML-blobs i en database, gemmer Sanity hvert enkelt indholdselement som struktureret JSON i en administreret backend kaldet Content Lake. Du forespørger den med GROQ eller GraphQL og gengiver indholdet i enhver frontend, du ønsker: Next.js, React Native, Svelte, en mobilapp, et CLI-værktøj – hvad som helst.
Virksomhederne, der bruger det, spænder bredt. Nike, Figma, Puma og Cloudflare kører Sanity i enterpriseskala. Startups bruger det, fordi den gratis tier er virkelig brugbar (mere om prissætning senere). Vi bruger det, fordi intet andet gav os fleksibiliteten til at opbygge en fuldt automatiseret 10-sprogs udgivelsespipeline.
Content Lake-arkitektur
Content Lake er Sanitets administrerede backend. Tænk på det som en hosted dokumentbutik, der synkroniseres i realtid på tværs af alle tilsluttede klienter. Når en redaktør ændrer et afsnit i Sanity Studio, ser en anden redaktør det øjeblikkeligt – ingen gem-knap, ingen merge-konflikter, ingen databasemigrationer.
Under motorhjelmen gemmes dokumenter som struktureret JSON med typede felter. Hver mutation spores gennem en transaktionslog, så du får fuld versionshistorik som standard. Realtidssynkroniseringen bruger en lytterbaseret arkitektur (beskrevet i Sanitets GitHub-arkitekturdokumentation), der pusher ændringer til alle abonnenter via RxJS observables.
Hvad adskiller dette fra f.eks. en PostgreSQL-database med et REST API? Content Lake håndterer indholdsmodellering, adgangskontrol, CDN-caching, billedtransformationer og realtidssamarbejde som en enkelt administreret service. Du kører ikke migrationer. Du administrerer ikke replikaer. Du definerer blot skemaer og forespørger indhold.
Sanity Studio: Din tilpasselige editor
Sanity Studio er en open source React-applikation, der fungerer som din redigeringsgrænseflade. Det er ikke et hosted admin-panel; det er en React-app, der lever i din kodebase. Du kan tilpasse alle aspekter af den: brugerdefinerede inputkomponenter, betingede felter, dokumenthandlinger, strukturbyggermønstre og plugins.
Realtidssamarbejde er indbygget. Flere redaktører kan arbejde på det samme dokument samtidigt med tilstedeværelsesindikatorer og liveopdateringer. Hvis du har brugt Google Docs, er oplevelsen lignende; du ser andre menneskers markører og ændringer i realtid.
Vi deployer vores Studio med npx sanity deploy, hvilket hoster det på Sanitets CDN på et brugerdefineret subdomæne. Du kan også self-hoste det, da det blot er en React-app. Vi rangerede Sanity højt i vores sammenligning af headless CMS primært på grund af Studios fleksibilitet.
Sådan opsætter du et Sanity-projekt
For at opsætte Sanity CMS skal du installere CLI'en med npm create sanity@latest, vælge en projektskabelon, konfigurere dine skemafiler og køre npx sanity dev for at starte Studio lokalt. Hele processen tager under 5 minutter.
Forudsætninger og installation
Du skal bruge Node.js 18+ og npm (eller pnpm). Det er alt. Kør init-kommandoen:
npm create sanity@latest
# You'll be prompted for:
# - Login method (Google, GitHub, email)
# - Project name
# - Dataset name (default: "production")
# - Project template (blog, ecommerce, clean)
# - TypeScript? (recommended: yes)CLI'en stiller et projekt op med alt, hvad du behøver. Her er hvordan projektstrukturen ser ud:
Projektstruktur forklaret
my-sanity-project/
├── schemas/ # Your content schemas (this is where you'll spend time)
│ ├── index.ts # Schema registry -- imports and exports all types
│ ├── post.ts # Document type definitions
│ └── blockContent.ts # Rich text / Portable Text config
├── sanity.config.ts # Main config -- plugins, Studio structure, dataset
├── sanity.cli.ts # CLI config -- project ID, dataset
├── package.json
└── tsconfig.jsonFilen sanity.config.ts er dit entry point. Her er en minimal version:
// 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 },
})Pluginnet visionTool() giver dig en GROQ-legplads inde i Studio, som du vil bruge konstant under udviklingen.
Deploying af dit Studio
Start lokalt med npx sanity dev (kører på localhost:3333). Når du er klar til at dele med redaktører, skal du deploye til Sanitets CDN:
npx sanity deploy
# Prompts for a hostname, e.g., "my-blog"
# Deploys to https://my-blog.sanity.studioPro tip: kør npx sanity@latest schema deploy efter enhver skemaændring. Dette uploader dit skema til Sanitets API, hvilket aktiverer funktioner som GraphQL API'et og skemabevidste værktøjer (inklusive MCP-serveren, som vi dækker senere).
Skemadesign i Sanity CMS
Sanity-skemaer defineres som JavaScript- eller TypeScript-objekter i din kodebase. Hvert skema specificerer en dokumenttype med felter, valideringsregler og brugerdefinerede inputkomponenter. Ændringer i skemaer er øjeblikkelige; der kræves ingen databasemigrationer. Dette er "schema-as-code"-tilgangen, og det var det, der solgte os på Sanity frem for Contentful.
Feltyper og validering
Sanity leveres med et rigt sæt af feltyper. Her er dem, vi bruger mest:
| Feltype | Brugstilfælde | Eksempel |
|---|---|---|
string | Kort tekst, titler, slugs | Posttitel, forfatternavn |
text | Flerlinjet almindelig tekst | Uddrag, beskrivelser |
number | Heltal, flydende tal | Læsetid, sorteringsrækkefølge |
boolean | Toggles | Fremhævet flag, kladdestatus |
array | Lister, rig tekst (Portable Text) | Brødtekst, tags |
reference | Links til andre dokumenter | Forfatter, kategori |
image | Billeder med metadata | Forsidebillede med alt-tekst |
slug | URL-venlige strenge | Auto-genereret fra titel |
object | Nestede feltgrupper | SEO-felter (metaTitle + metaDescription) |
date / datetime | Datoer | Udgivelsesdato |
Ethvert felt understøtter validering via et validation callback. Du kan håndhæve obligatoriske felter, min/max-værdier, regex-mønstre og brugerdefinerede 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'),
})Brugerdefinerede bloktyper (vores produktionseksempler)
Her bliver Sanity interessant, og hvor 0 ud af 6 konkurrerende guides viser nogen kode. I vores produktionsskema definerer vi fem brugerdefinerede bloktyper inde i body-arrayet: block (standardtekst), table, codeBlock, chartBlock og inlineImage.
Her er vores 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',
},
],
})Og her er hvordan body-feltet refererer til alle vores brugerdefinerede typer sammen:
// schemas/fields/body.ts
defineField({
name: 'body',
title: 'Body',
type: 'array',
of: [
{ type: 'block' }, // Standard Portable Text (paragraphs, headings, lists)
{ type: 'table' }, // @sanity/table plugin
{ type: 'codeBlock' }, // Our custom code block
{ type: 'chartBlock' }, // Data visualization (bar, line, pie)
{ type: 'inlineImage' }, // Images with alt text and captions
],
})Dette giver vores redaktører et rigt indholdsværktøjssæt, mens hvert element forbliver typet og forespørgeligt. En chartBlock er ikke bare et uigennemsigtigt HTML-embed; det er strukturerede data med felterne chartType, title, dataPoints og dataLabels. Det betyder noget, når du forsøger at gengive det samme indhold på web, e-mail og mobil.
Best practices for skemaorganisering
Hold skemaerne modulære. Vi opdeler vores efter type i filer: schemas/documents/post.ts, schemas/objects/codeBlock.ts, schemas/objects/chartBlock.ts. Importér dem alle 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 vigtigste indsigt, vi fik fra at arbejde med struktureret indhold: dit skema ER din indholdsmodel. Hvis du tænker på det som context engineering for dit indholdsteam, vil du træffe bedre designbeslutninger. Hvert felt, du tilføjer, bør tjene et formål, enten for redaktører, for gengivelse eller for forespørgsler.
GROQ: Sanitets forespørgselssprog
GROQ (Graph-Relational Object Queries) er Sanitets open source-forespørgselssprog til filtrering, joining og projicering af JSON-dokumenter. Den grundlæggende syntaks er *[filter]{projection}; vælg alle dokumenter, der matcher et filter, og form derefter outputtet. Det er mere koncist end GraphQL til Sanity-specifikke forespørgsler og efter vores erfaring hurtigere at lære.
Grundlæggende forespørgsler: Filtrer og projicer
Den enkleste forespørgsel henter alle dokumenter af en type:
// Fetch all posts -- just title and slug
*[_type == "post"]{
title,
"slug": slug.current
}
// Filter by language, expand author reference
*[_type == "post" && language == "en"]{
title,
"slug": slug.current,
"authorName": author->name,
"authorImage": author->image,
"categoryTitle": category->title,
publishedAt
}Operatoren -> følger referencer. author->name betyder "følge author-referencen og returnere name-feltet". Ingen separate forespørgsler, ingen N+1-problemer, ingen JOINs – det er alt sammen ét udtryk.
Joins, sortering og pagination
Til vores blog-indekssider har vi brug for sorterede, paginerede posts med udvidede referencer:
// Paginated posts with full 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] giver dig de første 10 resultater (0-indekseret, eksklusiv slutning). | order(publishedAt desc) sorterer nyeste først. Projektionen former outputtet til at inkludere præcis det, din frontend har brug for, ikke mere.
Du kan teste alle disse forespørgsler interaktivt ved hjælp af Vision-pluginnet inde i Sanity Studio. Det er uvurderligt under udviklingen. For flere mønstre, se GROQ-cheat sheetet.
GROQ vs GraphQL
Sanity understøtter både GROQ og GraphQL. Hvornår skal du bruge hvad?
GROQ er Sanitets oprindelige sprog. Det håndterer joins, projektioner og beregnede felter i en enkelt forespørgselsstreng. Det er det, Content Lake er optimeret til.
GraphQL er tilgængeligt, efter at du har deployet dit skema (npx sanity@latest schema deploy). Brug det, når du har brug for standardiserede værktøjer, for eksempel hvis din frontend allerede bruger Apollo Client, eller hvis dit team kender GraphQL, men ikke GROQ.
Vi bruger udelukkende GROQ. Det er mere udtryksfuldt for Sanity-data, og Vision-pluginnet gør debugging af forespørgsler trivielt.
Portable Text: Rigtigt rigt indhold
Portable Text er Sanitets specifikation for struktureret rig tekst. I stedet for at gemme indhold som HTML-strenge gemmer det et array af typede blokke – afsnit, overskrifter, billeder, kodestykker, tabeller – hver som et JSON-objekt. Dette gør indholdet gengiveligt i ethvert framework, på enhver platform, i ethvert format.
Datastrukturen
Sådan ser et afsnit og en kodeblok ud 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({ ... })"
}
]Hver blok har en _type og en _key. Standard tekstblokke bruger "block" med children spans (som understøtter marks som fed, kursiv og links). Brugerdefinerede blokke, som vores codeBlock, chartBlock, table og inlineImage, bruger deres egen _type og bærer strukturerede felter.
Hvorfor betyder det noget? Fordi HTML er et gengivelsesformat, ikke et lagringsformat. Hvis du gemmer <h2>Title</h2><p>Some <strong>text</strong></p> i din database, har du låst dig fast i web-gengivelse. Du kan ikke rent ekstrahere det til en mobilapp, et nyhedsbrev, en PDF eller en AI-agents kontekstvindue. Portable Text adskiller indhold fra præsentation. Portable Text-specifikationen er open source; det er ikke en Sanity-lock-in.
Brugerdefinerede blokke i produktion
Vores pipeline konverterer Markdown til Portable Text ved hjælp af et Python-script (scripts/md_to_portable_text.py). Konverteren håndterer standardblokke plus vores fire brugerdefinerede typer:
table, bruger@sanity/tableplugin-skemaet. Rækker og celler gemmes som strukturerede data.codeBlock, sprog og kode som separate felter, hvilket muliggør syntaksfremhævning ved gengivelse.chartBlock, diagramtype, titel, akseetiketter, serienavne og datapunkter som struktureret JSON. Frontenden gengiver disse med Chart.js.inlineImage, alt-tekst, kilde og valgfri billedtekst som separate felter.
Denne struktur betyder, at vi kan forespørge efter alle kodeeksempler i vores blog (*[body[]._type == "codeBlock"]), finde posts med diagrammer eller ekstrahere alle billeder med manglende alt-tekst, alt sammen via GROQ.
Gengivelse af Portable Text
På frontenden skal du bruge @portabletext/react (eller Svelte/Vue-ækvivalenterne). Du registrerer brugerdefinerede komponenter for hver bloktype:
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>
),
},
}
// In your component:
<PortableText value={post.body} components={components} />Det er den fulde gengivelsespipeline. Komponenten PortableText håndterer standardblokke (afsnit, overskrifter, lister, marks) automatisk. Du behøver kun at definere brugerdefinerede komponenter for dine brugerdefinerede typer.
Flersproget indhold med Sanity CMS
Sanity understøtter flersproget indhold gennem dokumentniveau-lokalisering (separate dokumenter per sprog linket af en kanonisk reference) eller feltniveau-lokalisering (oversatte felter inden for ét dokument). Dokumentniveau fungerer bedre til SEO og storskala udgivelse; det er det, vi bruger på tværs af vores 10-sprogs pipeline.
Dokumentniveau vs. feltniveau-lokalisering
| Aspekt | Dokumentniveau | Feltniveau |
|---|---|---|
| Tilgang | Separat dokument per sprog | Alle oversættelser i ét dokument |
| SEO | Hvert dokument har sin egen URL/slug | Enkel URL, sværere at servere sider per sprog |
| Forespørgselskompleksitet | Enkle filtre: language == "de" | Nested feltadgang: title.de |
| Indholdsstørrelse | Små, fokuserede dokumenter | Ét stort dokument med alle sprog |
| Bedst til | Blogposts, sider, SEO-drevet indhold | Små UI-strenge, labels, metadata |
| Vores dom | Vi bruger dette til alt | Kun til delte UI-strenge |
Vi valgte dokumentniveau-lokalisering, fordi hver oversættelse får sin egen slug, sin egen URL og sine egne metadata. Den tyrkiske version af et post om Supabase vs. Firebase får slugen supabase-firebase-karsilastirma, korrekt tyrkisk, ikke et URL-parameter-hack.
Vores 10-sprogs pipeline-arkitektur
Sådan fungerer vores automatiserede pipeline: vi skriver et post på engelsk og oversætter det derefter til 9 yderligere sprog (tysk, fransk, hollandsk, spansk, tyrkisk, italiensk, svensk, norsk, arabisk). Hver oversættelse går gennem Markdown-konvertering, Portable Text-generering og Sanity API-publicering.
Arkitekturen ser sådan ud:
- Skriv, engelsk Markdown med YAML frontmatter
- Oversæt, AI-oversættelse til 9 sprog (verificeret for fuldstændighed og diakritiske tegn)
- Konverter, Python-script konverterer hver
.md-fil til Portable Text JSON - Udgiv, API-kald til Sanity: opret dokument, upload billeder, patch referencer
Hvert dokument har et language-felt og en canonicalPost-reference, der peger på den engelske original. Her er GROQ-forespørgslen for at hente et post og alle dets oversættelser:
// Fetch a post and all its translations
*[_type == "post" && slug.current == "sanity-cms-guide" && language == "en"][0]{
title,
language,
"translations": *[
_type == "post" &&
canonicalPost._ref == ^._id
]{
title,
language,
"slug": slug.current
}
}Skemasiden er ligetil: et language-felt med en enum over understøttede sprog:
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 faldgrube, vi lærte på den hårde måde: udgiv det engelske dokument først, og patch derefter canonicalPost-referencer på oversættelser ved hjælp af det udgivne dokument-ID, ikke drafts.-præfikset. Sanity behandler kladder og udgivne dokumenter som separate enheder internt.
For flere detaljer om, hvordan denne pipeline forbinder til Model Context Protocol, se næste afsnit.
Sanity AI-funktioner: MCP, Canvas og Agent Context
Sanity positionerer sig selv som indholdsstyresystemet for AI-æraen. Nøgle-AI-funktioner inkluderer en MCP-server, der tillader AI-agenter at læse og skrive indhold, Canvas til AI-assisteret redigering inde i Studio og Agent Context, der giver produktions-AI-agenter mulighed for at forespørge struktureret indhold med skemabevidsthed.
MCP-serverintegration
Sanity MCP-serveren lader AI-agenter – Claude Code, Cursor, Windsurf og andre – interagere med dit Sanity-workspace programmatisk. Agenter kan læse skemaer, udføre GROQ-forespørgsler, oprette dokumenter og administrere indhold uden brugerdefinerede API-wrappers.
Vi bruger Sanity MCP-serveren dagligt i vores indholdspipeline. Vores AI-agenter forespørger skemaet for at forstå dokumentstrukturen, henter eksisterende posts for at finde interne linkmuligheder og publicerer nye dokumenter. MCP-protokollen giver agenter skemabevidsthed; de ved, hvilke felter der findes, hvilke typer de forventer, og hvilke valideringsregler der gælder. Hvis du bygger AI-agenter til forretnings workflows, er dette et kraftfuldt mønster.
Agent Context til produktions-AI
Agent Context er en separat funktion til AI-integrationer i produktionskvalitet. I modsætning til MCP-serveren (som er designet til udviklerværktøjer) giver Agent Context read-only, scoped adgang til AI-agenter, der har brug for at forespørge dit indhold i runtime – tænk chatbots, anbefalingsmotorer eller systemer til indholdspersonliggørelse.
Forskellen betyder noget: MCP er til build-time og redaktionelle workflows (skemabevidste udviklingsværktøjer), mens Agent Context er til runtime-indholdsadgang med korrekt godkendelse og rate limiting.
Sanitets strukturerede indhold giver det en reel fordel her. Et WordPress-site gemmer indhold som HTML-blobs; en AI-agent skal parse HTML for at forstå indholdet. Sanity gemmer typede JSON-dokumenter med definerede skemaer. En agent kan forespørge *[_type == "product" && category == "electronics"]{name, price, features} og få rene, strukturerede data tilbage. Ingen scraping, ingen parsing, ingen gætteri.
Sådan bruger vi Sanity hos Techsy
Dette er ikke et hypotetisk afsnit. Vi kører Sanity CMS på tværs af 4 produktionswebsteder og udgiver på 10 sprog med en automatiseret pipeline, vi har bygget over det sidste år. Her er arkitekturen.
Vores indholdspipeline-arkitektur
Pipeline'en går fra research til publiceret post på tværs af alle 10 sprog:
- Research, søgeordsanalyse, identifikation af konkurrentgab, SERP-mønstre
- Brief, struktureret skrive-spec med sektionvejledning, ordantal, interne links
- Skriv, producer engelsk Markdown med YAML frontmatter
- Konverter, Python-script transformerer Markdown til Portable Text JSON med vores 5 brugerdefinerede bloktyper
- Udgiv, API-kald til Sanity:
createOrReplacedokument, upload billeder til Sanity CDN, patch forfatter/kategori-referencer - Oversæt, AI-oversættelse til 9 sprog, verificeret for fuldstændighed
- Udgiv oversættelser, samme konverter/udgiv-flow per sprog, med
canonicalPost-reference patched til den engelske original
Det brugerdefinerede skema understøtter typerne block, table, codeBlock, chartBlock og inlineImage, alle defineret som produktions-Sanity-skemaobjekter med valideringsregler. Blandt de AI-værktøjer til startups vi har testet, har denne Sanity-baserede pipeline været den mest pålidelige til struktureret indhold i stor skala.
Lærdomme fra 400+ publicerede stykker
Et par ting, vi wished someone had told us:
Rækkefølgen for reference-patching betyder noget. Sanity-referencer kan ikke pege på dokumenter, der endnu ikke eksisterer. Udgiv det engelske post først, og opret derefter oversættelser med canonicalPost pegende på det engelske dokuments udgivne ID. Vi brød dette flere gange i begyndelsen.
Skemadeployment er per workspace. Hvis du kører flere Sanity-projekter (vi kører 4), skal du deploye skemaer til hvert enkelt separat: npx sanity@latest schema deploy per projektkonfiguration.
Den gratis tier er ægte. Vi kørte to af vores fire sites på den gratis plan i måneder. 20 brugere, 500K API-forespørgsler/md., 100K CDN-forespørgsler – det er nok til et rigtig produktionssite, ikke bare et legetøjsprojekt.
Portable Text-konvertering er flaskehalsen. Markdown til Portable Text er ikke trivielt. Nestede lister, tabeller inde i blockquotes, kodeblokke med specialtegn – edge cases overalt. Vi har itereret på vores konverter-script i måneder.
Har du brug for hjælp til at opsætte Sanity til dit projekt? Vi har bygget flersprogede indholdspipelines til 4 produktionssites. Få en gratis konsultation
Oversigt over Sanity CMS-priser
Sanity tilbyder tre planer: Free (20 brugere, 500K API-forespørgsler/md.), Growth ($15/bruger/md. med avancerede roller og planlagte kladder) og Enterprise (brugerdefineret prissætning med SLA og compliance-funktioner). Den gratis tier er den mest generøse på markedet for headless CMS.
| Funktion | Free | Growth ($15/bruger/md.) | Enterprise |
|---|---|---|---|
| Brugere | 20 | 50 | Ubegrænset |
| API-forespørgsler | 500K/md. | 2,5M/md. | Brugerdefineret |
| CDN-forespørgsler | 100K/md. | 500K/md. | Brugerdefineret |
| Roller | Kun Admin | Admin, Developer, Editor, Contributor | Brugerdefinerede roller |
| Samarbejde | Realtidsredigering | + Planlagt udgivelse, kladder | + Workflows |
| Support | Community | Dedikeret + SLA | |
| Compliance | , | , | SOC 2, HIPAA |
På den gratis tier kører vi to af vores sites uden at ramme grænser. Growth-planen til $15/bruger/md. tilføjede rollebaseret adgang (vigtigt, når vi fik ikke-tekniske redaktører) og planlagt udgivelse. Viewers er gratis på Growth, hvilket er en nice touch; du straffes ikke for at give stakeholders read-access.
Hvordan sammenligner dette med konkurrenter?
| Funktion | Sanity Free | Contentful Free | Strapi Cloud Free | Payload Cloud |
|---|---|---|---|---|
| Brugere | 20 | 1 | 1 | 1 |
| Indholdstyper | Ubegrænset | 48 | Ubegrænset | Ubegrænset |
| API-kald | 500K/md. | Inkluderet | Inkluderet | Inkluderet |
| Brugerdefinerede typer | Ja | Begrænset | Ja | Ja |
| Pris for vækst | $15/bruger/md. | $300/md. | $29/md. | $50/md. |
Sanitys 20-bruger gratis tier er exceptionel. Contentful begrænser dig til 1 bruger på free og hopper til $300/md. for deres Team-plan. Hvis du er en startup eller et lille team, lader Sanitys gratis plan dig køre rigtige produktionsarbejdsbyrder uden at bruge noget.
Sanity tilbyder også et startup-program, der giver berettigede startups et års gratis Growth-adgang. Det er værd at ansøge om, hvis du kvalificerer dig.
Ofte stillede spørgsmål
Hvad er Sanity CMS, og hvordan virker det?
Sanity CMS er en headless indholdsplatform, der gemmer strukturerede JSON-dokumenter i en administreret backend kaldet Content Lake. Du redigerer indhold via Sanity Studio (en tilpasselig React-app), forespørger det med GROQ eller GraphQL og gengiver det i ethvert frontend-framework. Indhold synkroniseres i realtid på tværs af alle tilsluttede klienter.
Er Sanity CMS gratis?
Ja. Sanitys gratis tier inkluderer 20 brugere, 500K API-forespørgsler per måned og 100K CDN-forespørgsler – den mest generøse gratis plan blandt headless CMS-platforme. Growth-planen koster $15 per bruger per måned og tilføjer rollebaseret adgang, planlagt udgivelse og højere grænser. Enterprise-prissætning er brugerdefineret.
Hvad er forskellen mellem Sanity og Contentful?
Sanity bruger schema-as-code (skemaer lever i din kodebase), GROQ til forespørgsler og en fuldt tilpasselig open source Studio. Contentful bruger GUI-baseret indholdsmodellering, GraphQL og en hosted editor med mindre tilpasning. Sanitys gratis tier inkluderer 20 brugere mod Contentfuls 1. Contentful har et større plugin-markedsplads.
Er Sanity CMS godt for begyndere?
Sanity Studio er intuitivt for indholdsredaktører; redigeringsoplevelsen kræver ingen teknisk viden. Opsætning af skemaer kræver dog JavaScript- eller TypeScript-kundskaber. Sanity tilbyder fremragende dokumentation, projektskabeloner og en community Slack med aktiv support. Start med npm create sanity@latest og en blogskabelon.
Kan jeg self-hoste Sanity?
Sanity Studio er fuldt self-hostbart, fordi det er en open source React-applikation. Du kan deploye det til Vercel, Netlify eller enhver statisk hosting-udbyder. Content Lake-backenden er en administreret service; der er ingen self-hosting-mulighed for datalaget. Dette er en tradeoff: du får nul infrastrukturadministration, men ingen on-premises datakontrol.
Hvilken type database bruger Sanity?
Sanitys Content Lake er ikke en traditionel SQL- eller NoSQL-database. Det er en administreret dokumentbutik, der gemmer indhold som struktureret JSON med et GROQ-forespørgselslag ovenpå. Du interagerer ikke direkte med den underliggende database; du interagerer gennem Sanitys API'er. Dokumenter har fuld versionshistorik og indbygget realtidssynkronisering.
Er Sanity CMS open source?
Sanity Studio er open source under MIT-licensen; du kan forke det, tilpasse det og self-hoste det. Content Lake-backenden er proprietær SaaS. GROQ-forespørgselssprog-specifikationen er også open source, publiceret på GitHub. Portable Text-specifikationen er ligeledes open source og vedligeholdes på portabletext.org.
Hvad er Portable Text i Sanity?
Portable Text er Sanitys specifikation for struktureret rig tekst. I stedet for at gemme indhold som HTML-strenge repræsenterer det afsnit, overskrifter, billeder og brugerdefinerede blokke som typede JSON-objekter i et array. Dette gør indholdet portabelt på tværs af frameworks og platforme. Du kan definere brugerdefinerede bloktyper som kodestykker, diagrammer og tabeller med deres egne strukturerede felter.
Hvad er GROQ, og hvordan er det anderledes end GraphQL?
GROQ (Graph-Relational Object Queries) er Sanitys oprindelige forespørgselssprog. Dens syntaks, *[filter]{projection}, er mere koncis end GraphQL til Sanity-data, med indbygget support for joins via ->-operatoren og beregnede felter. GraphQL er også tilgængeligt for teams, der foretrækker standardiserede værktøjer eller allerede bruger Apollo Client.
Hvordan håndterer Sanity flersproget indhold?
Sanity understøtter dokumentniveau-lokalisering (separate dokumenter per sprog linket af kanoniske referencer) og feltniveau-lokalisering (oversatte felter inden for ét dokument). Dokumentniveau er bedre til SEO, fordi hver oversættelse får sin egen URL og metadata. Vi bruger dokumentniveau-lokalisering til at udgive på tværs af 10 sprog med automatiserede oversættelses- og udgivelsespipelines.