# Deploying Next.js to Vercel

> Source: https://agilitycms.com/docs/nextjs/deploying-next-js-to-vercel

Vercel is built by the team behind Next.js, so every Next.js feature works there on the day it ships — including Cache Components, the proxy, and on-demand revalidation. This guide covers deploying an Agility-powered Next.js site, wiring up publish-triggered updates, and the two settings that most often break preview after a successful deploy.

## Deploy via the Agility integration

The fastest path. In the Agility Manager, go to **Settings → Deployment** and click **Setup Deployment** for Vercel.

> **Note:** You'll need a GitHub account and a Vercel account.

The wizard then:

1. Authorizes the Agility integration with your Vercel account.
2. Creates (or connects) a Git repository and clones the starter into it.
3. Sets your `AGILITY_*` environment variables on the Vercel project — for **Production** and **Preview** both.
4. Builds and deploys.
5. Writes the resulting Production and Preview domains back into your Agility instance.

That last step is what makes preview work without you configuring anything: Agility now knows which URL to open when an editor clicks **Preview**.

## Deploy manually

If your project isn't based on a starter:

1. Push your repository to GitHub, GitLab or Bitbucket.
2. At [vercel.com/new](https://vercel.com/new), import it. Vercel detects Next.js and needs no build configuration.
3. Add your environment variables:

   | Variable | Purpose |
   |---|---|
   | `AGILITY_GUID` | Your instance identifier |
   | `AGILITY_API_FETCH_KEY` | Live (published) content |
   | `AGILITY_API_PREVIEW_KEY` | Draft content, for preview |
   | `AGILITY_SECURITY_KEY` | Validates preview links and webhooks |
   | `AGILITY_LOCALES` | Comma-separated, first is the default |
   | `AGILITY_SITEMAP` | Sitemap channel name, usually `website` |

   Set them for **Production, Preview and Development**. A missing key on Preview is the classic cause of "it works in production but every preview deploy 500s."

4. Deploy, then install the **Agility CMS** integration from the Vercel Marketplace to link the project back to your instance.

## Updating content without rebuilding

> **Coming from the older recipe?** This guide used to show `getStaticPaths` with `fallback: true` plus `revalidate: 10` in `getStaticProps` — Incremental Static Regeneration on a timer. That model is gone in the App Router, and route segment configs like `export const revalidate` are **rejected outright** when `cacheComponents` is enabled. The replacement is better: instead of every page re-checking on a stopwatch, a publish webhook invalidates exactly the affected cache tags, so the change is live in seconds and nothing else re-renders.

With [Cache Components](/docs/nextjs/caching-with-next-js-and-agility), each content read is cached and tagged:

```ts
const cachedContentItem = async (params) => {
  "use cache"
  cacheTag(`agility-content-${params.contentID}-${params.languageCode}`)
  cacheLife("days")
  return fetchContentItem(params)
}
```

and a route handler clears those tags when Agility says something changed:

```ts
// app/api/revalidate/route.ts
import { revalidateTag } from "next/cache"

export async function POST(req: NextRequest) {
  const data = await req.json()

  if (data.state === "Published" && data.referenceName) {
    // Next 16 requires the second argument — the cache profile to expire
    revalidateTag(`agility-content-${data.referenceName}-${data.languageCode}`, "max")
  }

  return NextResponse.json({ revalidated: true })
}
```

> `revalidateTag(tag)` with one argument is a Next 15 signature. In Next 16 it takes a cache-life profile as a second argument, and omitting it is a build error.

### Point Agility at it

In the Manager, go to **Settings → Web Hooks** and add one pointing at `https://your-site.com/api/revalidate`. Check **Receive Content Publish Events**, and send a **Test Payload** to confirm you get a success response before relying on it.

If you want to trigger a full rebuild instead — appropriate if you don't use tag revalidation — create a **Deploy Hook** in Vercel under **Settings → Git → Deploy Hooks** and point the Agility webhook at that URL.

## Making preview work on a deployed site

Two things bite here, and both only appear once the site is actually on Vercel.

### 1. Cached pages skip the proxy

Vercel serves prerendered pages straight from its edge cache **without invoking your proxy**. On exactly the pages that matter most, `?agilitypreviewkey=` never reaches `/api/preview`, draft mode is never enabled, and Web Studio quietly shows published content.

The fix is a `beforeFiles` rewrite, which is compiled into the routes manifest and evaluated *before* the cache lookup:

```js
// next.config.mjs
async rewrites() {
  return {
    beforeFiles: [
      {
        source: "/:path((?!api).*)",
        has: [{ type: "query", key: "agilitypreviewkey" }],
        destination: "/api/preview?slug=/:path",
      },
    ],
  }
}
```

Keep the proxy logic as well — it handles uncached requests. Full detail in [Handling Preview URLs & Request Lifecycle](/docs/nextjs/handling-preview-urls-request-lifecycle).

### 2. Deployment Protection blocks Agility

Vercel protects preview deployments by default. Agility's preview requests and your webhook calls arrive unauthenticated and get an SSO page instead of your site — so preview shows a Vercel login screen, and publishes appear not to revalidate.

Under **Settings → Deployment Protection**, either add a **Protection Bypass for Automation** secret and configure it in your Agility integration, or scope protection so the domain Agility calls is reachable. Don't simply switch protection off.

## Build settings worth checking

- **Node version** — set it explicitly under **Settings → General**, and keep it on a current LTS. Node 18 is end-of-life.
- **`prebuild`** — if your project syncs redirects or other data before building (npm runs `prebuild` automatically before `build`), confirm that step has the env vars it needs on Vercel, not just locally.
- **Build cache** — Vercel caches `.next/cache` between builds, which is what keeps incremental builds fast. Use **Redeploy without cache** when debugging a build that succeeds locally but not on Vercel.

## Verify the deployment

```bash
curl -I https://your-site.com/about-us                  # 200, with cache headers
curl -I https://your-site.com/no-such-page              # a real 404, not a 200
curl -X POST https://your-site.com/api/revalidate \
  -H "Content-Type: application/json" -d '{"state":"Published", ...}'
```

Then publish a change in Agility and confirm it appears on the live site within seconds — the end-to-end test that actually proves the wiring.

## Summary

1. **Settings → Deployment** in Agility for the automated path; Vercel Marketplace integration for a manual one.
2. Set every `AGILITY_*` variable on **all three** environments.
3. Forget timed ISR — use cached, tagged reads plus a publish webhook that calls `revalidateTag(tag, "max")`.
4. Add the `beforeFiles` preview rewrite, or preview breaks on exactly the cached pages editors care about.
5. Deal with Deployment Protection deliberately, or Agility can't reach your preview deployments.
