A publish reaches readers in about a second
Delivery is GraphQL over GET, so the CDN caches every query, and a publish purges the cached answers. Frontends stay in sync through the Sync API, which streams every change since a cursor, deletions included, for published and draft content alike. The types come from your content model, generated by the CLI, so a renamed field breaks the build instead of the page.
From Save to the reader's screen
The draft is saved.
Nothing live changes. The Preview API serves drafts from the origin, never cached, so the preview sees the save at once.
The draft becomes the published version.
Publishing checks the draft against the current model and copies it to the published state. Webhooks fire with the entry's ID only, so a draft never leaks through a payload.
The CDN drops the old answers.
The publish purges the environment's cached responses. The next request for each query goes to the origin once and is cached again.
Readers see it.
About a second after Publish. Every request after that is a cache hit, around 25 ms.
One query, typed from your model
Write GraphQL; the editor types it.
The client is a small transport, not a query builder. You write the query. uniwoven schema pulls your environment's schema, and gql.tada types the result in the editor as you write, with no watch process.
import { createClient } from '@uniwoven/client'
import { graphql } from './graphql' // your gql.tada instance
const cms = createClient({
baseUrl: 'https://delivery.example.com',
space: 'my-space',
token: process.env.UNIWOVEN_DELIVERY_KEY!,
})
const PageQuery = graphql(`
query Page($id: ID!, $locale: String) {
page(id: $id, locale: $locale) {
title
sys { id path publishedAt }
}
}
`)
const data = await cms.query(PageQuery, { id: '5a1ac675-…', locale: 'en' })
console.log(data.page?.title) // typed: string | null | undefined
Mirrors that catch up on their own
Search indexes, static builds and mirrors need every change, in order, deletions included. The Sync API streams them since a cursor you store: a full walk first, then only deltas. It works with delivery keys for published content and with preview keys for drafts, so a preview mirror stays as current as the live one. Pair it with a webhook: the webhook rings the doorbell, sync.sync() catches up, and a missed webhook heals on the next call.
import { createClient, createSyncClient, memoryStore } from '@uniwoven/client'
const cms = createClient({
baseUrl: 'https://delivery.example.com',
space: 'my-space',
token: process.env.UNIWOVEN_DELIVERY_KEY!,
})
const sync = createSyncClient({
client: cms,
store: memoryStore(),
onUpsert: async (item) => index.put(item.id, item),
onDelete: async (id) => index.remove(id),
})
const result = await sync.sync()
// First call: full walk. Every later call: delta since the stored cursor.
console.log(`${result.upserted} upserted, ${result.deleted} deleted`)
Small packages your team can read
Zero runtime dependencies.
ESM-only. The delivery client runs on Node 20.19 or later, in edge runtimes and in browsers, on the global fetch alone.
Errors you can switch on.
Every error carries a code: unauthorized, rate_limited, graphql, network and the rest. A missing page from resolve returns null, because "no page here" is routing, not an error.
Deep queries in one request.
References, nested components and rich text with its embeds resolve server-side in one query, batched, up to ten levels deep.
Examples that run.
The SDK example scripts run in CI against the real API router. When an example stops working, the build fails.
If your current delivery setup is slow to purge or untyped, a Setup Review finds out why, on the platform you already run. Our view, October 2026: GraphQL delivery behind a CDN is a tie with the mature headless CMS vendors. The differences sit around it: sync for draft content as well as published, URLs resolved by the API instead of your router, and types generated from the model you already have. Corrections welcome.
See the Setup Review →What developers ask about delivery
About a second. A publish purges the environment's cached answers at the CDN, and the next request for each query goes to the origin once. Frontends that keep their own copy, such as search indexes and static builds, call the Sync API with a stored cursor and get every change since, deletions included, for published and draft content.
See a publish reach the page
A free walkthrough. We shape the sample space like your site, publish a change, and query it with you from a typed client. There's nothing to prepare.
Book a walkthrough →