Claude Code Plugins

Community-maintained marketplace

Feedback

moai-platform-vercel

@modu-ai/moai-adk
391
0

Vercel edge deployment specialist covering Edge Functions, Next.js optimization, preview deployments, and ISR. Use when deploying Next.js or edge-first applications.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name moai-platform-vercel
description Vercel edge deployment specialist covering Edge Functions, Next.js optimization, preview deployments, and ISR. Use when deploying Next.js or edge-first applications.
version 1.0.0
category platform
tags vercel, edge, nextjs, isr, preview, cdn
context7-libraries /vercel/next.js, /vercel/vercel
related-skills moai-platform-railway, moai-lang-typescript
updated Sun Dec 07 2025 00:00:00 GMT+0000 (Coordinated Universal Time)
status active
allowed-tools Read, Write, Bash, Grep, Glob

moai-platform-vercel: Vercel Edge Deployment Specialist

Quick Reference (30 seconds)

Vercel Optimization Focus: Edge-first deployment platform with global CDN, Next.js optimized runtime, and developer-centric preview workflows.

Core Capabilities

Edge Functions:

  • Global low-latency compute at 30+ edge locations
  • Sub-50ms cold start for optimal user experience
  • Geo-based routing and personalization
  • Edge middleware for request/response transformation

Next.js Optimized Runtime:

  • First-class Next.js support with automatic optimizations
  • Server Components and App Router integration
  • Streaming SSR for improved TTFB
  • Built-in image optimization with next/image

Preview Deployments:

  • Automatic PR-based preview URLs
  • Branch-specific environment variables
  • Comment integration for PR reviews
  • Instant rollback capabilities

ISR (Incremental Static Regeneration):

  • On-demand revalidation for dynamic content
  • Stale-while-revalidate caching strategy
  • Tag-based cache invalidation
  • Background regeneration without user impact

Quick Decision Guide

Choose Vercel When:

  • Next.js is primary framework
  • Edge performance is critical requirement
  • Preview deployments needed for team collaboration
  • Web Vitals monitoring is priority

Implementation Guide

Phase 1: Edge Functions Architecture

Edge Runtime Configuration:

// app/api/edge-handler/route.ts
export const runtime = 'edge'
export const preferredRegion = ['iad1', 'sfo1', 'fra1']

export async function GET(request: Request) {
  const { geo, ip } = request

  return Response.json({
    country: geo?.country ?? 'Unknown',
    city: geo?.city ?? 'Unknown',
    region: geo?.region ?? 'Unknown',
    ip: ip ?? 'Unknown',
    timestamp: new Date().toISOString()
  })
}

Edge Function Patterns:

Geo-Based Content Delivery:

// app/api/localized/route.ts
export const runtime = 'edge'

const CONTENT_BY_REGION: Record<string, { currency: string; locale: string }> = {
  US: { currency: 'USD', locale: 'en-US' },
  DE: { currency: 'EUR', locale: 'de-DE' },
  JP: { currency: 'JPY', locale: 'ja-JP' },
  KR: { currency: 'KRW', locale: 'ko-KR' }
}

export async function GET(request: Request) {
  const country = request.geo?.country ?? 'US'
  const config = CONTENT_BY_REGION[country] ?? CONTENT_BY_REGION.US

  return Response.json(config, {
    headers: {
      'Cache-Control': 'public, s-maxage=3600',
      'CDN-Cache-Control': 'public, max-age=86400'
    }
  })
}

A/B Testing at Edge:

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const existingBucket = request.cookies.get('ab-bucket')?.value

  if (!existingBucket) {
    const bucket = Math.random() < 0.5 ? 'control' : 'variant'
    const response = NextResponse.next()
    response.cookies.set('ab-bucket', bucket, {
      maxAge: 60 * 60 * 24 * 30, // 30 days
      httpOnly: true,
      sameSite: 'lax'
    })
    return response
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)']
}

Phase 2: Next.js Optimization Patterns

ISR Implementation:

// app/products/[id]/page.tsx
import { notFound } from 'next/navigation'

// Revalidate every 60 seconds
export const revalidate = 60

// Generate static params for top products
export async function generateStaticParams() {
  const products = await fetch('https://api.example.com/products/top').then(r => r.json())
  return products.map((p: { id: string }) => ({ id: p.id }))
}

// Dynamic metadata for SEO
export async function generateMetadata({ params }: { params: { id: string } }) {
  const product = await fetchProduct(params.id)
  if (!product) return {}

  return {
    title: product.name,
    description: product.description,
    openGraph: {
      images: [product.imageUrl]
    }
  }
}

export default async function ProductPage({ params }: { params: { id: string } }) {
  const product = await fetchProduct(params.id)
  if (!product) notFound()

  return <ProductDetail product={product} />
}

async function fetchProduct(id: string) {
  const res = await fetch(`https://api.example.com/products/${id}`, {
    next: { tags: [`product-${id}`] }
  })
  if (!res.ok) return null
  return res.json()
}

On-Demand Revalidation:

// app/api/revalidate/route.ts
import { revalidateTag, revalidatePath } from 'next/cache'
import { NextRequest } from 'next/server'

export async function POST(request: NextRequest) {
  const { tag, path, secret } = await request.json()

  // Validate webhook secret
  if (secret !== process.env.REVALIDATION_SECRET) {
    return Response.json({ error: 'Invalid secret' }, { status: 401 })
  }

  try {
    if (tag) {
      revalidateTag(tag)
      return Response.json({ revalidated: true, tag })
    }

    if (path) {
      revalidatePath(path)
      return Response.json({ revalidated: true, path })
    }

    return Response.json({ error: 'Missing tag or path' }, { status: 400 })
  } catch (error) {
    return Response.json({ error: 'Revalidation failed' }, { status: 500 })
  }
}

