Next.js Integration
Edge-optimized AI agent detection for Next.js applications
Overview
The AgentShield Next.js integration provides seamless AI agent detection and protection for your Next.js applications. With edge runtime optimization and full App Router support, it delivers enterprise-grade protection with minimal performance impact.
Features
Performance
- Edge Runtime Compatible - Runs at the edge for ultra-low latency
- < 2ms overhead - Minimal impact on response times
- Streaming Support - Works with Next.js streaming responses
- ISR Compatible - Works with Incremental Static Regeneration
Protection
- Middleware-based - Protect all routes automatically
- Route Matching - Fine-grained control over protected paths
- Session Tracking - Track agents across multiple requests
- Custom Actions - Flexible response strategies
React Integration
- Server Components - Full RSC support
- Client Hooks - React hooks for client-side detection
- TypeScript - Full type safety
- App Router - Native App Router support
Installation
npm install @kya-os/agentshield-nextjs
Quick Setup
1. Create Middleware
Create middleware.ts
in your project root:
import { agentShield } from '@kya-os/agentshield-nextjs';
export default agentShield({
apiKey: process.env.AGENTSHIELD_API_KEY!,
onAgentDetected: 'block',
confidenceThreshold: 0.8,
});
export const config = {
matcher: [
/*
* Match all request paths except:
* - api routes
* - static files
* - image optimization files
* - favicon
*/
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
};
2. Server Component Usage
// app/page.tsx
import { headers } from 'next/headers';
export default function Page() {
const headersList = headers();
const detection = headersList.get('x-agentshield-detection');
if (detection) {
const result = JSON.parse(detection);
if (result.isAgent) {
return <div>Access Restricted</div>;
}
}
return <div>Welcome!</div>;
}
3. Client Component Usage
'use client';
import { useAgentDetection } from '@kya-os/agentshield-nextjs';
export function ProtectedContent() {
const { isAgent, confidence, isLoading } = useAgentDetection();
if (isLoading) return <div>Checking...</div>;
if (isAgent) return <div>Content not available</div>;
return <div>Premium content here</div>;
}
1. Create Middleware
Create middleware.ts
in your project root:
import { agentShield } from '@kya-os/agentshield-nextjs';
export default agentShield({
apiKey: process.env.AGENTSHIELD_API_KEY!,
onAgentDetected: 'block',
confidenceThreshold: 0.8,
});
export const config = {
matcher: '/:path*',
};
2. API Route Protection
// pages/api/protected.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const detection = req.headers['x-agentshield-detection'];
if (detection) {
const result = JSON.parse(detection as string);
if (result.isAgent) {
return res.status(403).json({ error: 'Access denied' });
}
}
res.status(200).json({ data: 'Protected data' });
}
3. Page Component Usage
// pages/protected.tsx
import { useAgentDetection } from '@kya-os/agentshield-nextjs';
export default function ProtectedPage() {
const { isAgent, confidence } = useAgentDetection();
if (isAgent) {
return <div>This content is protected</div>;
}
return <div>Welcome to the protected page</div>;
}
Configuration Options
Basic Configuration
agentShield({
// Required
apiKey: string; // Your API key
// Detection Settings
onAgentDetected: 'block' | 'log' | 'redirect' | 'custom';
confidenceThreshold: number; // 0-1 (default: 0.8)
// Response Customization
blockMessage?: string; // Custom block message
redirectUrl?: string; // Redirect URL for agents
customHandler?: (req, result) => Response; // Custom response handler
// Advanced Options
sessionTracking?: {
enabled: boolean; // Track sessions (default: true)
storage?: 'cookie' | 'header'; // Storage method
duration?: number; // Session duration in ms
};
skipPaths?: string[]; // Paths to skip detection
allowedAgents?: string[]; // Whitelisted user agents
// Performance
cacheDetection?: boolean; // Cache detection results
cacheDuration?: number; // Cache TTL in seconds
// Debug
debug?: boolean; // Enable debug logging
logLevel?: 'error' | 'warn' | 'info' | 'debug';
});
Environment Variables
# .env.local
AGENTSHIELD_API_KEY=your_api_key_here
AGENTSHIELD_ACTION=block
AGENTSHIELD_THRESHOLD=0.8
AGENTSHIELD_DEBUG=false
Advanced Configuration Example
export default agentShield({
apiKey: process.env.AGENTSHIELD_API_KEY!,
onAgentDetected: 'custom',
confidenceThreshold: 0.85,
// Custom response handler
customHandler: async (req, result) => {
// Log detection
await logToAnalytics({
agent: result.signals.userAgent,
confidence: result.confidence,
path: req.nextUrl.pathname,
});
// Custom response based on confidence
if (result.confidence > 0.95) {
return new Response('Access Denied', { status: 403 });
} else if (result.confidence > 0.8) {
return NextResponse.redirect(new URL('/challenge', req.url));
}
return NextResponse.next();
},
// Session tracking
sessionTracking: {
enabled: true,
storage: 'cookie',
duration: 24 * 60 * 60 * 1000, // 24 hours
},
// Skip certain paths
skipPaths: [
'/api/webhooks',
'/health',
'/robots.txt',
],
// Allow specific bots
allowedAgents: [
'Googlebot',
'Bingbot',
],
// Performance optimization
cacheDetection: true,
cacheDuration: 300, // 5 minutes
});
React Hooks
useAgentDetection
Monitor detection status in your components:
import { useAgentDetection } from '@kya-os/agentshield-nextjs';
function Component() {
const {
isAgent, // Boolean: detected as agent
confidence, // Number: confidence score (0-1)
signals, // Object: detection signals
isLoading, // Boolean: detection in progress
error, // Error: detection error if any
refetch, // Function: re-run detection
} = useAgentDetection();
if (isAgent && confidence > 0.9) {
return <BlockedContent />;
}
return <NormalContent />;
}
useAgentShield
Access the full AgentShield client:
import { useAgentShield } from '@kya-os/agentshield-nextjs';
function Component() {
const shield = useAgentShield();
const handleSensitiveAction = async () => {
const result = await shield.verify();
if (result.isAgent) {
alert('This action is not available');
return;
}
// Proceed with sensitive action
};
return (
<button onClick={handleSensitiveAction}>
Sensitive Action
</button>
);
}
Edge Runtime Optimization
AgentShield is fully optimized for Next.js Edge Runtime, providing ultra-fast detection at the edge.
Edge API Routes
// app/api/protected/route.ts
import { NextRequest } from 'next/server';
export const runtime = 'edge';
export async function GET(request: NextRequest) {
const detection = request.headers.get('x-agentshield-detection');
if (detection) {
const result = JSON.parse(detection);
if (result.isAgent) {
return new Response('Forbidden', { status: 403 });
}
}
return new Response('Protected data');
}
Edge Middleware
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { agentShield } from '@kya-os/agentshield-nextjs';
export const runtime = 'edge';
export default agentShield({
apiKey: process.env.AGENTSHIELD_API_KEY!,
onAgentDetected: 'block',
});
Session Tracking
Track AI agents across multiple requests:
export default agentShield({
apiKey: process.env.AGENTSHIELD_API_KEY!,
sessionTracking: {
enabled: true,
storage: 'cookie', // Use cookies for session storage
duration: 86400000, // 24 hour sessions
// Optional: Custom session ID generator
generateId: () => crypto.randomUUID(),
// Optional: Session data enrichment
enrichSession: (session) => ({
...session,
timestamp: Date.now(),
region: process.env.VERCEL_REGION,
}),
},
});
Custom Response Strategies
Challenge Page
customHandler: async (req, result) => {
if (result.confidence > 0.7) {
// Redirect to challenge page
const challengeUrl = new URL('/challenge', req.url);
challengeUrl.searchParams.set('return', req.nextUrl.pathname);
return NextResponse.redirect(challengeUrl);
}
return NextResponse.next();
}
Rate Limiting
customHandler: async (req, result) => {
if (result.isAgent) {
// Apply rate limiting for detected agents
const ip = req.ip || req.headers.get('x-forwarded-for');
const rateLimitKey = `agent_${ip}`;
const limited = await checkRateLimit(rateLimitKey);
if (limited) {
return new Response('Too Many Requests', { status: 429 });
}
}
return NextResponse.next();
}
A/B Testing
customHandler: async (req, result) => {
if (result.isAgent && result.confidence > 0.6) {
// A/B test different responses
const variant = Math.random() > 0.5 ? 'A' : 'B';
if (variant === 'A') {
return new Response('Access Restricted', { status: 403 });
} else {
return NextResponse.redirect(new URL('/limited', req.url));
}
}
return NextResponse.next();
}
Monitoring & Analytics
Custom Logging
export default agentShield({
apiKey: process.env.AGENTSHIELD_API_KEY!,
onAgentDetected: 'log',
// Custom logging
onDetection: async (result) => {
// Send to your analytics
await fetch('/api/analytics', {
method: 'POST',
body: JSON.stringify({
event: 'agent_detected',
...result,
}),
});
},
});
Vercel Analytics Integration
import { track } from '@vercel/analytics';
export default agentShield({
apiKey: process.env.AGENTSHIELD_API_KEY!,
onDetection: async (result) => {
if (result.isAgent) {
track('agent_detected', {
confidence: result.confidence,
userAgent: result.signals.userAgent,
});
}
},
});
Troubleshooting
Common Issues
Content Security Policy (CSP) Errors
If you're using the pixel.js and seeing errors like:
Refused to load the script 'https://kya.vouched.id/pixel.js'
because it violates the following Content Security Policy directive
Solution: Add AgentShield domains to your CSP headers:
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'Content-Security-Policy',
value: [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://kya.vouched.id https://agentshield.io",
"connect-src 'self' https://kya.vouched.id https://agentshield.io",
"img-src 'self' data: https:",
"style-src 'self' 'unsafe-inline'",
].join('; ')
}
]
}
]
}
}
Alternative Solutions:
- Proxy the script through your API routes
- Self-host the pixel script (requires manual updates)
- Use middleware to dynamically add CSP headers
See our Pixel documentation for detailed CSP configuration instructions.
Middleware not running
- Ensure
middleware.ts
is in the project root - Check the
matcher
configuration - Verify the file exports a default function
Detection not working
- Verify API key is correct
- Check network tab for API calls
- Enable debug mode for detailed logs
- If using pixel.js, check browser console for CSP errors
Performance issues
- Enable caching with
cacheDetection: true
- Adjust
confidenceThreshold
if too sensitive - Use
skipPaths
for non-critical routes
Debug Mode
Enable detailed logging:
export default agentShield({
apiKey: process.env.AGENTSHIELD_API_KEY!,
debug: true,
logLevel: 'debug',
});
Check console for:
- Detection results
- API responses
- Performance metrics
- Error messages
Best Practices
- Use Environment Variables - Never hardcode API keys
- Configure Matchers - Only protect necessary routes
- Enable Caching - Reduce API calls with caching
- Monitor Performance - Track middleware overhead
- Test Thoroughly - Test with various user agents
- Handle Errors - Implement fallback strategies
- Respect Privacy - Follow GDPR guidelines
Next Steps
- Middleware Setup - Detailed middleware configuration
- App Router Examples - App Router specific patterns
- React Hooks - Client-side integration
- Edge Runtime - Edge optimization guide