---
title: "Vercel"
description: "Deploy your docs on Vercel with content pinning, ISR caching, instant updates, and builds that skip content-only pushes."
canonical_url: "https://docs-template.comark.dev/deployment/vercel"
---
# Vercel

> Deploy your docs on Vercel with content pinning, ISR caching, instant updates, and builds that skip content-only pushes.

The layer is built for [Vercel](https://vercel.com): rendered pages are cached at the edge with [ISR](https://vercel.com/docs/incremental-static-regeneration), parsed content persists in the Runtime Cache across deployments, and a GitHub webhook purges pages the moment content changes.

## Setup

<steps level="3">
### Import the repository



Create a Vercel project from your docs repository. If the Nuxt app lives in a subdirectory (for example `docs/`), set it as the project's **Root Directory**.



### Set the environment variables



In the project's **Settings → Environment Variables**:



| Variable               | Purpose                                                                                                                                                                                  |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GITHUB_TOKEN`         | Reads content from GitHub and queries the GraphQL API for page history and RSS. A fine-grained token with read access to the repository contents is enough.                              |
| `GLOBAL_CONFIG`        | Optional connection string for pinning production content to a specific commit. Vercel creates it when you connect a Global Config store.                                                |
| `WEBHOOK_SECRET`       | Shared secret that signs the push webhook. Generate a random string.                                                                                                                     |
| `VERCEL_BYPASS_TOKEN`  | Lets the revalidation endpoint purge ISR pages. Must be available at **build** time — it's baked into the deployment's ISR configuration, so a runtime-only value leaves purging broken. |
| `NUXT_OG_IMAGE_SECRET` | Signs OG image URLs. Generate a random string.                                                                                                                                           |



`VERCEL_AUTOMATION_BYPASS_SECRET` is set automatically when [Deployment Protection](https://vercel.com/docs/deployment-protection) is enabled; it lets the revalidation endpoint call back through the protection wall.



### Add the push webhook



In your GitHub repository, go to **Settings → Webhooks → Add webhook**:



- **Payload URL**: `https://your-docs-domain.com/api/revalidate`
- **Content type**: `application/json`
- **Secret**: the same value as `WEBHOOK_SECRET`
- **Events**: just the push event



On every push to the production branch, the endpoint verifies the signature, resolves the new content commit, and purges exactly the pages that changed. Content is live within seconds — see [Architecture](https://docs-template.comark.dev/concepts/architecture#revalidation-on-push).



### Skip builds for content pushes



Since content never ships in the build, a push that only touches `content/` doesn't need a deployment — the webhook already handles it. Tell Vercel to skip those builds with an [Ignored Build Step](https://vercel.com/docs/project-configuration/git-settings#ignored-build-step):



In **Settings → Git → Ignored Build Step**, select **Custom** and set:



```bash
git diff --quiet HEAD^ HEAD -- ':!content'
```



The command exits `0` (skip the build) when nothing outside `content/` changed. Alternatively, version it in `vercel.json` at the project root:



```json [vercel.json]
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "ignoreCommand": "git diff --quiet HEAD^ HEAD -- ':!content'"
}
```



Adjust the path if your content directory differs. Both setups behave the same; the dashboard setting applies without a file in the repository, while `vercel.json` travels with the code.
</steps>

## Pin production content

By default, production follows the latest commit that changed your content directory. An optional Vercel Global Config value named `contentSha` lets you hold production on a reviewed commit or roll content back without moving the production branch. The pin affects production only; preview deployments and local development don't read it.

<steps level="3">
### Connect a Global Config store



In your Vercel project, open **Global Config**, then create a project store or connect an existing store. Vercel creates a `GLOBAL_CONFIG` environment variable containing the store's connection string. See [Vercel's Global Config setup guide](https://vercel.com/docs/global-config/get-started) for the dashboard workflow.



If you connect the store after the current production deployment was built, redeploy once so its server functions receive `GLOBAL_CONFIG`. Later item updates don't require a redeploy.



### Add the content SHA



Copy the full commit SHA for the content version you want to serve. In the store's **Items** editor, add `contentSha` as a JSON string, then select **Save Items**:



```json [Global Config items]
{
  "contentSha": "0123456789abcdef0123456789abcdef01234567"
}
```



New server renders now read content from that commit. Pages already cached by ISR update as they expire, which takes up to the configured [`comarkDocs.isr`](https://docs-template.comark.dev/getting-started/configuration#nuxtconfigts-comarkdocs-options) duration (300 seconds by default).



### Remove or move the pin



Replace `contentSha` with another full commit SHA to move the pin. Delete the item to resume following the latest content commit on the production branch. Neither change requires a redeploy, but the same ISR expiration window applies.
</steps>

<warning>
`contentSha` must resolve to a commit in the configured GitHub repository. An invalid or inaccessible value makes production content reads fail. A missing key, disconnected store, or Global Config read error safely falls back to the production branch.
</warning>

## ISR behavior

The layer generates ISR route rules for every top-level content section, the landing page, previews, and the machine-readable routes (`/raw/**`, `/llms.txt`, `/llms-full.txt`, `/sitemap.md`, `/rss.xml`, `/openapi.json`). Pages expire after 300 seconds by default, or immediately when the webhook purges them.

Tune or disable this with [`comarkDocs.isr`](https://docs-template.comark.dev/getting-started/configuration#nuxtconfigts-comarkdocs-options) in `nuxt.config.ts`. Your own `routeRules` take precedence over the generated ones.

## Rolling back content

Content follows the head of the production branch unless a `contentSha` pin is active, so rolling back a *deployment* in Vercel does not roll back *content*. For a temporary rollback that leaves git history unchanged, [pin production to an older content commit](#pin-production-content).

For a permanent rollback on the production branch, revert the content commit with git:

```bash [Terminal]
git revert <bad-commit>
git push
```

The webhook picks it up like any other push, and the Ignored Build Step means the revert doesn't trigger a build either. To inspect what any older version looked like before reverting, open it at [`/blob/<sha>`](https://docs-template.comark.dev/concepts/versioned-previews).

## Next steps

- [PR preview comments](https://docs-template.comark.dev/deployment/pr-preview-comments) — post `/tree/` preview links on content pull requests automatically.


## Sitemap

See the full [sitemap](https://docs-template.comark.dev/sitemap.md) for all pages.
