Skip to content

Static delivery

Static delivery adds CaretCMS to a static Astro site without running CMS routes in production. Editors use inline editing and Studio in astro dev. During astro build, CaretCMS writes published content into the generated HTML.

Use static delivery when… Use server delivery when…
Your site ships as static files (Netlify, Vercel static, S3, CDN) You already run Astro with output: 'server'
Publish → rebuild → deploy is acceptable for public updates You need visitor-visible edits immediately after save
You want CaretCMS without an SSR adapter You want per-request HTML rewriting in production
Dev (astro dev)
→ CaretCMS injects /admin, /api/cms, inline editor (local authoring)
Build (astro build, output: static)
→ Authoring routes stay out of production output
→ astro:build:done bakes stored field overrides into dist/**/*.html
Publish
→ Draft overlay commits to storage
→ Optional rebuild webhook triggers CI → astro build → deploy

Your template markup remains the seed content. Until an editor saves an override, visitors see the original HTML. After publish and rebuild, stored values replace tagged fields in the built files.

With markdownStorage(), supported prose edits publish back into the source .md file before CI rebuilds it. Every drafted range is rechecked first; a stale_body or invalid_body conflict leaves that entry’s source and draft untouched instead of triggering a partial publish.

  1. Wire the integration

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import caret from '@caretcms/core';
    export default defineConfig({
    integrations: [caret({ delivery: 'static' })],
    });

    npx @caretcms/caretize init scaffolds this automatically for static Astro projects.

  2. Make content editable

    Add data-caret attributes by hand or run npx @caretcms/caretize. Existing .md content collections are stamped automatically for supported prose when Markdown storage is active. See Inline editing and Markdown body editing.

  3. Author locally

    Terminal window
    npm run dev

    Sign in at /admin. With no CARET_EDIT_PASSWORD set, a temporary dev password prints in the terminal.

  4. Ship baked HTML

    Terminal window
    npm run build

    Look for [caretcms] static delivery bake complete (N/N HTML files rewritten). Deploy dist/ to your static host — no CMS routes in production output.

astro.config.mjs
caret({
delivery: {
mode: 'static',
bake: true,
publish: {
webhookUrl: process.env.CARET_REBUILD_WEBHOOK_URL,
method: 'POST',
headers: { authorization: `Bearer ${process.env.CI_TOKEN}` },
},
},
})

After Publish, the webhook receives:

{
"source": "caretcms",
"event": "publish",
"published": [{ "collection": "pages", "id": "home", "revision": 3, "deleted": false }],
"commit": "abc123..."
}

The publish still succeeds if the webhook fails — check logs and retry the deploy.

Option Default (static) Notes
delivery: 'static' Shorthand for { mode: 'static', bake: true }
delivery.mode 'auto' if omitted Resolves to static when Astro output is static; set 'static' to enforce this path
delivery.bake true when mode is static Set false to skip HTML rewrite at build
delivery.publish.webhookUrl none Called after successful publish
delivery.publish.method POST POST or PUT
delivery.publish.headers {} Extra headers for the webhook

See Configuration for all caret() options.