Deploy a UnfoldCMS-Powered Site on Vercel

Frontend on Vercel, CMS on your host, rebuild on publish.

Deploy a UnfoldCMS-Powered Site on Vercel

You can't run UnfoldCMS itself on Vercel — it's a PHP app and Vercel runs JavaScript. But the setup developers actually want is different: keep the CMS on a small PHP host, deploy your Next.js or Astro front end to Vercel's edge, and have the site rebuild the instant an editor publishes. This guide shows that architecture end to end, with the Vercel Deploy Hook wired to a signed CMS webhook. See also: the Next.js integration guide and the Cloudflare Pages guide.

TL;DR: UnfoldCMS stays on your PHP host (any cheap VPS or shared host). Your front end deploys to Vercel and fetches content from /api/v1/posts. You create a Vercel Deploy Hook (a URL that triggers a build), then register it in UnfoldCMS so the post.published webhook fires it. Publish in the CMS, Vercel rebuilds, live in a minute or two. No GraphQL, no SDK.

What Does the Architecture Look Like?

The key idea: the CMS and the front end live in different places and talk over HTTPS. This is normal for headless setups and it's why "deploy UnfoldCMS on Vercel" is the wrong mental model — you deploy the site on Vercel, powered by the CMS.

  • UnfoldCMS runs on a PHP host (VPS, shared hosting, anywhere with PHP 8.3 + MySQL). This is where editors work and content lives.
  • Your front end (Next.js / Astro) runs on Vercel. It pulls content from the CMS API at build time.
  • The link between them is a Vercel Deploy Hook, triggered by the CMS's signed publish webhook.

What You Need Before Starting

  • UnfoldCMS running on a PHP host with at least one published post.
  • A front-end project (Next.js or Astro) connected to a Vercel project.
  • The CMS base URL set as an env var in Vercel, e.g. CMS_URL=https://cms.yoursite.com.
  • About 20 minutes.

Step 1: Deploy the Front End and Point It at the CMS

Connect your repo to Vercel as usual. In Project Settings → Environment Variables, add CMS_URL pointing to your UnfoldCMS install. Your build fetches published content from the public API — no auth needed for reads:

// fetched at build time on Vercel
const res = await fetch(`${process.env.CMS_URL}/api/v1/posts`);
const { data } = (await res.json()).data; // { success, data: { data: [...] } }

Deploy once. You now have a static, edge-served site sourced from your CMS. The remaining question is how it updates when content changes — that's the Deploy Hook.

Step 2: Create a Vercel Deploy Hook

A Deploy Hook is a unique URL that triggers a production build when something POSTs to it. In Project Settings → Git → Deploy Hooks, create one (name it "CMS publish", branch main). Vercel gives you a URL like:

https://api.vercel.com/v1/integrations/deploy/prj_xxx/yyy

Copy it. Anything that POSTs to this URL kicks off a fresh build that re-fetches your CMS content.

Step 3: Fire the Deploy Hook on Publish

UnfoldCMS ships outgoing HMAC-signed webhooks. On the post.published event it POSTs a signed payload to a URL you register. You have two ways to connect it to the Deploy Hook:

Option A — direct (simplest). Register the Vercel Deploy Hook URL itself in UnfoldCMS. Vercel triggers the build on any POST, so this works immediately. The trade-off: you're not verifying the CMS signature, so anyone with the hook URL could trigger a build.

Option B — verified relay (recommended). Put a tiny Vercel Function in front that checks the signature, then calls the Deploy Hook:

// app/api/cms-deploy/route.ts
import crypto from 'crypto';

export async function POST(req: Request) {
  const raw = await req.text();
  // UnfoldCMS signs with spatie/laravel-webhook-server — header "Signature",
  // value hash_hmac('sha256', rawBody, secret).
  const signature = req.headers.get('signature') ?? '';
  const expected = crypto
    .createHmac('sha256', process.env.CMS_WEBHOOK_SECRET!)
    .update(raw)
    .digest('hex');

  const ok = crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
  if (!ok) return new Response('Bad signature', { status: 401 });

  // Payload: { event, occurred_at, data: { id, title, slug, url, posted_at } }
  await fetch(process.env.VERCEL_DEPLOY_HOOK_URL!, { method: 'POST' });
  return Response.json({ deploying: true });
}

Register it in UnfoldCMS. In the admin webhooks settings, add your endpoint (the Deploy Hook URL for Option A, or your /api/cms-deploy route for Option B), subscribe to post.published, and for Option B copy the signing secret into CMS_WEBHOOK_SECRET. Hit "Send test" to confirm a build kicks off.

If you use Next.js as a server (not a static export), you may not need a full rebuild at all — on-demand revalidation updates a single page in seconds. See the Next.js integration guide for that pattern.

Deploy Hook vs On-Demand Revalidation: Which on Vercel?

Two ways to keep a Vercel site fresh against UnfoldCMS. Pick by your front-end's rendering mode.

Method What updates Speed Best for
Deploy Hook (full rebuild) Whole site 1–2 min Astro / static exports
On-demand revalidation One page Seconds Next.js running as a server

If your front end is Astro or a static export, use the Deploy Hook. If it's a server-rendered Next.js app, prefer on-demand revalidation — it's faster and cheaper.

Frequently Asked Questions

Can I host UnfoldCMS on Vercel?

No. UnfoldCMS is a PHP/Laravel app and needs PHP plus MySQL; Vercel runs JavaScript functions. Host the CMS on a PHP-capable server and deploy only your front end to Vercel, pointing it at the CMS API.

What does the CMS host cost on top of Vercel?

UnfoldCMS runs on modest hardware — a small VPS (around $5–10/month) handles a typical content site, since the heavy traffic hits your static front end on Vercel's edge, not the CMS.

Do I have to verify the webhook signature?

It's optional but recommended. The direct method (registering the Deploy Hook URL in the CMS) works without verification, but a verified relay function ensures only genuine CMS publishes can trigger builds. Use Option B for production.

Which CMS events trigger a Vercel build?

UnfoldCMS emits the post.published event today. Subscribe to it in the admin and point it at your Deploy Hook (or relay) to rebuild whenever a post goes live.

Can I preview drafts on a Vercel deployment?

The public API serves published content only — drafts return 404. For draft preview you'd authenticate with a Sanctum admin token and gate it behind your framework's preview mode.

Where to Go From Here

You now have a CMS-powered site on Vercel that rebuilds on publish. For the data-fetching detail, read the Next.js or Astro integration guide. Prefer Cloudflare's edge? The Cloudflare Pages guide follows the same shape. Full endpoint list is in the API docs.

UnfoldCMS is a one-time license, self-hosted, with the full public API in every tier — see pricing. You keep the content on your own host and let Vercel serve the fast front end. No per-seat SaaS pricing, no vendor lock-in on your data.

Related: Next.js integration · Deploy on Cloudflare Pages · CMS for Next.js