Self-hosted · 100% SDK-compatible

The Storyblok API — but it's yours.

Osstblok is a drop-in, self-hosted headless CMS that speaks Storyblok's wire format byte-for-byte. Every @storyblok/* SDK works unchanged. Zero row limits. Zero seat fees. Zero MAU gate.

Stories per space
Users & spaces
$0
per MAU
Docker
One compose file

Everything Storyblok paywalls — removed.

Storyblok's pricing tiers cap stories, seats, traffic, languages and data regions. Self-hosting rips every one of those ceilings out.

No story limits

Ship 1,000 or 1,000,000 stories per space. Your Postgres is the only ceiling.

No seat charges

Invite every dev, editor and translator on the team. Per-user pricing doesn't exist here.

No MAU gate

Serve ten readers or ten million. CDN traffic is your infra bill, not a per-visit tax.

Your data, your region

No EU/US tier split. Data lives exactly where you run the server — and nowhere else.

Pin the version you trust

You own the deploy. Roll forward when you're ready, stay on a known-good build when you're not — the Storyblok SDKs keep working either way.

All the languages, always

i18n, datasource dimensions and translation workflows — on every tier. Because there are no tiers.

Built for teams that ship.

A boring, self-hosted stack with the features you actually need on day one — not after a sales call.

Drop-in compatible

CDN v2, Management API, Bridge protocol, asset pipeline, datasources, i18n, scheduled publish — all byte-for-byte. Point STORYBLOK_API at your instance and ship.

Boring stack, one compose file

Bun + Hono for the API, Nuxt 4 for the admin, Postgres + Drizzle, Minio/S3 for assets, optional Redis. Runs on a 2 GB VPS.

Auth that fits your org

Email + password by default. One env var (OIDC_ISSUER_URL) flips the whole login over to your SSO. Personal access tokens, per-space roles, append-only audit log.

Fast by default

Bun runtime, SQL-native Drizzle queries, optional Redis CDN cache, on-the-fly /m/ image transforms served straight from the storage service.

Migrate in an afternoon

POST /v1/spaces/:id/import/storyblok pulls a whole Storyblok space — components, stories, datasources, assets — into Osstblok. Live in hours, not weeks.

MCP-native for AI agents

Every space exposes a Streamable HTTP MCP endpoint. Claude and other agents read, write and manage content — with per-token roles.

Swap the endpoint. That's it.

Boot Osstblok, point the official Storyblok JS SDK at your instance, and read stories back. The response shape is identical — because it's the same shape.

storyblok.ts
import { storyblokInit, apiPlugin } from '@storyblok/js'

const { storyblokApi } = storyblokInit({
  accessToken: process.env.OSSTBLOK_TOKEN!,
  apiOptions: { endpoint: 'https://your-osstblok.example/api/v2' },
  use: [apiPlugin],
})

const { data } = await storyblokApi!.get('cdn/stories/home', { version: 'published' })
console.log(data.story.content)
Official @storyblok/js — only the endpoint changes.