Headless delivery preview
Let your marketing team edit in SnabbSajt while your own app serves the published site.
Developer preview. The published-site API, read-only keys, settings and deploy hook work, and
connect,pull,linkandpushhave all shipped in@snabbsajt/cli@0.4.0. What is still missing is a real repository having gone through the whole journey end to end, meaning a token in your own host, a publish and a deploy hook firing, so this page is intentionally not listed in the public docs navigation yet. Do not runnpx @snabbsajt/cli init: that command is designed but not built.
Your marketing team can edit the website in SnabbSajt and press Publish while your own app fetches the published snapshot and renders it with your own components, on your own hosting.
Content lives in SnabbSajt. Code lives in your git. Neither syncs into the other.
What works today
- A site owner, or a retained builder with the explicit delivery grant, can switch a site from hosted to headless delivery and manage its keys.
- A read-only key can access one site's published snapshot. That key can never reach the draft.
- A separate test-version key reads the unpublished draft, for your preview deployment. See Staging below.
- Publishing can call your deploy hook and records whether it succeeded.
- Keys can be revoked immediately.
snabbsajt connect,pull,linkandpushare published (0.4.0). See the CLI reference.- The starter template renders either source through the same components: your
local
src/site.tswhile you build, and the published snapshot onceSNABBSAJT_SITE_IDandSNABBSAJT_DELIVERY_TOKENare set. The mapping isrenderModelFromPublished/renderModelFromPackagein@snabbsajt/site-kit, so your own app can use it without the template.
Pilot setup
In SnabbSajt, open Settings → Developers → Var hemsidan visas and choose Hos er själva. Add the separate preview and published website URLs, then create a key under Nycklar för er app and copy it when it is shown. We store only its hash, so it cannot be shown again.
For a pilot, SnabbSajt also provides the API base URL. Keep these values in your server-only environment:
SNABBSAJT_API_URL=https://<deployment>.convex.site
SNABBSAJT_SITE_ID=<site-id>
SNABBSAJT_DELIVERY_TOKEN=<shown-once-key>Fetch the published snapshot from a Server Component, route handler or build step:
const {
SNABBSAJT_API_URL,
SNABBSAJT_SITE_ID,
SNABBSAJT_DELIVERY_TOKEN,
} = process.env;
if (
!SNABBSAJT_API_URL ||
!SNABBSAJT_SITE_ID ||
!SNABBSAJT_DELIVERY_TOKEN
) {
throw new Error("SnabbSajt environment variables are missing");
}
const response = await fetch(
`${SNABBSAJT_API_URL}/v1/sites/${SNABBSAJT_SITE_ID}/published`,
{
headers: {
Authorization: `Bearer ${SNABBSAJT_DELIVERY_TOKEN}`,
},
cache: "no-store",
},
);
if (!response.ok) {
throw new Error(`SnabbSajt delivery failed (${response.status})`);
}
const site = await response.json();The response contains version, siteId, stage: "published", versionId,
publishedAt and the public snapshot. Add ?locale=en or ?locale=pl for a
translated snapshot. A valid key receives 404 not_published until the site has
been published once.
Keep the key on the server
The delivery key is read-only and scoped to one site, but it is still a
credential. Never expose it through a NEXT_PUBLIC_ variable or ship it in a
browser bundle.
Staging: the unpublished version
There is no third environment to configure. Your draft in SnabbSajt IS your staging content, and the published snapshot IS production. Two worlds, which is what the editor already gives every site.
To render the draft from your own preview deployment:
- In SnabbSajt, under Nycklar för er app, choose Skapa nyckel för
testversionen. It starts with
sajt_draft_rather thansajt_pub_, so you can see which one you pasted. - Put that key in your preview environment only. It reads work nobody has chosen to publish yet.
- Ask for the draft with
?stage=draft:
const response = await fetch(
`${SNABBSAJT_API_URL}/v1/sites/${SNABBSAJT_SITE_ID}/published?stage=draft`,
{ headers: { Authorization: `Bearer ${STAGING_TOKEN}` }, cache: "no-store" },
);Or from the SDK and the CLI:
const { snapshot } = await sajt.getPublishedSite({ stage: "draft" });snabbsajt pull --stage draftA draft answer carries stage: "draft" and no versionId and no
publishedAt, because there is no version: a draft is whatever it is right
now. That absence is deliberate. It is what stops a staging build presenting
itself as a production one in a cache key or a build log.
renderModelFromPublished accepts either shape, so the same components render
both and your preview cannot drift from production.
A production sajt_pub_ key asking for ?stage=draft gets a plain
401 unauthorized - the same answer a key that does not exist gets. That is on
purpose: the error must not tell whoever holds a weaker key that a stronger one
exists for this site. So do not read that 401 as "wrong stage".
?locale= is ignored for a draft. Translations are produced at publish, so a
draft has only the site's primary language, exactly like the editor's own
preview.
Rebuild staging when the content changes
Paste a second deploy hook under Bygg om testversionen. We call it when the draft changes, so before anyone publishes.
It is heavily debounced: at most one call every few minutes per site, however much typing happened in between. An owner writing a headline moves the draft on every keystroke and a build costs you money, so a burst of edits becomes a single rebuild. Bygg om nu beside the field answers the "did it pick up my change?" question immediately.
The two hooks send different bodies, so one endpoint can serve both:
{"source":"snabbsajt","event":"publish"} for production and
{"source":"snabbsajt","event":"draft_changed"} for staging. A failing staging
hook is recorded and never touches a publish.
Rebuild when someone publishes
Paste your host's deploy hook under Var hemsidan visas. Vercel, Netlify, AWS Amplify, Cloudflare Pages and GitLab pipelines all provide one.
SnabbSajt POSTs to that URL after a successful publish. A failed hook does not roll back the published content, and the outcome remains visible in settings.
A marketer publishing never deploys your code. The hook rebuilds whatever commit your host already considers current. A developer deploying never changes content.
Rate limits
The endpoint expects a build or server cache, not a browser request per visitor: 120 requests per minute per IP and 240 per minute per site.
Revoking access
Every key is listed under Settings → Developers → Nycklar för er app,
labelled so you can see which ones read the unpublished version. Revoking one
takes effect immediately. A revoked key is rejected like an unknown one with the
same 401 unauthorized response. Production and test-version keys are minted,
listed and revoked separately, and they share one per-site limit of ten.
Automated setup
The canonical SDK source implements snabbsajt connect and snabbsajt pull
with device-code approval, .snabbsajt.json and a server-only
SNABBSAJT_DELIVERY_TOKEN. Those commands must not be documented as available
until the matching npm package is published and tested from a clean external
repository.
Leaving
Remove the three server environment variables and the fetch integration. Your last downloaded snapshot is ordinary JSON and remains yours.
Didn't find the answer, or is something wrong here? Tell us.
Last updated on