Zudoku
Deployment

Vercel

Vercel offers multiple ways to deploy to its service, including via GitHub, and their CLI. You can read more about them in their Deployments Overview.

Prerequisites

To deploy to Vercel you will need:

  • A Vercel account (free)
  • A GitHub account (if deploying via GitHub)
  • The Vercel CLI

Deploying your Zudoku powered documentation using the Vercel CLI is what we will cover in this guide.

Install the CLI

To get started you need to install the CLI:

TerminalCode
npm i -g vercel

Setup a new project

Next, set up a new Vercel project in the root of your docs:

TerminalCode
vercel

This command will set up everything that is needed to deploy your documentation to Vercel.

It will ask some specific questions including the project name and where the code is located. You can answer however you like for these.

When you get to this step:

TerminalCode
No framework detected. Default Project Settings: - Build Command: `npm run vercel-build` or `npm run build` - Development Command: None - Install Command: `yarn install`, `pnpm install`, `npm install`, or `bun install` - Output Directory: `public` if it exists, or `.` ? Want to modify these settings? (y/N)

You can accept these defaults as long as the Output Directory override remains disabled. Do not set it to dist, public, or another directory. When Vercel runs the build, Zudoku detects the VERCEL environment variable and emits a Build Output API deployment to .vercel/output. Vercel detects and deploys this directory automatically.

If your project already has an Output Directory saved in Vercel, disable the override in Project Settings or add a vercel.json file at the project root. A minimal configuration is:

JSONCode
{ "$schema": "https://openapi.vercel.sh/vercel.json", "framework": null, "buildCommand": "npm run build", "outputDirectory": null }

The framework: null setting selects Vercel's Other framework preset. Adjust the build command if your project uses a different script.

After this is complete, your site will build and Vercel will respond with the URL for you to test it.

Generated Vercel output

For a standard static build, Zudoku writes the following directly into .vercel/output:

  • Static pages and assets under .vercel/output/static
  • Clean URL routes and overrides, including redirects from your Zudoku configuration
  • Vercel Routing Middleware for Markdown content negotiation when it is enabled

You do not need to add cleanUrls, copy Zudoku redirects, or define the generated middleware in vercel.json. To inspect the same artifact locally, use vercel build; a plain npm run build outside Vercel produces the portable dist output instead.

Markdown content negotiation

publishMarkdown is enabled by default, and contentNegotiation defaults to the same value. When both are enabled, Zudoku's generated Routing Middleware:

  • Serves Markdown from a canonical documentation URL when a GET or HEAD request prefers text/markdown
  • Honors media-range specificity and q values, returning 406 Not Acceptable when neither HTML nor Markdown is acceptable
  • Includes Vary: Accept, Accept-Encoding so Vercel's cache keeps HTML and Markdown separate
  • Advertises the .md representation with a Link header
  • Preserves real 404 responses with a short Markdown recovery body
  • Passes assets, published API schemas, and non-document routes through unchanged

Set contentNegotiation: false to disable the middleware while continuing to publish the explicit .md files.

After deployment, verify a known page and a missing Markdown path:

TerminalCode
curl -sS -D - -o /dev/null \ -H 'Accept: text/markdown' \ https://docs.example.com/quickstart curl -sS -D - -o /dev/null \ -H 'Accept: text/markdown' \ https://docs.example.com/path-that-does-not-exist curl -sS -D - -o /dev/null \ -H 'Accept: application/json' \ https://docs.example.com/quickstart

The first response should be 200 with Content-Type: text/markdown; charset=utf-8 and a Vary header containing both Accept and Accept-Encoding. The missing path should return 404 with a Markdown content type; missing explicit .md and .mdx paths should do the same. The final request should return 406. If the first request returns HTML, confirm that Vercel deployed .vercel/output and that no Output Directory override points to dist.

Accurate Last Modified Dates

If you have enabled the showLastModified option, Zudoku automatically tracks the last modified date of your documentation pages using Git history. However, Vercel performs shallow clones by default (only fetching the last 10 commits), which can result in inaccurate "Last Modified" dates for pages that haven't been updated recently.

To ensure accurate last modified dates, add the VERCEL_DEEP_CLONE environment variable to your Vercel project:

  1. Go to your project settings in Vercel
  2. Navigate to "Environment Variables"
  3. Add a new variable: VERCEL_DEEP_CLONE=true
  4. Save and redeploy your site

This will enable full Git history during builds, ensuring all pages show their correct last modified dates. The impact on build time is minimal (typically 5-20 seconds on the first build), and subsequent builds benefit from caching.

Last modified on