Vercel provides a powerful platform for deploying Next.js applications with automatic scaling and built-in CI/CD. This guide covers deploying AgentDoor with Next.js to Vercel.
Quick Deploy
Deploy the Vercel template in one click:
Click Deploy Button
Click the “Deploy with Vercel” button above to clone the template and create a new project.
Configure Repository
Choose a name for your repository and select whether to make it public or private.
Set Environment Variables
Set the X402_WALLET environment variable to your wallet address for receiving micropayments.
Deploy
Vercel automatically builds and deploys your application.
Manual Setup
For custom deployments or integration into existing Next.js projects:
1. Install Dependencies
npm install next react react-dom @agentdoor/next
2. Create Middleware
Create middleware.ts in your project root with AgentDoor configuration:
import { createAgentDoorMiddleware } from '@agentdoor/next' ;
export default createAgentDoorMiddleware ({
scopes: [
{ id: 'data.read' , description: 'Read application data' , price: '$0.001/req' },
{ id: 'data.write' , description: 'Write application data' , price: '$0.01/req' },
] ,
service: {
name: 'My Agent-Ready API' ,
description: 'Next.js API with AgentDoor authentication' ,
} ,
x402: {
network: 'base' ,
currency: 'USDC' ,
paymentAddress: process . env . X402_WALLET || '0xYourWalletAddress' ,
} ,
}) ;
export const config = {
matcher: [ '/api/:path*' , '/.well-known/:path*' , '/agentdoor/:path*' ],
};
3. Create API Routes
Create API routes in app/api/ (App Router) or pages/api/ (Pages Router):
App Router (app/api/data/route.ts)
import { NextRequest , NextResponse } from 'next/server' ;
export async function GET ( request : NextRequest ) {
// AgentDoor middleware has already validated authentication
const agentId = request . headers . get ( 'x-agentdoor-agent-id' );
const scopes = request . headers . get ( 'x-agentdoor-scopes' );
return NextResponse . json ({
success: true ,
data: [ /* your data */ ],
meta: {
agent: agentId || 'anonymous' ,
scopes: scopes ? scopes . split ( ',' ) : [],
},
});
}
export async function POST ( request : NextRequest ) {
const agentId = request . headers . get ( 'x-agentdoor-agent-id' );
const scopes = request . headers . get ( 'x-agentdoor-scopes' );
const grantedScopes = scopes ? scopes . split ( ',' ) : [];
if ( ! grantedScopes . includes ( 'data.write' )) {
return NextResponse . json (
{ success: false , error: 'Insufficient scope: data.write required' },
{ status: 403 }
);
}
const body = await request . json ();
return NextResponse . json ({
success: true ,
data: body ,
meta: { agent: agentId }
});
}
Pages Router (pages/api/data.ts)
import type { NextApiRequest , NextApiResponse } from 'next' ;
export default function handler (
req : NextApiRequest ,
res : NextApiResponse
) {
const agentId = req . headers [ 'x-agentdoor-agent-id' ] as string ;
const scopes = ( req . headers [ 'x-agentdoor-scopes' ] as string || '' ). split ( ',' );
if ( req . method === 'GET' ) {
return res . status ( 200 ). json ({
success: true ,
data: [ /* your data */ ],
meta: { agent: agentId , scopes },
});
}
if ( req . method === 'POST' ) {
if ( ! scopes . includes ( 'data.write' )) {
return res . status ( 403 ). json ({
success: false ,
error: 'Insufficient scope: data.write required'
});
}
return res . status ( 201 ). json ({
success: true ,
data: req . body ,
meta: { agent: agentId }
});
}
res . status ( 405 ). json ({ error: 'Method not allowed' });
}
Create or update next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true ,
// Enable serverless functions
experimental: {
// Optimize for serverless
outputStandalone: true ,
},
};
module . exports = nextConfig ;
5. Create vercel.json (Optional)
For custom configuration, create vercel.json:
{
"framework" : "nextjs" ,
"buildCommand" : "next build" ,
"devCommand" : "next dev" ,
"installCommand" : "npm install" ,
"functions" : {
"app/api/**/*.ts" : {
"maxDuration" : 10
}
}
}
Deployment Methods
Deploy with Vercel CLI
Deploy
# Deploy to preview
vercel
# Deploy to production
vercel --prod
Deploy with Git Integration
Connect Repository
Go to Vercel Dashboard
Click Add New → Project
Import your Git repository (GitHub, GitLab, or Bitbucket)
Configure Project
Vercel automatically detects Next.js configuration. Adjust if needed:
Framework Preset : Next.js
Build Command : next build
Output Directory : .next
Set Environment Variables
Add environment variables in the Vercel dashboard or during setup.
Deploy
Click Deploy . Vercel builds and deploys your application automatically.
Automatic Deployments
Once connected to Git, Vercel automatically:
Deploys every push to production branch (e.g., main)
Creates preview deployments for pull requests
Runs build checks and provides deployment URLs
Environment Variables
Manage environment variables via Vercel dashboard or CLI.
Required Variables
Variable Description Required X402_WALLETWallet address for receiving x402 payments Yes DATABASE_URLPostgreSQL connection string (if using database) Conditional
Setting Variables via Dashboard
Open Project Settings
Navigate to your project in Vercel dashboard and click Settings .
Add Environment Variables
Go to Environment Variables section and click Add New .
Configure Variable
Name : X402_WALLET
Value : Your wallet address
Environments : Select Production, Preview, and/or Development
Save
Click Save . Redeploy your application to apply changes.
Setting Variables via CLI
# Add environment variable
vercel env add X402_WALLET
# Enter value when prompted
# Select environments (production, preview, development)
# List environment variables
vercel env ls
# Pull environment variables to .env.local
vercel env pull .env.local
Local Development
Create .env.local for local development:
# .env.local (never commit this file)
X402_WALLET = 0xYourWalletAddress
DATABASE_URL = postgresql://localhost:5432/agentdoor
Next.js automatically loads .env.local during development.
Storage Configuration
Vercel serverless functions are stateless. Use external storage:
PostgreSQL (Recommended)
Use managed PostgreSQL services like:
import { PostgresStore } from '@agentdoor/core/storage/postgres' ;
const store = new PostgresStore ({
connectionString: process . env . DATABASE_URL
});
export default createAgentDoorMiddleware ({
// ... other config
storage: store
}) ;
Vercel Postgres (Integrated)
Vercel provides integrated PostgreSQL:
Create Database
In Vercel dashboard:
Navigate to Storage tab
Click Create Database
Select Postgres
Connect to Project
Link the database to your project. Vercel automatically sets environment variables:
POSTGRES_URL
POSTGRES_PRISMA_URL
POSTGRES_URL_NON_POOLING
Use in Application
import { PostgresStore } from '@agentdoor/core/storage/postgres' ;
const store = new PostgresStore ({
connectionString: process . env . POSTGRES_URL
});
Redis (Session Storage)
For caching and session data:
import { createClient } from 'redis' ;
const redis = createClient ({
url: process . env . REDIS_URL
});
await redis . connect ();
Consider Upstash Redis for serverless-compatible Redis.
Edge Middleware vs Serverless Functions
Vercel supports both Edge Middleware and Serverless Functions:
Edge Middleware
Runs at the edge before requests reach functions:
// middleware.ts
import { createAgentDoorMiddleware } from '@agentdoor/next' ;
export default createAgentDoorMiddleware ({
// ... config
}) ;
export const config = {
matcher: [ '/api/:path*' ],
};
Pros:
Faster response times (runs at edge)
Lower costs (runs before functions)
Global distribution
Cons:
Limited runtime APIs
4MB size limit
Cannot use Node.js-specific modules
Serverless Functions
Runs in serverless functions:
// app/api/data/route.ts
import { NextRequest , NextResponse } from 'next/server' ;
export async function GET ( request : NextRequest ) {
// Full Node.js runtime available
}
Pros:
Full Node.js runtime
No size restrictions
Access to all npm packages
Cons:
Higher latency
Cold starts
Higher costs
AgentDoor middleware works in both Edge and Serverless contexts. Choose based on your requirements.
Custom Domains
Add Domain
In Vercel dashboard:
Navigate to Settings → Domains
Enter your domain name
Click Add
Configure DNS
Vercel provides DNS configuration instructions: Option A: Nameservers (Recommended)
Point your domain’s nameservers to Vercel:ns1.vercel-dns.com
ns2.vercel-dns.com
Option B: A Record
Add an A record pointing to Vercel:Option C: CNAME
Add a CNAME record:CNAME api cname.vercel-dns.com
Verify
Vercel automatically verifies DNS configuration and provisions SSL certificates.
Enable Caching
Cache responses at the edge:
export async function GET ( request : NextRequest ) {
const response = NextResponse . json ({ data: [] });
// Cache for 60 seconds
response . headers . set ( 'Cache-Control' , 'public, s-maxage=60, stale-while-revalidate=30' );
return response ;
}
Optimize Bundle Size
Reduce function size:
// next.config.js
module . exports = {
experimental: {
optimizePackageImports: [ '@agentdoor/next' ],
},
};
Use Edge Runtime
Opt into Edge Runtime for better performance:
export const runtime = 'edge' ; // Use Edge Runtime
export async function GET ( request : NextRequest ) {
// This runs at the edge
}
Monitoring and Logs
Viewing Logs
View logs in Vercel dashboard:
Navigate to your project
Click Logs tab
Filter by deployment, function, or time range
Or via CLI:
# Stream logs
vercel logs
# View logs for specific deployment
vercel logs [deployment-url]
Analytics
Enable Vercel Analytics:
// app/layout.tsx
import { Analytics } from '@vercel/analytics/react' ;
export default function RootLayout ({ children }) {
return (
< html >
< body >
{ children }
< Analytics />
</ body >
</ html >
);
}
Custom Logging
Add structured logging:
export async function POST ( request : NextRequest ) {
const start = Date . now ();
try {
// Your logic here
const duration = Date . now () - start ;
console . log ( JSON . stringify ({
method: request . method ,
path: request . nextUrl . pathname ,
duration ,
status: 200
}));
return NextResponse . json ({ success: true });
} catch ( error ) {
console . error ( 'Request failed:' , error );
return NextResponse . json ({ error: 'Internal error' }, { status: 500 });
}
}
Scaling
Automatic Scaling
Vercel automatically scales serverless functions based on traffic. No configuration required.
Resource Limits
Tier Execution Time Memory Bandwidth Hobby 10s 1024MB 100GB/month Pro 60s 3008MB 1TB/month Enterprise 900s 3008MB Custom
Concurrency
Each function instance handles one request at a time. Vercel creates new instances as needed.
Troubleshooting
Build Failures
Common issues:
TypeScript errors : Run npm run build locally to check
Missing dependencies : Ensure all dependencies are in package.json
Environment variables : Verify variables are set for build environment
Function Timeouts
If functions timeout:
Optimize slow operations
Use background jobs for long tasks
Upgrade to Pro for longer execution time
Cold Starts
Reduce cold start impact:
Minimize dependencies
Use Edge Runtime when possible
Keep functions small and focused
Database Connection Issues
For connection pooling:
import { Pool } from 'pg' ;
const pool = new Pool ({
connectionString: process . env . POSTGRES_URL ,
max: 10 , // Connection pool size
});
export async function GET () {
const client = await pool . connect ();
try {
// Use client
} finally {
client . release ();
}
}
Or use a connection pooler like PgBouncer .
Best Practices
Use Environment Variables : Never hardcode secrets in code.
Enable Analytics : Monitor performance and usage patterns.
Configure Caching : Cache responses to reduce function invocations.
Optimize Bundle Size : Keep dependencies minimal for faster cold starts.
Use Edge Runtime : When possible, use Edge Runtime for better performance.
Set Function Timeouts : Configure appropriate timeouts in vercel.json.
Monitor Logs : Regularly review logs for errors and performance issues.
Next Steps
Next.js Integration Learn more about Next.js with AgentDoor
PostgreSQL Storage Configure PostgreSQL storage
Rate Limiting Configure rate limits for serverless functions
Vercel Docs Official Vercel documentation