Streaming with Suspense:

// app/dashboard/page.tsx
import { Suspense } from 'react'

export default function DashboardPage() {
  return (
    <div className="dashboard">
      <h1>Dashboard</h1>

      <Suspense fallback={<MetricsSkeleton />}>
        <Metrics />
      </Suspense>

      <Suspense fallback={<ChartSkeleton />}>
        <AnalyticsChart />
      </Suspense>

      <Suspense fallback={<TableSkeleton />}>
        <RecentOrders />
      </Suspense>
    </div>
  )
}

async function Metrics() {
  const data = await fetch('https://api.example.com/metrics', {
    next: { revalidate: 30 }
  }).then(r => r.json())

  return <MetricsDisplay data={data} />
}

Phase 3: Vercel Configuration

vercel.json Configuration:

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "framework": "nextjs",
  "buildCommand": "pnpm build",
  "installCommand": "pnpm install",
  "outputDirectory": ".next",
  "regions": ["iad1", "sfo1", "fra1", "hnd1"],
  "functions": {
    "app/api/**/*.ts": {
      "memory": 1024,
      "maxDuration": 30
    },
    "app/api/heavy/**/*.ts": {
      "memory": 3008,
      "maxDuration": 60
    }
  },
  "crons": [
    {
      "path": "/api/cron/cleanup",
      "schedule": "0 0 * * *"
    },
    {
      "path": "/api/cron/sync",
      "schedule": "*/15 * * * *"
    }
  ],
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        { "key": "Access-Control-Allow-Origin", "value": "*" },
        { "key": "Cache-Control", "value": "s-maxage=60, stale-while-revalidate" }
      ]
    },
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Content-Type-Options", "value": "nosniff" },
        { "key": "X-Frame-Options", "value": "DENY" },
        { "key": "X-XSS-Protection", "value": "1; mode=block" }
      ]
    }
  ],
  "rewrites": [
    { "source": "/blog/:slug", "destination": "/posts/:slug" },
    { "source": "/api/v1/:path*", "destination": "/api/:path*" }
  ],
  "redirects": [
    { "source": "/old-page", "destination": "/new-page", "permanent": true }
  ]
}

Environment Variables Management:

# Production environment
vercel env add DATABASE_URL production
vercel env add API_SECRET production
vercel env add NEXT_PUBLIC_API_URL production

# Preview environments (PR deployments)
vercel env add DATABASE_URL preview
vercel env add API_SECRET preview

# Development environment
vercel env add DATABASE_URL development

# Pull environment for local development
vercel env pull .env.local

Phase 4: Preview Deployments

GitHub Integration Setup:

# .github/workflows/vercel-preview.yml
name: Vercel Preview Deployment
on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  deploy-preview:
    runs-on: ubuntu-latest
    environment:
      name: Preview
      url: ${{ steps.deploy.outputs.url }}
    steps:
      - uses: actions/checkout@v4

      - name: Install Vercel CLI
        run: npm i -g vercel@latest

      - name: Pull Vercel Environment
        run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}

      - name: Build Project
        run: vercel build --token=${{ secrets.VERCEL_TOKEN }}

      - name: Deploy to Vercel
        id: deploy
        run: |
          url=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
          echo "url=$url" >> $GITHUB_OUTPUT

      - name: Comment PR with Preview URL
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: `Preview deployed: ${{ steps.deploy.outputs.url }}`
            })

Production Deployment:

# .github/workflows/vercel-production.yml
name: Vercel Production Deployment
on:
  push:
    branches: [main]

jobs:
  deploy-production:
    runs-on: ubuntu-latest
    environment:
      name: Production
      url: https://your-domain.com
    steps:
      - uses: actions/checkout@v4

      - name: Install Vercel CLI
        run: npm i -g vercel@latest

      - name: Pull Vercel Environment
        run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}

      - name: Build Project
        run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}

      - name: Deploy to Vercel
        run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}

Phase 5: Web Vitals Monitoring

Analytics Integration:

// app/layout.tsx
import { Analytics } from '@vercel/analytics/react'
import { SpeedInsights } from '@vercel/speed-insights/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Analytics />
        <SpeedInsights />
      </body>
    </html>
  )
}

Custom Web Vitals Reporting:

// app/components/WebVitals.tsx
'use client'

import { useReportWebVitals } from 'next/web-vitals'

export function WebVitals() {
  useReportWebVitals((metric) => {
    const body = JSON.stringify({
      name: metric.name,
      value: metric.value,
      rating: metric.rating,
      delta: metric.delta,
      id: metric.id,
      navigationType: metric.navigationType
    })

    // Send to custom analytics endpoint
    if (navigator.sendBeacon) {
      navigator.sendBeacon('/api/vitals', body)
    } else {
      fetch('/api/vitals', { body, method: 'POST', keepalive: true })
    }
  })

  return null
}

Advanced Patterns

Monorepo with Turborepo

{
  "buildCommand": "cd ../.. && pnpm turbo build --filter=web",
  "installCommand": "cd ../.. && pnpm install",
  "framework": "nextjs"
}

Blue-Green Deployment

Deploy new version, run smoke tests on preview URL, then switch production alias using Vercel SDK aliases.assign() method for zero-downtime releases.

Context7 Integration

Use /vercel/vercel for edge function patterns and /vercel/next.js for App Router, ISR, and streaming patterns with appropriate token allocation.


Works Well With

  • moai-platform-railway - Container-based deployment alternative
  • moai-lang-typescript - TypeScript patterns for Next.js
  • moai-domain-frontend - React and Next.js component patterns
  • moai-foundation-quality - Deployment validation and testing

Status: Production Ready | Version: 1.0.0 | Updated: 2025-12-07