MkDocs + Vercel¶
I wasn't satisfied with any of the existing guides for deploying an MkDocs site to Vercel, so I wrote my own.
This method uses GitHub Actions to build and deploy your site via the Vercel CLI.
Prerequisites¶
Configuring your project¶
First and foremost, you'll need to install the Vercel CLI on your own machine.
Connect it to your Vercel account:
Then switch into your project's directory and link it to Vercel:
After following the interactive prompts, a .vercel
folder will appear in your project's directory.
Inside that folder is a project.json
file with a projectId
property and an orgId
property. Add the values of
these properties as secrets in your project's GitHub repository under the names VERCEL_PROJECT_ID
and VERCEL_ORG_ID
,
respectively.
You can do this on GitHub.com or with the GitHub CLI:
Getting a token¶
You'll need to generate a Vercel account token so the Vercel CLI can access your account from within GitHub Actions. Head over
to your Vercel account settings, choose a name, appropriate scope, and expiration
date for your token, and click Create. Copy the token and set it as a repository secret under the name
VERCEL_TOKEN
.
Configuring vercel.json
¶
It's optional, but strongly recommended, that you put a vercel.json
file in your docs
folder with at least the following contents:
Why?
Relative internal links on your site will break if the request URL
does not have a trailing slash. This isn't a problem on MkDocs'
de facto standard hosting platform, GitHub Pages, which automatically enforces trailing slashes, so the
overwhelming majority of public MkDocs sites do not exhibit this issue. Yours will,
though, if you deploy it on Vercel without configuring vercel.json
to enforce trailing slashes.
Writing the workflow¶
Finally, you need to write a GitHub Actions workflow that builds your documentation and deploys it to Vercel. There's no one-size-fits-all solution here, but here are some basic examples for commonly-used package managers.
name: Deploy Documentation
on:
push:
paths:
- docs/**
- mkdocs.yml
- requirements.txt
- .github/workflows/docs.yml
workflow_dispatch:
jobs:
deploy:
name: Deploy Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set Up Python
uses: actions/setup-python@v5
- name: Install Dependencies
run: pip install -r requirements.txt
- name: Build Documentation
run: mkdocs build
- name: Deploy to Vercel
uses: npx vercel --token ${{ secrets.VERCEL_TOKEN }} # (1)!
working-directory: site
env: # (2)!
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
-
To create a production deployment, add the
--prod
flag:To emulate Vercel's branch-dependent creation of preview and production deployments, you can do something like this (replacing
main
with your production branch if necessary): -
If you don't want the Vercel CLI to send telemetry, you can add
VERCEL_DISABLE_TELEMETRY: 1
to theenv:
key:
name: Deploy Documentation
on:
push:
paths:
- docs/**
- mkdocs.yml
- pyproject.toml
- .github/workflows/docs.yml
workflow_dispatch:
jobs:
deploy:
name: Deploy Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set Up uv
uses: astral-sh/setup-uv@v3
- name: Install Dependencies
run: uv sync # (2)!
- name: Build Documentation
run: uv run mkdocs build
- name: Deploy to Vercel
uses: npx vercel --token ${{ secrets.VERCEL_TOKEN }} # (1)!
working-directory: site
env: # (3)!
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
-
To create a production deployment, add the
--prod
flag:To emulate Vercel's branch-dependent creation of preview and production deployments, you can do something like this (replacing
main
with your production branch if necessary): -
If you have a seperate dependency group for your documentation, you might instead do something like:
-
If you don't want the Vercel CLI to send telemetry, you can add
VERCEL_DISABLE_TELEMETRY: 1
to theenv:
key:
name: Deploy Documentation
on:
push:
paths:
- docs/**
- mkdocs.yml
- pyproject.toml
- .github/workflows/docs.yml
workflow_dispatch:
jobs:
deploy:
name: Deploy Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set Up Python
uses: actions/setup-python@v5
- name: Install Poetry
run: pipx install poetry
- name: Install Dependencies
run: poetry install # (2)!
- name: Build Documentation
run: poetry run mkdocs build
- name: Deploy to Vercel
uses: npx vercel --token ${{ secrets.VERCEL_TOKEN }} # (1)!
working-directory: site
env: # (3)!
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
-
To create a production deployment, add the
--prod
flag:To emulate Vercel's branch-dependent creation of preview and production deployments, you can do something like this (replacing
main
with your production branch if necessary): -
If you have a seperate dependency group for your documentation, you might instead do something like:
-
If you don't want the Vercel CLI to send telemetry, you can add
VERCEL_DISABLE_TELEMETRY: 1
to theenv:
key:
name: Deploy Documentation
on:
push:
paths:
- docs/**
- mkdocs.yml
- pyproject.toml
- .github/workflows/docs.yml
workflow_dispatch:
jobs:
deploy:
name: Deploy Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set Up PDM
uses: pdm-project/setup-pdm@v4
- name: Install Dependencies
run: pdm sync # (2)!
- name: Build Documentation
run: pdm run mkdocs build
- name: Deploy to Vercel
uses: npx vercel --token ${{ secrets.VERCEL_TOKEN }} # (1)!
working-directory: site
env: # (3)!
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
-
To create a production deployment, add the
--prod
flag:To emulate Vercel's branch-dependent creation of preview and production deployments, you can do something like this (replacing
main
with your production branch if necessary): -
If you have a seperate dependency group for your documentation, you might instead do something like:
-
If you don't want the Vercel CLI to send telemetry, you can add
VERCEL_DISABLE_TELEMETRY: 1
to theenv:
key:
You can also check out the workflow that deploys this very website.