← Alla nyheter
ARTIKEL
22 september 2026

Varför vi byggde Osprey, vårt headless CMS

Osprey håller innehållsscheman i TypeScript, levererar publicerat innehåll vid build-tillfället och svarar med 404, inte ett behörighetsfel, för allt som är privat.

De flesta headless-CMS tvingar fram ett val: ett verktyg med visuell editor som behandlar schemat som en databas-blob som genererades en gång, eller en egenbyggd lösning där varje sidladdning anropar CMS:et live. Vi byggde Osprey, vårt eget headless-CMS, för att slippa det valet: ett innehållsschema som versionshanteras som kod och en sajt som levereras som statiska filer. Här är vad koden faktiskt gör, inte bara vad presentationen säger.

Rader av höga bokhyllor fyllda med böcker i ett bibliotek
Foto: Szeronine (CC BY 4.0), Wikimedia Commons.

Scheman är kod, inte en databas-blob

I Osprey definieras en collection i TypeScript och ligger i samma repo som resten av applikationen. Det innebär samma versionshantering, samma kodgranskning och samma end-to-end-typer som ett team redan tillämpar på sin applikationskod, nu även på innehållsmodellen. Adminvyn är en bekvämlighet för att redigera poster; den är aldrig den enda sanningskällan för själva schemat.

Innehåll levereras vid build-tillfället, inte vid varje anrop

Loadern @osprey/astro hämtar publicerade poster från Ospreys publika REST-endpoint under build och lämnar dem till Astros content collections, utan att en API-nyckel behövs för den publika läsningen. Den levererade sajten är ren statisk HTML: Osprey är ett build-tidsberoende, inte ett runtime-beroende. Om en build körs medan CMS:et är långsamt eller onåbart behåller loadern de redan cachade posterna i stället för att låta builden misslyckas.

Privat som standard, osynlig vid nekande

En collection exponeras i det publika API:et bara när dess egen access.read-regel uttryckligen tillåter en anonym anropare; allt annat förblir privat. En förfrågan mot en privat collection, eller mot ett opublicerat dokument, kommer tillbaka som en 404 i stället för ett behörighetsfel, så att API:et aldrig bekräftar att en privat collection ens existerar.

SEO-metadata följer med varje post

Varje post som det publika API:et returnerar bär ett sammanslaget SEO-objekt: postens egen titel, beskrivning, Open Graph- och Twitter-taggar samt kanonisk URL har företräde, och arbetsytans standardvärden fyller i det som saknas. Samma payload innehåller den upplösta robots-direktivet och hreflang-länkar till varje publicerad översättning av sidan, så att en frontend kan rendera sina metataggar utan att bygga om den logiken själv.

En driftsättning, flera tenanter

Osprey är multi-tenant: en enda driftsättning kan betjäna fler än en sajt, var och en begränsad till sin egen tenant. På de publika innehållsvägarna avgörs vilken tenant som ska läsas från utifrån själva förfrågans host-header, inte utifrån ett värde som klienten skickar med, så att en anonym förfrågan inte kan läsa en annan tenants innehåll genom att skicka ett annat tenant-id. Varje databasfråga som API:et kör begränsas internt till tenanten, i stället för att varje handler själv behöver hålla reda på det.

GDPR i praktiken, inte bara ett påstående

Osprey har en endpoint för rätten att bli glömd som redigerar bort personuppgifter — formulärinskick, aktörer i granskningsloggen, användarkonton — för en angiven e-postadress eller id, begränsat till en tenant. En separat export-endpoint tar fram ett komplett manifest över en tenants innehåll för dataportabilitetsförfrågningar. Den inbyggda cookiesamtyckeshanteraren behandlar bara strikt nödvändiga cookies som alltid aktiva och sätter varje annan kategori till nekad som standard tills besökaren samtycker, där "avvisa alla" har samma visuella tyngd som "acceptera alla". Eftersom Osprey är egenhostat kan ett team också köra det helt på europeisk infrastruktur; särskilda garantier för EU-datalagring ingår i produktens enterprise-plan, inte som standard i varje installation.

Headless med flit

Osprey lagrar innehåll och levererar det som JSON; det har ingen uppfattning om hur en sajt ska se ut. Ett team kan bygga frontend i Astro, Next.js eller vilken generator för statiska sajter som helst som kan anropa ett REST-API, och använda Osprey enbart som innehållslager bakom den. De aktuella planerna, inklusive de egenhostade och enterprise-nivåerna, listas på Ospreys produktsida.

Vad du bör göra

  • Definiera din innehållsmodell som TypeScript-collections och versionshantera den tillsammans med applikationskoden.
  • Sätt en explicit access.read-regel på varje collection du vill exponera via det publika API:et; lämna den osatt för att hålla collectionen privat.
  • Lägg till loadern @osprey/astro, eller anropa REST-API:et direkt, så att innehåll hämtas vid build-tillfället i stället för vid varje anrop.
  • Sätt SEO-fält per post bara där de behöver avvika från sajtens standardvärden, och låt standardvärdena fylla i resten.
  • Använd de inbyggda endpointerna för export och rätten att bli glömd för dataportabilitets- och raderingsförfrågningar, i stället för att bygga egna.
  • Om enbart EU-hosting spelar roll för er efterlevnad, hosta Osprey på europeisk infrastruktur eller fråga om enterprise-planens garantier för datalagring.

Källor: Ospreys produktsida, getosprey.dev.