Deploying a Hexo Site to Vercel

Updated 2026-03-04

Vercel is one of the smoothest ways to deploy a static site — connect your repository and every push to main triggers an automatic build and deploy. For a Hexo blog, the whole process takes under five minutes to set up.

Prerequisites

  • A Hexo site in a GitHub, GitLab, or Bitbucket repository
  • A Vercel account (free tier is plenty for a blog)

Your repository should have at minimum:

1
2
3
4
5
├── _config.yml
├── package.json
├── source/
│ └── _posts/
└── themes/

Step 1 — Import the Project

  1. Go to vercel.com/new
  2. Click Import Git Repository
  3. Select your Hexo site repo
  4. Vercel will auto-detect it as a Node.js project

Step 2 — Configure Build Settings

Vercel might not detect Hexo automatically. Set these manually in the Configure Project step:

Setting Value
Framework Preset Other
Build Command npm run build
Output Directory public
Install Command npm install

Your package.json should have:

1
2
3
4
5
6
7
{
"scripts": {
"build": "hexo generate",
"clean": "hexo clean",
"server": "hexo server"
}
}

Step 3 — Environment Variables

If you want to enable Vercel Analytics (Vaultex supports this natively), set:

1
VERCEL_ANALYTICS_ID = your-analytics-id

In themes/vaultex/_config.yml:

1
vercel_analytics: true

This injects the Vercel Speed Insights script only when the environment variable is set.


Step 4 — Deploy

Click Deploy. Vercel will:

  1. Clone the repository
  2. Run npm install
  3. Run hexo generate
  4. Serve the public/ directory as a static site

The first deploy takes ~30–60 seconds. Subsequent deploys are faster due to caching.


Custom Domain

After the initial deploy:

  1. Go to your project’s Settings → Domains
  2. Add your domain (e.g., blog.example.com)
  3. Add the provided DNS records to your domain registrar:
    • An A record pointing to Vercel’s IP, or
    • A CNAME record pointing to cname.vercel-dns.com

SSL certificates are provisioned automatically via Let’s Encrypt.

Update your Hexo _config.yml to use the real URL:

1
url: https://blog.example.com

Rebuild and deploy — the sitemap and feed will use the correct base URL.


Automatic Deploys

Every push to the default branch (usually main) triggers a production deploy. Every push to any other branch creates a Preview Deployment — a unique URL for testing changes before merging.

This workflow:

1
2
3
4
5
6
# Work on a draft post
git checkout -b draft/new-post
# ... write the post ...
git add source/_posts/new-post.md
git commit -m "Add new post draft"
git push origin draft/new-post

Creates a preview URL like https://my-blog-git-draft-new-post.vercel.app where you can review the rendered post before it goes live.


Vercel Configuration File

For advanced control, add a vercel.json to the repo root:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"buildCommand": "hexo generate",
"outputDirectory": "public",
"installCommand": "npm install",
"headers": [
{
"source": "/fonts/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
},
{
"source": "/(.*)",
"headers": [
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-Frame-Options",
"value": "DENY"
}
]
}
]
}

This adds long-lived caching for fonts and basic security headers.


Troubleshooting

Build Fails — Theme Not Found

If Hexo can’t find the theme, check _config.yml:

1
theme: themes/vaultex   # path relative to the themes/ directory

And confirm the theme is committed to the repository (not git-ignored).

Missing Plugins

If hexo-generator-search or other plugins aren’t in package.json, add them:

1
npm install hexo-generator-search hexo-generator-feed hexo-generator-sitemap

Then commit the updated package.json and package-lock.json.

public/ in .gitignore

Make sure public/ is in .gitignore — Vercel builds this directory itself. Committing it causes conflicts and bloats the repository.

1
2
3
public/
db.json
node_modules/

Once it’s running, a Vercel-deployed Hexo blog with Vaultex requires essentially zero maintenance — push Markdown, get a live post. That’s the pitch.