Claude Skills with Vercel Deployment Automation
Vercel’s deployment platform hooks into your Git workflow, but the gap between pushing code and knowing whether your deployment is production-ready still requires human judgment. Claude skills fill that gap: the tdd skill catches missing tests before deployment, frontend-design flags accessibility regressions, pdf generates release notes, and supermemory tracks deployment history for incident context. This guide covers Claude skills with Vercel deployment automation from Vercel API setup through full pre- and post-deployment pipelines.
What You Will Build
- Pre-deployment gate: Claude
tddskill reviews staged changes and blocks deploys with critical test gaps - Post-deployment check: Claude validates the live deployment against a checklist
- Automated changelog:
pdfskill generates structured release notes from commit history - Incident context:
supermemoryskill stores deployment metadata for faster debugging
Prerequisites
- Vercel account with a deployed project
- Vercel API token (from vercel.com/account/tokens)
- GitHub repository connected to Vercel
- Claude API key
- Node.js 18+
Step 1: Get Your Vercel API Token
- Go to vercel.com/account/tokens
- Create a token with Full Account scope (or project-scoped for tighter security)
- Store it as
VERCEL_TOKENin your environment
Step 2: Set Up the Project
mkdir claude-vercel-automation && cd claude-vercel-automation
npm init -y
npm install @anthropic-ai/sdk dotenv node-fetch
Create .env:
VERCEL_TOKEN=your_vercel_token
VERCEL_TEAM_ID=your_team_id_or_empty
VERCEL_PROJECT_ID=your_project_id
ANTHROPIC_API_KEY=your_claude_api_key
GITHUB_TOKEN=your_github_token
Find your project ID in Vercel project settings under the General tab.
Step 3: Vercel API Client
require('dotenv').config();
const fetch = require('node-fetch');
const VERCEL_BASE = 'https://api.vercel.com';
const headers = {
Authorization: `Bearer ${process.env.VERCEL_TOKEN}`,
'Content-Type': 'application/json',
};
const teamParam = process.env.VERCEL_TEAM_ID
? `?teamId=${process.env.VERCEL_TEAM_ID}`
: '';
async function getLatestDeployment(projectId) {
const resp = await fetch(
`${VERCEL_BASE}/v6/deployments${teamParam}&projectId=${projectId}&limit=1`,
{ headers }
);
const data = await resp.json();
return data.deployments?.[0];
}
async function getDeploymentStatus(deploymentId) {
const resp = await fetch(
`${VERCEL_BASE}/v13/deployments/${deploymentId}${teamParam}`,
{ headers }
);
return resp.json();
}
async function cancelDeployment(deploymentId) {
await fetch(
`${VERCEL_BASE}/v12/deployments/${deploymentId}/cancel${teamParam}`,
{ method: 'PATCH', headers }
);
}
Step 4: Pre-Deployment TDD Gate
Run the tdd skill on staged changes before Vercel deploys:
const Anthropic = require('@anthropic-ai/sdk');
const { execSync } = require('child_process');
const claude = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
async function runTDDGate(diffContent) {
const message = await claude.messages.create({
model: 'claude-opus-4-6',
max_tokens: 1024,
system: `You are the TDD skill for Claude Code. You are a pre-deployment gate.
Analyze the provided diff for critical test coverage issues.
Return JSON: { "approved": true/false, "risk_level": "low|medium|high", "issues": [], "blocking_reason": "" }
Approve unless there are CRITICAL untested code paths in business logic.`,
messages: [{
role: 'user',
content: `Review this diff for deployment approval:\n\n${diffContent.slice(0, 8000)}`,
}],
});
try {
return JSON.parse(message.content[0].text);
} catch {
return { approved: true, risk_level: 'unknown', issues: [], blocking_reason: '' };
}
}
async function preDeploymentCheck() {
console.log('Running pre-deployment TDD gate...');
// Get diff from last merge commit
const diff = execSync('git diff HEAD~1 -- "*.ts" "*.tsx" "*.js"').toString();
if (!diff.trim()) {
console.log('No code changes detected — skipping TDD gate');
return { approved: true };
}
const result = await runTDDGate(diff);
console.log(`TDD Gate: ${result.approved ? 'APPROVED' : 'BLOCKED'} (${result.risk_level} risk)`);
if (!result.approved) {
console.error('Deployment blocked by TDD gate:');
console.error(result.blocking_reason);
result.issues?.forEach(issue => console.error(` - ${issue}`));
}
return result;
}
Step 5: Integrate with GitHub Actions for Vercel
Use the gate in your GitHub Actions workflow. This runs before Vercel’s automatic deployment:
# .github/workflows/deploy.yml
name: Deploy with Claude Gate
on:
push:
branches: [main]
jobs:
claude-gate:
runs-on: ubuntu-latest
outputs:
approved: ${{ steps.gate.outputs.approved }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run Claude TDD gate
id: gate
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
node scripts/pre-deploy-gate.js
echo "approved=true" >> $GITHUB_OUTPUT
continue-on-error: true
deploy:
needs: claude-gate
if: needs.claude-gate.outputs.approved == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Vercel
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
run: |
npm install -g vercel
vercel pull --yes --environment=production --token=$VERCEL_TOKEN
vercel build --prod --token=$VERCEL_TOKEN
vercel deploy --prebuilt --prod --token=$VERCEL_TOKEN
Step 6: Post-Deployment Frontend Design Check
After deployment, validate the live site with the frontend-design skill:
async function postDeploymentCheck(deploymentUrl) {
// Fetch the deployed page HTML
const resp = await fetch(deploymentUrl);
const html = await resp.text();
// Extract visible text and structure (simplified)
const textContent = html
.replace(/<script[\s\S]*?<\/script>/gi, '')
.replace(/<style[\s\S]*?<\/style>/gi, '')
.replace(/<[^>]+>/g, ' ')
.replace(/\s+/g, ' ')
.trim()
.slice(0, 4000);
const message = await claude.messages.create({
model: 'claude-opus-4-6',
max_tokens: 1024,
system: `You are the frontend-design skill for Claude Code.
Review this deployed page for: missing meta tags, poor heading structure,
obvious accessibility issues, and broken content. Return JSON:
{ "passed": true/false, "issues": [], "warnings": [] }`,
messages: [{
role: 'user',
content: `Check this deployed page:\nURL: ${deploymentUrl}\n\nContent:\n${textContent}`,
}],
});
try {
return JSON.parse(message.content[0].text);
} catch {
return { passed: true, issues: [], warnings: [] };
}
}
Step 7: Generate Changelog with PDF Skill
async function generateChangelog(fromCommit, toCommit = 'HEAD') {
const { execSync } = require('child_process');
const commits = execSync(
`git log ${fromCommit}..${toCommit} --pretty=format:"%h %s" --no-merges`
).toString();
const message = await claude.messages.create({
model: 'claude-opus-4-6',
max_tokens: 1024,
system: `You are the PDF processing skill for Claude Code.
Generate a user-facing changelog from commit messages.
Group by: Features, Bug Fixes, Performance, Other.
Write for end users, not developers. Skip internal refactors.`,
messages: [{
role: 'user',
content: `Generate changelog from these commits:\n\n${commits}`,
}],
});
return message.content[0].text;
}
Step 8: Store Deployment History with Supermemory
Track deployments for incident response:
async function recordDeployment(deployment, gateResult, checkResult) {
const context = `
Deployment ${deployment.url}
Commit: ${deployment.meta?.githubCommitSha?.slice(0, 8)}
Time: ${new Date().toISOString()}
TDD Gate: ${gateResult.approved ? 'PASSED' : 'BLOCKED'} (${gateResult.risk_level})
Post-Check: ${checkResult.passed ? 'PASSED' : 'FAILED'}
Issues: ${[...gateResult.issues || [], ...checkResult.issues || []].join(', ') || 'None'}
`.trim();
await claude.messages.create({
model: 'claude-opus-4-6',
max_tokens: 256,
system: `You are the supermemory skill for Claude Code. Acknowledge storage of deployment context.`,
messages: [{ role: 'user', content: `Store this deployment record:\n\n${context}` }],
});
// In production, also write to a database
console.log('Deployment recorded in supermemory');
}
Step 9: Full Pipeline Script
async function fullDeploymentPipeline() {
const projectId = process.env.VERCEL_PROJECT_ID;
// 1. Pre-deployment gate
const gateResult = await preDeploymentCheck();
if (!gateResult.approved) {
process.exit(1); // Block deployment in CI
}
// 2. Deployment happens via Vercel (triggered by git push)
// Wait for it to complete
console.log('Waiting for Vercel deployment...');
await new Promise(r => setTimeout(r, 30000)); // In practice, poll the API
// 3. Get latest deployment
const deployment = await getLatestDeployment(projectId);
// 4. Post-deployment check
const checkResult = await postDeploymentCheck(`https://${deployment.url}`);
console.log(`Post-deployment: ${checkResult.passed ? 'PASSED' : 'ISSUES FOUND'}`);
// 5. Generate changelog
const changelog = await generateChangelog('HEAD~5');
console.log('Changelog generated');
// 6. Record in supermemory
await recordDeployment(deployment, gateResult, checkResult);
return { gateResult, checkResult, changelog };
}
fullDeploymentPipeline().catch(console.error);
Conclusion
Claude skills with Vercel deployment automation creates an intelligent deployment pipeline that catches issues before they reach production. The tdd skill acts as a quality gate, frontend-design validates the live result, pdf generates stakeholder-ready changelogs, and supermemory builds deployment history for incident response. The GitHub Actions integration in Step 5 is the practical starting point — add post-deployment checks once your gate is running reliably.
Related Reading
- Best Claude Skills for DevOps and Deployment — The DevOps skills that integrate naturally with Vercel deployment workflows, including tdd, pdf, and supermemory
- Best Claude Skills for Developers in 2026 — A comprehensive overview of the developer skills ecosystem that powers intelligent deployment pipelines
- Claude Skills Token Optimization: Reduce API Costs — Deployment pipelines run frequently; these techniques help keep per-deployment API costs predictable
Built by theluckystrike — More at zovo.one