
nextjs-vercel-pro
Complete Next.js and Vercel development toolkit with deployment automation and performance optimization
- version
- 1.0.0
- GitHub stars
- 24.2K
Install
/plugin install nextjs-vercel-pro@davila7-claude-code-templatesRun it inside Claude Code after adding the marketplace with /plugin marketplace add davila7/claude-code-templates.
Contents
Commands 7
Next.js Application Scaffolding
Project Name: $ARGUMENTS
Environment Analysis
- Current directory: !
pwd - Node.js version: !
node --version - npm version: !
npm --version - Existing package.json: @package.json (if exists)
Scaffolding Requirements
1. Project Initialization
Based on provided arguments, determine setup options:
- TypeScript: Check for
--typescriptflag or detect existing TS config - Tailwind CSS: Check for
--tailwindflag or detect existing config - App Router: Check for
--app-routerflag (default for new projects) - ESLint/Prettier: Always include for code quality
2. Next.js Configuration
Create optimized next.config.js with:
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
optimizePackageImports: ['lucide-react', '@heroicons/react'],
},
images: {
formats: ['image/webp', 'image/avif'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
},
async headers() {
return [
{
source: '/(.*)',
headers: [
{
key: 'X-Frame-Options',
value: 'DENY',
},
{
key: 'X-Content-Type-Options',
value: 'nosniff',
},
],
},
];
},
};
3. Essential Dependencies
Install core dependencies:
- Production:
next,react,react-dom - Development:
eslint,eslint-config-next,typescript(if TS),@types/*(if TS) - Optional:
tailwindcss,prettier,husky,lint-staged
4. Project Structure
Create optimal directory structure:
project-name/
├── app/ # App Router (Next.js 13+)
│ ├── globals.css
│ ├── layout.tsx
│ ├── page.tsx
│ └── api/
├── components/ # Reusable components
│ └── ui/ # UI primitives
├── lib/ # Utilities and configurations
├── public/ # Static assets
├── types/ # TypeScript type definitions
├── .env.local # Environment variables
├── .env.example # Environment template
├── .gitignore
├── next.config.js
├── package.json
├── README.md
└── tsconfig.json # If TypeScript
5. Configuration Files
ESLint Configuration
{
"extends": ["next/core-web-vitals"],
"rules": {
"@next/next/no-img-element": "error",
"@next/next/no-html-link-for-pages": "error"
}
}
TypeScript Configuration (if applicable)
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "es6"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
6. Starter Components
Root Layout
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
title: 'Project Name',
description: 'Generated with Claude Code Next.js scaffolding',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}
Home Page
export default function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm">
<h1 className="text-4xl font-bold">Welcome to Your Next.js App</h1>
<p className="mt-4 text-lg">
Built with Claude Code scaffolding
</p>
</div>
</main>
);
}
7. Development Scripts
Update package.json with optimized scripts:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"type-check": "tsc --noEmit",
"format": "prettier --write .",
"format:check": "prettier --check ."
}
}
8. Documentation
Create comprehensive README.md with:
- Project overview and features
- Installation and setup instructions
- Development workflow
- Deployment guidelines
- Contributing guidelines
Implementation Steps
- Initialize Project: Create project directory and basic structure
- Install Dependencies: Set up Next.js with chosen options
- Configure TypeScript: Set up TypeScript if requested
- Setup Tailwind: Configure Tailwind CSS if requested
- Create Components: Generate starter components and layouts
- Setup Development Tools: Configure ESLint, Prettier, and scripts
- Environment Configuration: Create .env files and examples
- Generate Documentation: Create README and setup guides
Quality Checklist
- Next.js configured with App Router
- TypeScript setup (if requested)
- Tailwind CSS configured (if requested)
- ESLint and Prettier configured
- Security headers configured
- Image optimization enabled
- Development scripts working
- Environment variables template created
- README documentation complete
- Project builds successfully
Post-Scaffolding Tasks
After scaffolding, run these commands to verify setup:
cd [project-name]
npm install
npm run build
npm run lint
npm run type-check # If TypeScript
Provide specific next steps based on the project requirements and any additional features needed.
Next.js Component Generator
Component Name: $ARGUMENTS
Project Context Analysis
Framework Detection
- Next.js config: @next.config.js
- TypeScript config: @tsconfig.json (if exists)
- Tailwind config: @tailwind.config.js (if exists)
- Package.json: @package.json
Existing Component Patterns
- Components directory: @components/
- App directory: @app/ (if App Router)
- Pages directory: @pages/ (if Pages Router)
- Styles directory: @styles/
Component Generation Requirements
1. Component Type Detection
Based on arguments and context, determine component type:
- Client Component: Interactive UI with state/events (
--clientor default for interactive components) - Server Component: Static rendering, data fetching (
--serveror default for Next.js 13+) - Page Component: Route-level component (
--page) - Layout Component: Shared layout wrapper (
--layout)
2. File Structure Creation
Generate comprehensive component structure:
components/[ComponentName]/
├── index.ts # Barrel export
├── [ComponentName].tsx # Main component
├── [ComponentName].module.css # Component styles
├── [ComponentName].test.tsx # Unit tests
├── [ComponentName].stories.tsx # Storybook story (if detected)
└── types.ts # TypeScript types
3. Component Templates
Server Component Template
import { FC } from 'react';
import styles from './ComponentName.module.css';
interface ComponentNameProps {
/**
* Component description
*/
children?: React.ReactNode;
/**
* Additional CSS classes
*/
className?: string;
}
/**
* ComponentName - Server Component
*
* @description Brief description of component purpose
* @example
* <ComponentName>Content</ComponentName>
*/
export const ComponentName: FC<ComponentNameProps> = ({
children,
className = '',
...props
}) => {
return (
<div className={`${styles.container} ${className}`} {...props}>
{children}
</div>
);
};
export default ComponentName;
Client Component Template
'use client';
import { FC, useState, useEffect } from 'react';
import styles from './ComponentName.module.css';
interface ComponentNameProps {
/**
* Component description
*/
children?: React.ReactNode;
/**
* Click event handler
*/
onClick?: () => void;
/**
* Additional CSS classes
*/
className?: string;
}
/**
* ComponentName - Client Component
*
* @description Interactive component with client-side functionality
* @example
* <ComponentName onClick={() => console.log('clicked')}>
* Content
* </ComponentName>
*/
export const ComponentName: FC<ComponentNameProps> = ({
children,
onClick,
className = '',
...props
}) => {
const [isActive, setIsActive] = useState(false);
const handleClick = () => {
setIsActive(!isActive);
onClick?.();
};
return (
<button
className={`${styles.button} ${isActive ? styles.active : ''} ${className}`}
onClick={handleClick}
{...props}
>
{children}
</button>
);
};
export default ComponentName;
Page Component Template
import { Metadata } from 'next';
import ComponentName from '@/components/ComponentName';
export const metadata: Metadata = {
title: 'Page Title',
description: 'Page description',
};
interface PageProps {
params: { id: string };
searchParams: { [key: string]: string | string[] | undefined };
}
export default function Page({ params, searchParams }: PageProps) {
return (
<main>
<h1>Page Title</h1>
<ComponentName />
</main>
);
}
Layout Component Template
import { FC } from 'react';
import styles from './Layout.module.css';
interface LayoutProps {
children: React.ReactNode;
/**
* Page title
*/
title?: string;
}
/**
* Layout - Shared layout component
*
* @description Provides consistent layout structure across pages
*/
export const Layout: FC<LayoutProps> = ({
children,
title,
}) => {
return (
<div className={styles.layout}>
<header className={styles.header}>
{title && <h1 className={styles.title}>{title}</h1>}
</header>
<main className={styles.main}>
{children}
</main>
<footer className={styles.footer}>
<p>© 2024 Your App</p>
</footer>
</div>
);
};
export default Layout;
4. CSS Module Templates
Basic Component Styles
/* ComponentName.module.css */
.container {
display: flex;
flex-direction: column;
padding: 1rem;
border-radius: 8px;
border: 1px solid #e2e8f0;
background-color: #ffffff;
}
.button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem 1rem;
border-radius: 6px;
border: 1px solid transparent;
background-color: #3b82f6;
color: white;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.button:hover {
background-color: #2563eb;
}
.button:focus {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}
.button.active {
background-color: #1d4ed8;
}
/* Responsive design */
@media (max-width: 768px) {
.container {
padding: 0.75rem;
}
.button {
padding: 0.75rem 1rem;
}
}
Layout Styles
/* Layout.module.css */
.layout {
min-height: 100vh;
display: grid;
grid-template-rows: auto 1fr auto;
}
.header {
padding: 1rem 2rem;
background-color: #f8fafc;
border-bottom: 1px solid #e2e8f0;
}
.title {
margin: 0;
font-size: 1.5rem;
font-weight: 600;
color: #1e293b;
}
.main {
padding: 2rem;
max-width: 1200px;
margin: 0 auto;
width: 100%;
}
.footer {
padding: 1rem 2rem;
background-color: #f1f5f9;
border-top: 1px solid #e2e8f0;
text-align: center;
color: #64748b;
}
5. TypeScript Types
// types.ts
export interface BaseComponentProps {
children?: React.ReactNode;
className?: string;
'data-testid'?: string;
}
export interface ButtonProps extends BaseComponentProps {
variant?: 'primary' | 'secondary' | 'outline';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
loading?: boolean;
onClick?: () => void;
}
export interface LayoutProps extends BaseComponentProps {
title?: string;
sidebar?: React.ReactNode;
breadcrumbs?: BreadcrumbItem[];
}
export interface BreadcrumbItem {
label: string;
href?: string;
current?: boolean;
}
6. Unit Tests
// ComponentName.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import ComponentName from './ComponentName';
describe('ComponentName', () => {
it('renders children correctly', () => {
render(<ComponentName>Test Content</ComponentName>);
expect(screen.getByText('Test Content')).toBeInTheDocument();
});
it('applies custom className', () => {
render(<ComponentName className="custom-class">Test</ComponentName>);
const element = screen.getByText('Test');
expect(element).toHaveClass('custom-class');
});
it('handles click events', () => {
const handleClick = jest.fn();
render(<ComponentName onClick={handleClick}>Click me</ComponentName>);
const button = screen.getByText('Click me');
fireEvent.click(button);
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('toggles active state on click', () => {
render(<ComponentName>Toggle</ComponentName>);
const button = screen.getByText('Toggle');
expect(button).not.toHaveClass('active');
fireEvent.click(button);
expect(button).toHaveClass('active');
fireEvent.click(button);
expect(button).not.toHaveClass('active');
});
it('is accessible', () => {
render(<ComponentName>Accessible Button</ComponentName>);
const button = screen.getByRole('button');
expect(button).toBeInTheDocument();
expect(button).toHaveAccessibleName('Accessible Button');
});
});
7. Storybook Stories (if detected)
// ComponentName.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import ComponentName from './ComponentName';
const meta: Meta<typeof ComponentName> = {
title: 'Components/ComponentName',
component: ComponentName,
parameters: {
layout: 'centered',
docs: {
description: {
component: 'A reusable component built for Next.js applications.',
},
},
},
tags: ['autodocs'],
argTypes: {
onClick: { action: 'clicked' },
className: { control: 'text' },
},
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {
children: 'Default Component',
},
};
export const WithCustomClass: Story = {
args: {
children: 'Custom Styled',
className: 'custom-style',
},
};
export const Interactive: Story = {
args: {
children: 'Click me',
onClick: () => alert('Component clicked!'),
},
};
8. Barrel Export
// index.ts
export { default } from './ComponentName';
export type { ComponentNameProps } from './ComponentName';
Framework-Specific Optimizations
Tailwind CSS Integration (if detected)
Replace CSS modules with Tailwind classes:
export const ComponentName: FC<ComponentNameProps> = ({
children,
className = '',
}) => {
return (
<div className={`flex flex-col p-4 rounded-lg border border-slate-200 bg-white ${className}`}>
{children}
</div>
);
};
Next.js App Router Optimizations
- Server Components: Default for non-interactive components
- Client Components: Explicit 'use client' directive
- Metadata: Include metadata for page components
- Loading States: Implement loading.tsx for async components
Accessibility Features
- ARIA Labels: Proper labeling for screen readers
- Keyboard Navigation: Tab order and keyboard shortcuts
- Focus Management: Visible focus indicators
- Semantic HTML: Proper semantic elements
Component Generation Process
- Analysis: Analyze existing project structure and patterns
- Template Selection: Choose appropriate template based on component type
- Customization: Adapt template to project conventions
- File Creation: Generate all component files
- Integration: Update index files and exports
- Validation: Verify component compiles and tests pass
Quality Checklist
- Component follows project naming conventions
- TypeScript types are properly defined
- CSS follows established patterns (modules or Tailwind)
- Unit tests cover key functionality
- Component is accessible (ARIA, keyboard navigation)
- Documentation includes usage examples
- Storybook story created (if Storybook detected)
- Component compiles without errors
- Tests pass successfully
Provide the complete component implementation with all specified files and features.
Next.js API Route Tester
API Route: $ARGUMENTS
Current Project Analysis
API Routes Detection
- App Router API: @app/api/
- Pages Router API: @pages/api/
- API configuration: @next.config.js
- Environment variables: @.env.local
Project Context
- Next.js version: !
grep '"next"' package.json | head -1 - TypeScript config: @tsconfig.json (if exists)
- Testing framework: @jest.config.js or @vitest.config.js (if exists)
API Route Analysis
Route Discovery
Based on the provided route path, analyze:
- Route File: Locate the actual route file
- HTTP Methods: Supported methods (GET, POST, PUT, DELETE, PATCH)
- Route Parameters: Dynamic segments and query parameters
- Middleware: Applied middleware functions
- Authentication: Required authentication/authorization
Route Implementation Review
- Route handler implementation: @app/api/[route-path]/route.ts or @pages/api/[route-path].ts
- Type definitions: @types/ or inline types
- Validation schemas: @lib/validations/ or inline validation
- Database models: @lib/models/ or @models/
Test Generation Strategy
1. Basic Functionality Tests
// Basic API route test template
describe('API Route: /api/[route-path]', () => {
describe('GET requests', () => {
test('should return 200 for valid request', async () => {
const response = await fetch('/api/[route-path]');
expect(response.status).toBe(200);
});
test('should return valid JSON response', async () => {
const response = await fetch('/api/[route-path]');
const data = await response.json();
expect(data).toBeDefined();
expect(typeof data).toBe('object');
});
});
describe('POST requests', () => {
test('should create resource with valid data', async () => {
const testData = { name: 'Test', email: 'test@example.com' };
const response = await fetch('/api/[route-path]', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(testData)
});
expect(response.status).toBe(201);
const result = await response.json();
expect(result.name).toBe(testData.name);
});
test('should reject invalid data', async () => {
const invalidData = { invalid: 'field' };
const response = await fetch('/api/[route-path]', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(invalidData)
});
expect(response.status).toBe(400);
});
});
});
2. Authentication Tests
describe('Authentication', () => {
test('should require authentication for protected routes', async () => {
const response = await fetch('/api/protected-route');
expect(response.status).toBe(401);
});
test('should allow authenticated requests', async () => {
const token = 'valid-jwt-token';
const response = await fetch('/api/protected-route', {
headers: { 'Authorization': `Bearer ${token}` }
});
expect(response.status).not.toBe(401);
});
test('should validate JWT token format', async () => {
const invalidToken = 'invalid-token';
const response = await fetch('/api/protected-route', {
headers: { 'Authorization': `Bearer ${invalidToken}` }
});
expect(response.status).toBe(403);
});
});
3. Input Validation Tests
describe('Input Validation', () => {
const validationTests = [
{ field: 'email', invalid: 'not-an-email', valid: 'test@example.com' },
{ field: 'phone', invalid: '123', valid: '+1234567890' },
{ field: 'age', invalid: -1, valid: 25 },
{ field: 'name', invalid: '', valid: 'John Doe' }
];
validationTests.forEach(({ field, invalid, valid }) => {
test(`should validate ${field} field`, async () => {
const invalidData = { [field]: invalid };
const validData = { [field]: valid };
// Test invalid data
const invalidResponse = await fetch('/api/[route-path]', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(invalidData)
});
expect(invalidResponse.status).toBe(400);
// Test valid data
const validResponse = await fetch('/api/[route-path]', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(validData)
});
expect(validResponse.status).not.toBe(400);
});
});
});
4. Error Handling Tests
describe('Error Handling', () => {
test('should handle malformed JSON', async () => {
const response = await fetch('/api/[route-path]', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: 'invalid-json'
});
expect(response.status).toBe(400);
});
test('should handle missing Content-Type header', async () => {
const response = await fetch('/api/[route-path]', {
method: 'POST',
body: JSON.stringify({ test: 'data' })
});
expect(response.status).toBe(400);
});
test('should handle request timeout', async () => {
// Mock slow endpoint
jest.setTimeout(5000);
const response = await fetch('/api/slow-endpoint');
// Test appropriate timeout handling
}, 5000);
test('should handle database connection errors', async () => {
// Mock database failure
const mockDbError = jest.spyOn(db, 'connect').mockRejectedValue(new Error('DB Error'));
const response = await fetch('/api/[route-path]');
expect(response.status).toBe(500);
mockDbError.mockRestore();
});
});
5. Performance Tests
describe('Performance', () => {
test('should respond within acceptable time', async () => {
const startTime = Date.now();
const response = await fetch('/api/[route-path]');
const endTime = Date.now();
expect(response.status).toBe(200);
expect(endTime - startTime).toBeLessThan(1000); // 1 second
});
test('should handle concurrent requests', async () => {
const promises = Array.from({ length: 10 }, () =>
fetch('/api/[route-path]')
);
const responses = await Promise.all(promises);
responses.forEach(response => {
expect(response.status).toBe(200);
});
});
test('should implement rate limiting', async () => {
const requests = Array.from({ length: 100 }, () =>
fetch('/api/[route-path]')
);
const responses = await Promise.all(requests);
const rateLimitedResponses = responses.filter(r => r.status === 429);
expect(rateLimitedResponses.length).toBeGreaterThan(0);
});
});
Manual Testing Commands
cURL Commands Generation
# GET request
curl -X GET "http://localhost:3000/api/[route-path]" \
-H "Accept: application/json"
# POST request with data
curl -X POST "http://localhost:3000/api/[route-path]" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"key": "value"}'
# Authenticated request
curl -X GET "http://localhost:3000/api/protected-route" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Accept: application/json"
# Upload file
curl -X POST "http://localhost:3000/api/upload" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-F "file=@path/to/file.jpg"
HTTPie Commands
# GET request
http GET localhost:3000/api/[route-path]
# POST request with JSON
http POST localhost:3000/api/[route-path] key=value
# Authenticated request
http GET localhost:3000/api/protected-route Authorization:"Bearer TOKEN"
# Custom headers
http GET localhost:3000/api/[route-path] X-Custom-Header:value
Interactive Testing Tools
Postman Collection Generation
{
"info": {
"name": "Next.js API Tests",
"description": "Generated API tests for [route-path]"
},
"item": [
{
"name": "GET [route-path]",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/[route-path]",
"host": ["{{baseUrl}}"],
"path": ["api", "[route-path]"]
}
}
},
{
"name": "POST [route-path]",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"key\": \"value\"\n}"
},
"url": {
"raw": "{{baseUrl}}/api/[route-path]",
"host": ["{{baseUrl}}"],
"path": ["api", "[route-path]"]
}
}
}
]
}
Thunder Client Collection
{
"client": "Thunder Client",
"collectionName": "Next.js API Tests",
"dateExported": "2024-01-01",
"version": "1.1",
"folders": [],
"requests": [
{
"name": "Test API Route",
"url": "localhost:3000/api/[route-path]",
"method": "GET",
"headers": [
{
"name": "Accept",
"value": "application/json"
}
]
}
]
}
Test Data Management
Test Fixtures
// test/fixtures/apiTestData.ts
export const validUserData = {
name: 'John Doe',
email: 'john@example.com',
age: 30,
role: 'user'
};
export const invalidUserData = {
name: '',
email: 'invalid-email',
age: -1,
role: 'invalid-role'
};
export const testHeaders = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'API-Test-Suite/1.0'
};
Mock Data Generation
// test/utils/mockData.ts
export function generateMockUser() {
return {
id: Math.random().toString(36).substr(2, 9),
name: `User ${Math.floor(Math.random() * 1000)}`,
email: `user${Date.now()}@example.com`,
createdAt: new Date().toISOString()
};
}
export function generateBulkTestData(count: number) {
return Array.from({ length: count }, generateMockUser);
}
Test Environment Setup
Jest Configuration
// jest.config.js for API testing
module.exports = {
testEnvironment: 'node',
setupFilesAfterEnv: ['<rootDir>/test/setup.js'],
testMatch: ['**/__tests__/**/*.test.js', '**/?(*.)+(spec|test).js'],
collectCoverageFrom: [
'pages/api/**/*.{js,ts}',
'app/api/**/*.{js,ts}',
'!**/*.d.ts',
],
coverageThreshold: {
global: {
branches: 70,
functions: 70,
lines: 70,
statements: 70
}
}
};
Test Setup
// test/setup.js
import { createMocks } from 'node-mocks-http';
import { testDb } from './testDatabase';
// Global test setup
beforeAll(async () => {
// Setup test database
await testDb.connect();
});
afterAll(async () => {
// Cleanup test database
await testDb.disconnect();
});
beforeEach(async () => {
// Reset database state
await testDb.reset();
});
// Helper function for API testing
global.createAPITest = (handler) => {
return (method, url, options = {}) => {
const { req, res } = createMocks({
method,
url,
...options
});
return handler(req, res);
};
};
Automated Testing Integration
GitHub Actions Workflow
name: API Tests
on: [push, pull_request]
jobs:
test-api:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm run test:api
- name: Upload coverage
uses: codecov/codecov-action@v3
Continuous Testing
# Watch mode for development
npm run test:api -- --watch
# Coverage reporting
npm run test:api -- --coverage
# Specific route testing
npm run test:api -- --testNamePattern="api/users"
Test Results Analysis
Generate comprehensive test report including:
- Test Coverage: Line, branch, function coverage percentages
- Performance Metrics: Response times, throughput
- Security Analysis: Authentication, authorization, input validation
- Error Handling: Exception scenarios and error responses
- Compatibility: Cross-environment testing results
Provide actionable recommendations for improving API reliability, performance, and security.
Next.js Performance Audit
Audit Type: $ARGUMENTS
Current Application Analysis
Application State
- Build status: !
ls -la .next/ 2>/dev/null || echo "No build found - run 'npm run build' first" - Application running: !
curl -s http://localhost:3000 > /dev/null && echo "App is running" || echo "App not running - start with 'npm run dev'" - Bundle analysis: !
ls -la .next/analyze/ 2>/dev/null || echo "No bundle analysis found"
Project Configuration
- Next.js config: @next.config.js
- Package.json: @package.json
- TypeScript config: @tsconfig.json (if exists)
- Vercel config: @vercel.json (if exists)
Performance Monitoring Setup
- Web Vitals: Check for @next/web-vitals or similar
- Analytics: Check for Vercel Analytics or Google Analytics
- Monitoring tools: Check for Sentry, DataDog, or other APM tools
Performance Audit Framework
1. Lighthouse Audit
# Install Lighthouse CLI if not available
npm install -g lighthouse
# Run Lighthouse audit
lighthouse http://localhost:3000 \
--output=json \
--output=html \
--output-path=./performance-audit \
--chrome-flags="--headless" \
--preset=perf
# Mobile performance audit
lighthouse http://localhost:3000 \
--output=json \
--output-path=./performance-audit-mobile \
--preset=perf \
--form-factor=mobile \
--throttling-method=devtools \
--chrome-flags="--headless"
# Generate detailed report
lighthouse http://localhost:3000 \
--output=html \
--output-path=./lighthouse-report.html \
--view
2. Bundle Analysis
// next.config.js - Enable bundle analysis
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({
// ... your config
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// Bundle analysis optimizations
if (!dev && !isServer) {
config.optimization.splitChunks = {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
};
}
return config;
},
});
3. Runtime Performance Analysis
# Build and analyze bundle
ANALYZE=true npm run build
# Check bundle sizes
ls -lah .next/static/chunks/ | grep -E "\\.js$" | sort -k5 -hr | head -10
# Analyze dependencies
npm ls --depth=0 --prod | grep -v "deduped"
# Check for duplicate dependencies
npm ls --depth=0 | grep -E "UNMET|invalid"
Performance Metrics Collection
1. Core Web Vitals Implementation
// lib/analytics.ts
export function reportWebVitals({ id, name, label, value }: any) {
// Send to analytics service
if (typeof window !== 'undefined') {
// Client-side reporting
fetch('/api/analytics/web-vitals', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id,
name,
label,
value,
url: window.location.href,
timestamp: Date.now(),
}),
}).catch(console.error);
}
}
// Track specific metrics
export function trackMetric(name: string, value: number, labels?: Record<string, string>) {
reportWebVitals({
id: `${name}-${Date.now()}`,
name,
label: 'custom',
value,
...labels,
});
}
// Performance observer for custom metrics
export function initPerformanceObserver() {
if (typeof window === 'undefined') return;
// Largest Contentful Paint
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
trackMetric('LCP', entry.startTime);
}
}).observe({ entryTypes: ['largest-contentful-paint'] });
// First Input Delay
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
trackMetric('FID', entry.processingStart - entry.startTime);
}
}).observe({ entryTypes: ['first-input'] });
// Cumulative Layout Shift
new PerformanceObserver((entryList) => {
let clsValue = 0;
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
}
trackMetric('CLS', clsValue);
}).observe({ entryTypes: ['layout-shift'] });
}
2. Server-Side Performance Monitoring
// middleware.ts - Performance monitoring
import { NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
const start = Date.now();
const response = NextResponse.next();
// Add performance headers
response.headers.set('X-Response-Time', `${Date.now() - start}ms`);
response.headers.set('X-Timestamp', new Date().toISOString());
return response;
}
Performance Analysis Areas
1. Loading Performance
// Analyze loading performance
const loadingPerformanceAudit = {
// First Contentful Paint (FCP)
fcp: {
target: '< 1.8s',
current: '?', // From Lighthouse
optimizations: [
'Optimize critical rendering path',
'Inline critical CSS',
'Preload key resources',
'Minimize render-blocking resources',
],
},
// Largest Contentful Paint (LCP)
lcp: {
target: '< 2.5s',
current: '?', // From Lighthouse
optimizations: [
'Optimize images (Next.js Image component)',
'Preload LCP element',
'Optimize server response time',
'Use CDN for static assets',
],
},
// Time to Interactive (TTI)
tti: {
target: '< 3.8s',
current: '?', // From Lighthouse
optimizations: [
'Reduce JavaScript bundle size',
'Code splitting',
'Remove unused code',
'Optimize third-party scripts',
],
},
// Speed Index
speedIndex: {
target: '< 3.4s',
current: '?', // From Lighthouse
optimizations: [
'Optimize above-the-fold content',
'Progressive image loading',
'Critical resource prioritization',
],
},
};
2. Runtime Performance
// Runtime performance analysis
const runtimePerformanceAudit = {
// First Input Delay (FID)
fid: {
target: '< 100ms',
current: '?',
optimizations: [
'Reduce JavaScript execution time',
'Break up long tasks',
'Use web workers for heavy computation',
'Optimize event handlers',
],
},
// Cumulative Layout Shift (CLS)
cls: {
target: '< 0.1',
current: '?',
optimizations: [
'Set dimensions for media elements',
'Reserve space for ads/embeds',
'Avoid dynamic content insertion',
'Use CSS transforms for animations',
],
},
// Total Blocking Time (TBT)
tbt: {
target: '< 200ms',
current: '?',
optimizations: [
'Code splitting',
'Remove unused polyfills',
'Optimize third-party code',
'Use setTimeout for heavy operations',
],
},
};
3. Bundle Performance
// Bundle analysis report
const bundleAnalysis = {
totalSize: '?', // From webpack-bundle-analyzer
firstLoadJS: '?', // Critical for performance
chunks: {
main: '?',
framework: '?',
vendor: '?',
pages: '?',
},
recommendations: [
// Dynamic imports for code splitting
{
type: 'Dynamic Import',
description: 'Use dynamic imports for non-critical components',
example: `
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <Loading />,
ssr: false
});
`,
},
// Tree shaking optimization
{
type: 'Tree Shaking',
description: 'Import only needed functions from libraries',
example: `
// ❌ Imports entire library
import * as _ from 'lodash';
// ✅ Import only needed functions
import { debounce, throttle } from 'lodash';
`,
},
// Bundle splitting
{
type: 'Bundle Splitting',
description: 'Optimize webpack chunk splitting',
example: `
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.optimization.splitChunks.cacheGroups = {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
};
}
return config;
},
};
`,
},
],
};
Optimization Recommendations
1. Image Optimization
// Image optimization analysis
const imageOptimization = {
// Next.js Image component usage
nextImageUsage: 'Analyze usage of next/image vs <img>',
recommendations: [
{
priority: 'High',
description: 'Replace <img> tags with Next.js Image component',
implementation: `
import Image from 'next/image';
// ❌ Regular img tag
<img src="/hero.jpg" alt="Hero" />
// ✅ Next.js Image component
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority={true} // For above-the-fold images
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
/>
`,
},
{
priority: 'Medium',
description: 'Implement responsive images with sizes prop',
implementation: `
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
`,
},
{
priority: 'Low',
description: 'Configure custom image loader for CDN',
implementation: `
// next.config.js
module.exports = {
images: {
loader: 'cloudinary',
path: 'https://res.cloudinary.com/demo/image/fetch/',
},
};
`,
},
],
};
2. CSS Optimization
/* Critical CSS analysis */
.critical-css-audit {
/* Above-the-fold styles that should be inlined */
}
/* Non-critical CSS that can be loaded asynchronously */
.non-critical-css {
/* Styles for below-the-fold content */
}
// CSS optimization recommendations
const cssOptimization = {
recommendations: [
{
type: 'Critical CSS',
description: 'Inline critical CSS for faster initial render',
implementation: 'Use styled-jsx or CSS-in-JS for critical styles',
},
{
type: 'CSS Modules',
description: 'Use CSS Modules to avoid global namespace pollution',
implementation: 'Import styles as modules: import styles from "./Component.module.css"',
},
{
type: 'Tailwind Purging',
description: 'Ensure unused Tailwind classes are purged',
implementation: 'Configure purge in tailwind.config.js',
},
],
};
3. JavaScript Optimization
// JavaScript optimization analysis
const jsOptimization = {
recommendations: [
{
priority: 'High',
type: 'Code Splitting',
description: 'Implement route-based and component-based code splitting',
example: `
// Route-based splitting (automatic with Next.js pages)
// Component-based splitting
const LazyComponent = dynamic(() => import('./LazyComponent'));
// Conditional loading
const AdminPanel = dynamic(() => import('./AdminPanel'), {
ssr: false,
loading: () => <AdminSkeleton />,
});
`,
},
{
priority: 'Medium',
type: 'Tree Shaking',
description: 'Ensure unused code is eliminated',
example: `
// ❌ Imports entire library
import moment from 'moment';
// ✅ Use tree-shakable alternative
import { format } from 'date-fns';
// ✅ Or import specific functions
import debounce from 'lodash/debounce';
`,
},
{
priority: 'Medium',
type: 'Polyfill Optimization',
description: 'Reduce polyfill size by targeting modern browsers',
example: `
// next.config.js
module.exports = {
experimental: {
browsersListForSwc: true,
},
};
`,
},
],
};
Performance Monitoring Setup
1. Real User Monitoring (RUM)
// pages/_app.tsx
import { reportWebVitals } from '../lib/analytics';
export { reportWebVitals };
export default function MyApp({ Component, pageProps }) {
return (
<>
<Component {...pageProps} />
{process.env.NODE_ENV === 'production' && (
<script
dangerouslySetInnerHTML={{
__html: `
// Custom RUM implementation
window.addEventListener('load', () => {
// Track page load time
const loadTime = performance.timing.loadEventEnd - performance.timing.navigationStart;
fetch('/api/analytics/performance', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
metric: 'page_load_time',
value: loadTime,
url: window.location.href,
}),
});
});
`,
}}
/>
)}
</>
);
}
2. Performance Budget
// webpack.config.js - Performance budgets
module.exports = {
performance: {
maxAssetSize: 250000, // 250KB
maxEntrypointSize: 400000, // 400KB
hints: process.env.NODE_ENV === 'production' ? 'error' : 'warning',
},
};
3. Continuous Performance Monitoring
# .github/workflows/performance.yml
name: Performance Audit
on:
pull_request:
branches: [main]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Build Next.js
run: npm run build
- name: Start Next.js
run: npm start &
- name: Wait for server
run: npx wait-on http://localhost:3000
- name: Run Lighthouse CI
run: |
npm install -g @lhci/cli@0.12.x
lhci autorun
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
Performance Report Generation
1. Comprehensive Audit Report
Generate detailed performance report including:
Executive Summary
- Overall performance score (0-100)
- Core Web Vitals status
- Key performance issues
- Impact on user experience
Detailed Analysis
- Loading performance breakdown
- Runtime performance metrics
- Bundle analysis and recommendations
- Image optimization opportunities
- CSS and JavaScript optimization
Action Plan
- High priority fixes (immediate impact)
- Medium priority improvements (moderate impact)
- Long-term optimization strategy
- Performance monitoring setup
Implementation Roadmap
- Week 1: Critical performance fixes
- Week 2-3: Image and asset optimization
- Week 4: Bundle optimization and code splitting
- Ongoing: Performance monitoring and regression prevention
2. Performance Tracking Dashboard
// Create performance dashboard component
const PerformanceDashboard = () => {
return (
<div className="performance-dashboard">
<h2>Performance Metrics</h2>
{/* Core Web Vitals */}
<section>
<h3>Core Web Vitals</h3>
<div className="metrics-grid">
<MetricCard title="LCP" value="2.1s" target="< 2.5s" status="good" />
<MetricCard title="FID" value="89ms" target="< 100ms" status="good" />
<MetricCard title="CLS" value="0.08" target="< 0.1" status="good" />
</div>
</section>
{/* Bundle Analysis */}
<section>
<h3>Bundle Analysis</h3>
<BundleChart data={bundleData} />
</section>
{/* Performance Trends */}
<section>
<h3>Performance Trends</h3>
<TrendChart metrics={performanceHistory} />
</section>
</div>
);
};
Provide comprehensive performance audit with specific, measurable recommendations and implementation guidance for immediate and long-term optimization.
Vercel Deployment Optimization
Target Environment: $ARGUMENTS
Current Deployment State
- Project directory: !
pwd - Git status: !
git status --porcelain - Current branch: !
git branch --show-current - Vercel project status: !
vercel --version 2>/dev/null || echo "Vercel CLI not installed" - Build output: !
ls -la .next/ 2>/dev/null || echo "No build found"
Configuration Analysis
Project Configuration
- Next.js config: @next.config.js
- Vercel config: @vercel.json (if exists)
- Package.json: @package.json
- Environment variables: @.env.local (if exists)
- Environment example: @.env.example (if exists)
Vercel Configuration
Analyze and optimize vercel.json configuration:
{
"framework": "nextjs",
"buildCommand": "npm run build",
"devCommand": "npm run dev",
"installCommand": "npm install",
"regions": ["iad1", "sfo1", "lhr1"],
"functions": {
"app/api/**/*.ts": {
"runtime": "nodejs18.x",
"maxDuration": 30,
"memory": 1024
}
},
"crons": [],
"headers": [
{
"source": "/api/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "s-maxage=300, stale-while-revalidate=86400"
}
]
},
{
"source": "/(.*)",
"headers": [
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "Referrer-Policy",
"value": "strict-origin-when-cross-origin"
}
]
}
],
"redirects": [],
"rewrites": []
}
Pre-Deployment Optimization
1. Build Optimization
Run comprehensive build analysis:
- Bundle Analysis: Generate bundle analyzer report
- Performance Check: Analyze build output for optimization opportunities
- Type Checking: Ensure TypeScript compilation is error-free
- Lint Check: Run ESLint for code quality
# Build optimization commands
npm run build
npm run lint
npm run type-check # If TypeScript project
2. Performance Optimization
Image Optimization Check
// Verify Next.js image configuration
const nextConfig = {
images: {
formats: ['image/webp', 'image/avif'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
minimumCacheTTL: 31536000,
dangerouslyAllowSVG: false,
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
},
};
Bundle Analysis
Generate and analyze webpack bundle:
ANALYZE=true npm run build
# or
npm run build -- --analyze
3. Environment Configuration
Environment Variables Setup
Ensure proper environment variable configuration:
- Production: Verify all required environment variables are set in Vercel dashboard
- Preview: Configure preview environment variables
- Development: Local development environment setup
4. Security Headers Optimization
// Enhanced security headers in next.config.js
const securityHeaders = [
{
key: 'X-DNS-Prefetch-Control',
value: 'on'
},
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload'
},
{
key: 'X-XSS-Protection',
value: '1; mode=block'
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN'
},
{
key: 'Permissions-Policy',
value: 'camera=(), microphone=(), geolocation=()'
},
{
key: 'X-Content-Type-Options',
value: 'nosniff'
},
{
key: 'Referrer-Policy',
value: 'origin-when-cross-origin'
}
];
Deployment Process
1. Pre-deployment Checklist
- Build passes without errors
- All tests pass (if available)
- Environment variables configured
- Security headers implemented
- Performance metrics baseline established
- Database migrations complete (if applicable)
2. Deployment Commands
Production Deployment
# Deploy to production
vercel --prod
# Deploy with environment variables
vercel --prod --env-file .env.production
# Deploy specific directory
vercel --prod --cwd ./path/to/project
Preview Deployment
# Deploy preview from current branch
vercel
# Deploy with custom alias
vercel --alias preview-branch-name.vercel.app
Deployment with Analytics
# Deploy with build analytics
ANALYZE=true vercel --prod
# Deploy with performance monitoring
vercel --prod --meta performance=true
Post-Deployment Optimization
1. Performance Monitoring Setup
Core Web Vitals Tracking
// Add to _app.tsx or layout.tsx
import { Analytics } from '@vercel/analytics/react';
import { SpeedInsights } from '@vercel/speed-insights/next';
export default function App({ Component, pageProps }) {
return (
<>
<Component {...pageProps} />
<Analytics />
<SpeedInsights />
</>
);
}
Custom Performance Tracking
// lib/analytics.ts
export function reportWebVitals({ id, name, label, value }) {
fetch('/api/analytics', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
metric: name,
value: value,
label: label,
timestamp: Date.now()
})
});
}
2. Deployment Validation
Health Checks
- Application Health: Verify application loads correctly
- API Endpoints: Test critical API routes
- Database Connectivity: Verify database connections (if applicable)
- External Services: Test third-party integrations
Performance Validation
- Core Web Vitals: Check LCP, FID, CLS scores
- Lighthouse Score: Run Lighthouse audit
- Load Testing: Verify application performance under load
- Error Monitoring: Confirm error tracking is working
3. Rollback Strategy
# List recent deployments
vercel list
# Rollback to specific deployment
vercel rollback <deployment-url>
# Alias management for instant rollback
vercel alias set <previous-deployment-url> <production-domain>
Environment-Specific Optimizations
Production Environment
- Caching Strategy: Implement aggressive caching with ISR
- CDN Configuration: Optimize asset delivery
- Database Optimization: Connection pooling and query optimization
- Monitoring: Comprehensive error tracking and performance monitoring
Preview Environment
- Feature Testing: Safe environment for feature validation
- Stakeholder Review: Shareable preview URLs
- Integration Testing: End-to-end testing environment
- Performance Benchmarking: Compare against production metrics
Development Environment
- Hot Reloading: Fast development feedback loop
- Debug Tools: Enhanced debugging capabilities
- Test Data: Isolated test database and services
- Development Analytics: Local performance profiling
Monitoring and Maintenance
1. Deployment Metrics
Track key deployment metrics:
- Build Time: Monitor build performance
- Deploy Time: Track deployment duration
- Success Rate: Monitor deployment success/failure rates
- Rollback Frequency: Track rollback events
2. Performance Monitoring
- Real User Monitoring: Track actual user performance
- Synthetic Monitoring: Automated performance testing
- Error Tracking: Monitor and alert on errors
- Uptime Monitoring: Track application availability
3. Cost Optimization
- Function Duration: Optimize serverless function execution time
- Bandwidth Usage: Monitor and optimize data transfer
- Build Minutes: Optimize build processes
- Edge Requests: Monitor edge function usage
Troubleshooting Common Issues
Build Failures
- Check build logs in Vercel dashboard
- Verify all dependencies are in package.json
- Ensure environment variables are properly set
- Check for TypeScript errors (if applicable)
Performance Issues
- Analyze bundle size and optimize imports
- Implement proper code splitting
- Optimize images and static assets
- Use Next.js performance optimization features
Deployment Issues
- Verify Git repository connection
- Check branch protection rules
- Ensure proper access permissions
- Validate deployment configuration
Success Criteria
Deployment is successful when:
- Application builds without errors
- All tests pass (if available)
- Core Web Vitals scores are optimal (LCP < 2.5s, FID < 100ms, CLS < 0.1)
- Security headers are properly configured
- Performance monitoring is active
- Error tracking is operational
- Rollback procedures are tested and documented
Provide post-deployment recommendations and next steps for ongoing optimization and monitoring.
Vercel Edge Function Generator
Function Name: $ARGUMENTS
Current Project Analysis
Project Structure
- Vercel config: @vercel.json (if exists)
- Next.js config: @next.config.js
- API routes: @app/api/ or @pages/api/
- Middleware: @middleware.ts (if exists)
Framework Detection
- Package.json: @package.json
- TypeScript config: @tsconfig.json (if exists)
- Environment variables: @.env.local (if exists)
Edge Function Implementation Strategy
1. File Structure Creation
Generate comprehensive edge function structure:
api/edge/[function-name]/
├── index.ts # Main edge function
├── types.ts # TypeScript types
├── utils.ts # Utility functions
├── config.ts # Configuration
└── __tests__/
└── [function-name].test.ts # Unit tests
2. Base Edge Function Template
// api/edge/[function-name]/index.ts
import { NextRequest, NextResponse } from 'next/server';
export const runtime = 'edge';
export async function GET(request: NextRequest) {
try {
// Get geolocation data
const country = request.geo?.country || 'Unknown';
const city = request.geo?.city || 'Unknown';
const region = request.geo?.region || 'Unknown';
// Get request metadata
const ip = request.headers.get('x-forwarded-for') || 'Unknown';
const userAgent = request.headers.get('user-agent') || 'Unknown';
const referer = request.headers.get('referer') || 'Unknown';
// Process request
const result = await processRequest({
geo: { country, city, region },
ip,
userAgent,
referer,
url: request.url,
});
return NextResponse.json(result, {
status: 200,
headers: {
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
'Content-Type': 'application/json',
'X-Edge-Location': region,
},
});
} catch (error) {
console.error('Edge function error:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
// Validate request body
const validationResult = validateRequestBody(body);
if (!validationResult.valid) {
return NextResponse.json(
{ error: 'Invalid request body', details: validationResult.errors },
{ status: 400 }
);
}
// Process POST request
const result = await processPostRequest(body, request);
return NextResponse.json(result, {
status: 201,
headers: {
'Content-Type': 'application/json',
},
});
} catch (error) {
console.error('Edge function POST error:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
async function processRequest(metadata: RequestMetadata): Promise<any> {
// Implement your edge function logic here
return {
message: 'Edge function executed successfully',
metadata,
timestamp: new Date().toISOString(),
};
}
async function processPostRequest(body: any, request: NextRequest): Promise<any> {
// Implement POST logic here
return {
message: 'POST processed successfully',
data: body,
timestamp: new Date().toISOString(),
};
}
function validateRequestBody(body: any): ValidationResult {
// Implement validation logic
return { valid: true, errors: [] };
}
interface RequestMetadata {
geo: {
country: string;
city: string;
region: string;
};
ip: string;
userAgent: string;
referer: string;
url: string;
}
interface ValidationResult {
valid: boolean;
errors: string[];
}
Specialized Edge Function Types
1. Geolocation-Based Content Delivery
// api/edge/geo-content/index.ts
import { NextRequest, NextResponse } from 'next/server';
export const runtime = 'edge';
interface ContentConfig {
[country: string]: {
currency: string;
language: string;
content: string;
pricing: number;
};
}
const contentConfig: ContentConfig = {
'US': {
currency: 'USD',
language: 'en-US',
content: 'Welcome to our US store!',
pricing: 99.99,
},
'GB': {
currency: 'GBP',
language: 'en-GB',
content: 'Welcome to our UK store!',
pricing: 79.99,
},
'DE': {
currency: 'EUR',
language: 'de-DE',
content: 'Willkommen in unserem deutschen Shop!',
pricing: 89.99,
},
};
export async function GET(request: NextRequest) {
const country = request.geo?.country || 'US';
const config = contentConfig[country] || contentConfig['US'];
// Add region-specific headers
const response = NextResponse.json({
country,
...config,
edgeLocation: request.geo?.region,
timestamp: new Date().toISOString(),
});
response.headers.set('Cache-Control', 'public, s-maxage=3600, stale-while-revalidate=86400');
response.headers.set('Vary', 'Accept-Language, CloudFront-Viewer-Country');
response.headers.set('Content-Language', config.language);
return response;
}
2. Authentication Edge Function
// api/edge/auth-check/index.ts
import { NextRequest, NextResponse } from 'next/server';
import { jwtVerify } from 'jose';
export const runtime = 'edge';
const JWT_SECRET = new TextEncoder().encode(
process.env.JWT_SECRET || 'your-secret-key'
);
export async function GET(request: NextRequest) {
try {
// Extract token from header or cookie
const authHeader = request.headers.get('authorization');
const cookieToken = request.cookies.get('auth-token')?.value;
const token = authHeader?.replace('Bearer ', '') || cookieToken;
if (!token) {
return NextResponse.json(
{ error: 'No token provided', authenticated: false },
{ status: 401 }
);
}
// Verify JWT token
const { payload } = await jwtVerify(token, JWT_SECRET);
// Return user info
return NextResponse.json({
authenticated: true,
user: {
id: payload.sub,
email: payload.email,
role: payload.role,
exp: payload.exp,
},
location: {
country: request.geo?.country,
city: request.geo?.city,
},
});
} catch (error) {
console.error('Auth verification failed:', error);
return NextResponse.json(
{ error: 'Invalid token', authenticated: false },
{ status: 401 }
);
}
}
export async function POST(request: NextRequest) {
try {
const { username, password } = await request.json();
// Validate credentials (implement your logic)
const user = await validateCredentials(username, password);
if (!user) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
);
}
// Generate JWT token
const token = await generateJWT(user);
const response = NextResponse.json({
success: true,
user: {
id: user.id,
email: user.email,
role: user.role,
},
});
// Set secure cookie
response.cookies.set('auth-token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 24 * 60 * 60, // 24 hours
});
return response;
} catch (error) {
console.error('Authentication error:', error);
return NextResponse.json(
{ error: 'Authentication failed' },
{ status: 500 }
);
}
}
async function validateCredentials(username: string, password: string) {
// Implement credential validation
// This would typically involve database lookup
return null; // Placeholder
}
async function generateJWT(user: any): Promise<string> {
// Implement JWT generation
// This would use a proper JWT library
return 'jwt-token'; // Placeholder
}
3. Data Transformation Edge Function
// api/edge/transform/index.ts
import { NextRequest, NextResponse } from 'next/server';
export const runtime = 'edge';
interface TransformConfig {
format: 'json' | 'xml' | 'csv';
fields?: string[];
transforms?: Record<string, (value: any) => any>;
}
const transformers = {
// Currency conversion
currency: (value: number, targetCurrency: string = 'USD') => {
const rates = { USD: 1, EUR: 0.85, GBP: 0.73 };
return value * (rates[targetCurrency as keyof typeof rates] || 1);
},
// Date formatting
date: (value: string, format: string = 'ISO') => {
const date = new Date(value);
if (format === 'ISO') return date.toISOString();
if (format === 'US') return date.toLocaleDateString('en-US');
return date.toString();
},
// Text formatting
text: (value: string, caseType: string = 'lower') => {
if (caseType === 'upper') return value.toUpperCase();
if (caseType === 'title') return value.replace(/\w\S*/g, txt =>
txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
);
return value.toLowerCase();
},
};
export async function POST(request: NextRequest) {
try {
const { data, config }: { data: any; config: TransformConfig } = await request.json();
if (!data || !config) {
return NextResponse.json(
{ error: 'Missing data or config' },
{ status: 400 }
);
}
// Apply transformations
const transformedData = await transformData(data, config, request);
// Format output based on requested format
const output = await formatOutput(transformedData, config.format);
const response = new NextResponse(output, {
status: 200,
headers: {
'Content-Type': getContentType(config.format),
'Cache-Control': 'public, s-maxage=300',
},
});
return response;
} catch (error) {
console.error('Transform error:', error);
return NextResponse.json(
{ error: 'Transformation failed' },
{ status: 500 }
);
}
}
async function transformData(data: any, config: TransformConfig, request: NextRequest) {
const country = request.geo?.country || 'US';
// Apply field filtering if specified
if (config.fields && Array.isArray(data)) {
data = data.map(item => {
const filtered: any = {};
config.fields!.forEach(field => {
if (item.hasOwnProperty(field)) {
filtered[field] = item[field];
}
});
return filtered;
});
}
// Apply custom transforms
if (config.transforms) {
Object.entries(config.transforms).forEach(([field, transformFunc]) => {
if (Array.isArray(data)) {
data = data.map(item => ({
...item,
[field]: transformFunc(item[field]),
}));
} else if (data.hasOwnProperty(field)) {
data[field] = transformFunc(data[field]);
}
});
}
// Add geo context
return {
...data,
_meta: {
transformedAt: new Date().toISOString(),
location: country,
edgeRegion: request.geo?.region,
},
};
}
async function formatOutput(data: any, format: string): Promise<string> {
switch (format) {
case 'xml':
return jsonToXml(data);
case 'csv':
return jsonToCsv(data);
case 'json':
default:
return JSON.stringify(data, null, 2);
}
}
function getContentType(format: string): string {
switch (format) {
case 'xml': return 'application/xml';
case 'csv': return 'text/csv';
case 'json':
default: return 'application/json';
}
}
function jsonToXml(data: any): string {
// Simple XML conversion (implement proper XML library for production)
return `<?xml version="1.0" encoding="UTF-8"?><root>${JSON.stringify(data)}</root>`;
}
function jsonToCsv(data: any): string {
// Simple CSV conversion (implement proper CSV library for production)
if (Array.isArray(data) && data.length > 0) {
const headers = Object.keys(data[0]);
const rows = data.map(row => headers.map(header => row[header] || '').join(','));
return [headers.join(','), ...rows].join('\n');
}
return '';
}
4. Proxy and Cache Edge Function
// api/edge/proxy/index.ts
import { NextRequest, NextResponse } from 'next/server';
export const runtime = 'edge';
interface ProxyConfig {
targetUrl: string;
cacheTime: number;
headers?: Record<string, string>;
transformResponse?: boolean;
}
const proxyConfigs: Record<string, ProxyConfig> = {
'api': {
targetUrl: 'https://jsonplaceholder.typicode.com',
cacheTime: 300, // 5 minutes
headers: {
'User-Agent': 'Vercel-Edge-Proxy/1.0',
},
},
'cdn': {
targetUrl: 'https://cdn.example.com',
cacheTime: 3600, // 1 hour
transformResponse: false,
},
};
export async function GET(request: NextRequest) {
try {
const url = new URL(request.url);
const proxyType = url.searchParams.get('type') || 'api';
const targetPath = url.searchParams.get('path') || '';
const config = proxyConfigs[proxyType];
if (!config) {
return NextResponse.json(
{ error: 'Invalid proxy type' },
{ status: 400 }
);
}
// Build target URL
const targetUrl = `${config.targetUrl}${targetPath}`;
// Check cache first (simplified - use proper cache in production)
const cacheKey = `proxy:${targetUrl}`;
// Make request to target
const response = await fetch(targetUrl, {
headers: {
...config.headers,
'X-Forwarded-For': request.headers.get('x-forwarded-for') || '',
'X-Real-IP': request.headers.get('x-real-ip') || '',
},
});
if (!response.ok) {
return NextResponse.json(
{ error: 'Upstream server error' },
{ status: response.status }
);
}
let data;
const contentType = response.headers.get('content-type') || '';
if (contentType.includes('application/json')) {
data = await response.json();
// Transform response if configured
if (config.transformResponse) {
data = await transformProxyResponse(data, request);
}
return NextResponse.json(data, {
status: 200,
headers: {
'Cache-Control': `public, s-maxage=${config.cacheTime}, stale-while-revalidate=${config.cacheTime * 2}`,
'X-Proxy-Cache': 'MISS',
'X-Edge-Location': request.geo?.region || 'unknown',
},
});
} else {
// For non-JSON responses, pass through
const blob = await response.blob();
return new NextResponse(blob, {
status: 200,
headers: {
'Content-Type': contentType,
'Cache-Control': `public, s-maxage=${config.cacheTime}`,
},
});
}
} catch (error) {
console.error('Proxy error:', error);
return NextResponse.json(
{ error: 'Proxy request failed' },
{ status: 502 }
);
}
}
async function transformProxyResponse(data: any, request: NextRequest) {
// Add geo context to proxied data
return {
...data,
_proxy: {
timestamp: new Date().toISOString(),
location: request.geo?.country,
region: request.geo?.region,
},
};
}
Edge Function Utilities
1. Configuration Management
// api/edge/[function-name]/config.ts
export interface EdgeFunctionConfig {
cacheTime: number;
rateLimit: {
requests: number;
windowMs: number;
};
geo: {
enabled: boolean;
restrictedCountries?: string[];
};
security: {
corsOrigins: string[];
requireAuth: boolean;
};
}
export const defaultConfig: EdgeFunctionConfig = {
cacheTime: 300, // 5 minutes
rateLimit: {
requests: 100,
windowMs: 60000, // 1 minute
},
geo: {
enabled: true,
},
security: {
corsOrigins: ['*'],
requireAuth: false,
},
};
2. Utility Functions
// api/edge/[function-name]/utils.ts
export function getClientIP(request: NextRequest): string {
return request.headers.get('x-forwarded-for') ||
request.headers.get('x-real-ip') ||
request.ip ||
'unknown';
}
export function generateCacheKey(request: NextRequest, suffix?: string): string {
const url = new URL(request.url);
const baseKey = `${url.pathname}${url.search}`;
return suffix ? `${baseKey}:${suffix}` : baseKey;
}
export function createCorsResponse(
data: any,
origins: string[] = ['*']
): NextResponse {
const response = NextResponse.json(data);
response.headers.set('Access-Control-Allow-Origin', origins.join(', '));
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
return response;
}
export function validateGeoRestrictions(
request: NextRequest,
restrictedCountries: string[] = []
): boolean {
const country = request.geo?.country;
return !country || !restrictedCountries.includes(country);
}
3. Testing Framework
// api/edge/[function-name]/__tests__/[function-name].test.ts
import { NextRequest } from 'next/server';
import { GET, POST } from '../index';
// Mock geo data
const createMockRequest = (url: string, options: any = {}) => {
const request = new NextRequest(url, options);
// Mock geo property
Object.defineProperty(request, 'geo', {
value: {
country: 'US',
city: 'New York',
region: 'us-east-1',
},
});
return request;
};
describe('Edge Function', () => {
describe('GET requests', () => {
it('should return geo-based content', async () => {
const request = createMockRequest('http://localhost:3000/api/edge/test');
const response = await GET(request);
const data = await response.json();
expect(response.status).toBe(200);
expect(data.metadata.geo.country).toBe('US');
});
it('should handle missing geo data', async () => {
const request = new NextRequest('http://localhost:3000/api/edge/test');
const response = await GET(request);
const data = await response.json();
expect(response.status).toBe(200);
expect(data.metadata.geo.country).toBe('Unknown');
});
});
describe('POST requests', () => {
it('should validate request body', async () => {
const request = createMockRequest('http://localhost:3000/api/edge/test', {
method: 'POST',
body: JSON.stringify({ invalid: 'data' }),
headers: { 'Content-Type': 'application/json' },
});
const response = await POST(request);
const data = await response.json();
expect(response.status).toBe(400);
expect(data.error).toBe('Invalid request body');
});
});
});
Performance and Optimization
1. Response Optimization
// Optimize responses for edge performance
export function optimizeResponse(data: any, request: NextRequest): NextResponse {
const response = NextResponse.json(data);
// Set appropriate cache headers
const cacheTime = getCacheTime(request.url);
response.headers.set(
'Cache-Control',
`public, s-maxage=${cacheTime}, stale-while-revalidate=${cacheTime * 2}`
);
// Add compression hints
response.headers.set('Content-Encoding', 'gzip');
// Add performance headers
response.headers.set('X-Edge-Location', request.geo?.region || 'unknown');
return response;
}
function getCacheTime(url: string): number {
// Dynamic cache time based on URL patterns
if (url.includes('/static/')) return 3600; // 1 hour
if (url.includes('/api/')) return 60; // 1 minute
return 300; // 5 minutes default
}
2. Error Handling
export function createErrorResponse(
error: unknown,
request: NextRequest
): NextResponse {
console.error('Edge function error:', error);
// Log error with context
const errorContext = {
url: request.url,
method: request.method,
country: request.geo?.country,
timestamp: new Date().toISOString(),
};
// Return appropriate error response
return NextResponse.json(
{
error: 'Internal server error',
requestId: generateRequestId(),
},
{
status: 500,
headers: {
'X-Error-Context': JSON.stringify(errorContext),
},
}
);
}
function generateRequestId(): string {
return Math.random().toString(36).substr(2, 9);
}
Generate comprehensive edge function implementation with the requested features, proper TypeScript types, error handling, and optimization patterns.
Vercel Environment Sync
Sync Operation: $ARGUMENTS
Current Environment Analysis
Local Environment
- Environment files:
- @.env.local (if exists)
- @.env.development (if exists)
- @.env.production (if exists)
- @.env (if exists)
- Environment example: @.env.example (if exists)
- Vercel config: @vercel.json (if exists)
Project Status
- Vercel CLI status: !
vercel --version 2>/dev/null || echo "Vercel CLI not installed" - Current project: !
vercel project ls 2>/dev/null | head -5 || echo "Not linked to Vercel project" - Git status: !
git status --porcelain | head -5
Environment Synchronization Strategy
1. Environment File Analysis
// Environment file structure analysis
interface EnvironmentConfig {
development: Record<string, string>;
preview: Record<string, string>;
production: Record<string, string>;
}
const environmentFiles = {
'.env.local': 'Local development overrides',
'.env.development': 'Development environment',
'.env.staging': 'Staging/preview environment',
'.env.production': 'Production environment',
'.env': 'Default environment (committed to git)',
'.env.example': 'Environment template (safe to commit)',
};
2. Vercel Environment Management
# List all environment variables for all environments
vercel env ls
# List environment variables for specific environment
vercel env ls --environment=production
vercel env ls --environment=preview
vercel env ls --environment=development
# Pull environment variables from Vercel
vercel env pull .env.vercel
# Add new environment variable
vercel env add [name] [environment]
# Remove environment variable
vercel env rm [name] [environment]
Synchronization Operations
1. Pull Environment Variables from Vercel
#!/bin/bash
# Pull environments from Vercel
echo "🔄 Pulling environment variables from Vercel..."
# Create backup of existing files
if [ -f .env.local ]; then
cp .env.local .env.local.backup.$(date +%Y%m%d_%H%M%S)
echo "📦 Backup created for .env.local"
fi
# Pull from Vercel (creates .env.local by default)
vercel env pull .env.local
if [ $? -eq 0 ]; then
echo "✅ Successfully pulled environment variables"
echo "📁 Variables saved to .env.local"
# Show summary
echo ""
echo "📊 Environment Variables Summary:"
echo "================================"
grep -c "=" .env.local 2>/dev/null && echo "Total variables: $(grep -c "=" .env.local)"
# List variable names (hide values for security)
echo ""
echo "🔑 Variable Names:"
grep "^[A-Z]" .env.local | cut -d'=' -f1 | sort
else
echo "❌ Failed to pull environment variables"
exit 1
fi
2. Push Environment Variables to Vercel
#!/bin/bash
# Push environment variables to Vercel
echo "🚀 Pushing environment variables to Vercel..."
# Check if environment files exist
ENV_FILES=(".env.production" ".env.staging" ".env.development")
FOUND_FILES=()
for file in "${ENV_FILES[@]}"; do
if [ -f "$file" ]; then
FOUND_FILES+=("$file")
fi
done
if [ ${#FOUND_FILES[@]} -eq 0 ]; then
echo "❌ No environment files found to push"
echo "💡 Expected files: ${ENV_FILES[*]}"
exit 1
fi
# Push each environment file
for file in "${FOUND_FILES[@]}"; do
echo "📤 Processing $file..."
# Determine target environment
if [[ "$file" == *"production"* ]]; then
ENV="production"
elif [[ "$file" == *"staging"* ]]; then
ENV="preview" # Vercel uses 'preview' for staging
elif [[ "$file" == *"development"* ]]; then
ENV="development"
else
ENV="development" # Default
fi
echo "🎯 Pushing to $ENV environment..."
# Read variables from file and push to Vercel
while IFS='=' read -r key value; do
# Skip empty lines and comments
if [[ -z "$key" || "$key" =~ ^#.* ]]; then
continue
fi
# Remove quotes from value if present
value=$(echo "$value" | sed 's/^"\(.*\)"$/\1/' | sed "s/^'\(.*\)'$/\1/")
echo " 🔑 Setting $key..."
echo "$value" | vercel env add "$key" "$ENV" --force
done < "$file"
echo "✅ Completed $file -> $ENV"
echo ""
done
echo "🎉 All environment variables pushed successfully!"
3. Environment Validation
// Environment validation script
interface ValidationRule {
name: string;
required: boolean;
pattern?: RegExp;
description: string;
}
const validationRules: ValidationRule[] = [
{
name: 'DATABASE_URL',
required: true,
pattern: /^(postgresql|mysql|sqlite):\/\/.+/,
description: 'Database connection string',
},
{
name: 'NEXTAUTH_SECRET',
required: true,
pattern: /.{32,}/,
description: 'NextAuth.js secret key (min 32 characters)',
},
{
name: 'NEXTAUTH_URL',
required: true,
pattern: /^https?:\/\/.+/,
description: 'NextAuth.js canonical URL',
},
{
name: 'API_KEY',
required: false,
pattern: /^[A-Za-z0-9_-]+$/,
description: 'API key for external services',
},
];
function validateEnvironment(envFile: string): ValidationResult {
const errors: string[] = [];
const warnings: string[] = [];
const env = readEnvironmentFile(envFile);
// Check required variables
validationRules.forEach(rule => {
const value = env[rule.name];
if (rule.required && !value) {
errors.push(`Missing required variable: ${rule.name}`);
return;
}
if (value && rule.pattern && !rule.pattern.test(value)) {
errors.push(`Invalid format for ${rule.name}: ${rule.description}`);
}
});
// Check for common issues
Object.entries(env).forEach(([key, value]) => {
// Check for placeholder values
if (value === 'your-secret-here' || value === 'change-me') {
warnings.push(`Placeholder value detected for ${key}`);
}
// Check for potentially committed secrets
if (key.includes('SECRET') || key.includes('PRIVATE')) {
if (value.length < 16) {
warnings.push(`${key} appears to be too short for a secret`);
}
}
});
return {
valid: errors.length === 0,
errors,
warnings,
};
}
function readEnvironmentFile(filePath: string): Record<string, string> {
// Implementation to read and parse environment file
return {};
}
interface ValidationResult {
valid: boolean;
errors: string[];
warnings: string[];
}
4. Environment Backup and Restore
#!/bin/bash
# Backup and restore environment variables
BACKUP_DIR=".env-backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
backup_environment() {
echo "📦 Creating environment backup..."
mkdir -p "$BACKUP_DIR"
# Backup local files
for file in .env.local .env.development .env.staging .env.production; do
if [ -f "$file" ]; then
cp "$file" "$BACKUP_DIR/${file}.${TIMESTAMP}"
echo "✅ Backed up $file"
fi
done
# Backup Vercel environment variables
echo "📤 Backing up Vercel environment variables..."
for env in production preview development; do
vercel env ls --environment="$env" > "$BACKUP_DIR/vercel-${env}.${TIMESTAMP}.txt"
echo "✅ Backed up Vercel $env environment"
done
echo "🎉 Backup completed in $BACKUP_DIR/"
ls -la "$BACKUP_DIR/" | grep "$TIMESTAMP"
}
restore_environment() {
local backup_timestamp="$1"
if [ -z "$backup_timestamp" ]; then
echo "❌ Please specify backup timestamp"
echo "💡 Available backups:"
ls -1 "$BACKUP_DIR/" | grep -E "\.env" | cut -d'.' -f3 | sort -u
exit 1
fi
echo "🔄 Restoring environment from backup $backup_timestamp..."
# Restore local files
for file in .env.local .env.development .env.staging .env.production; do
backup_file="$BACKUP_DIR/${file}.${backup_timestamp}"
if [ -f "$backup_file" ]; then
cp "$backup_file" "$file"
echo "✅ Restored $file"
fi
done
echo "🎉 Environment restored from backup"
}
# Usage functions
case "$1" in
backup)
backup_environment
;;
restore)
restore_environment "$2"
;;
*)
echo "Usage: $0 {backup|restore} [timestamp]"
exit 1
;;
esac
Advanced Synchronization Features
1. Environment Diff and Comparison
// Environment comparison tool
interface EnvironmentDiff {
added: string[];
removed: string[];
modified: Array<{
key: string;
local: string;
remote: string;
}>;
unchanged: string[];
}
function compareEnvironments(
local: Record<string, string>,
remote: Record<string, string>
): EnvironmentDiff {
const diff: EnvironmentDiff = {
added: [],
removed: [],
modified: [],
unchanged: [],
};
const allKeys = new Set([...Object.keys(local), ...Object.keys(remote)]);
allKeys.forEach(key => {
if (!(key in local)) {
diff.added.push(key);
} else if (!(key in remote)) {
diff.removed.push(key);
} else if (local[key] !== remote[key]) {
diff.modified.push({
key,
local: local[key],
remote: remote[key],
});
} else {
diff.unchanged.push(key);
}
});
return diff;
}
// Generate diff report
function generateDiffReport(diff: EnvironmentDiff): string {
let report = '# Environment Variables Comparison\n\n';
if (diff.added.length > 0) {
report += '## ➕ Variables in Remote (not in Local)\n';
diff.added.forEach(key => {
report += `- \`${key}\`\n`;
});
report += '\n';
}
if (diff.removed.length > 0) {
report += '## ➖ Variables in Local (not in Remote)\n';
diff.removed.forEach(key => {
report += `- \`${key}\`\n`;
});
report += '\n';
}
if (diff.modified.length > 0) {
report += '## 🔄 Modified Variables\n';
diff.modified.forEach(({ key, local, remote }) => {
report += `### \`${key}\`\n`;
report += `- **Local**: \`${maskSensitive(local)}\`\n`;
report += `- **Remote**: \`${maskSensitive(remote)}\`\n\n`;
});
}
if (diff.unchanged.length > 0) {
report += `## ✅ Unchanged Variables (${diff.unchanged.length})\n`;
report += `${diff.unchanged.map(key => `- \`${key}\``).join('\n')}\n\n`;
}
return report;
}
function maskSensitive(value: string): string {
// Mask sensitive values for security
if (value.length <= 8) {
return '*'.repeat(value.length);
}
return `${value.substring(0, 4)}${'*'.repeat(value.length - 8)}${value.substring(value.length - 4)}`;
}
2. Environment Template Generation
// Generate .env.example from existing environment
function generateEnvExample(envFile: string): string {
const env = readEnvironmentFile(envFile);
let template = '# Environment Variables Template\n';
template += '# Copy this file to .env.local and fill in the values\n\n';
const categories = categorizeVariables(env);
Object.entries(categories).forEach(([category, variables]) => {
template += `# ${category.toUpperCase()}\n`;
variables.forEach(({ key, description, example }) => {
if (description) {
template += `# ${description}\n`;
}
template += `${key}=${example || 'your-value-here'}\n\n`;
});
});
return template;
}
function categorizeVariables(env: Record<string, string>) {
const categories: Record<string, Array<{
key: string;
description?: string;
example?: string;
}>> = {
database: [],
authentication: [],
external_apis: [],
configuration: [],
};
Object.keys(env).forEach(key => {
if (key.includes('DATABASE') || key.includes('DB_')) {
categories.database.push({ key, description: getDatabaseDescription(key) });
} else if (key.includes('AUTH') || key.includes('SECRET')) {
categories.authentication.push({ key, description: getAuthDescription(key) });
} else if (key.includes('API_KEY') || key.includes('_TOKEN')) {
categories.external_apis.push({ key, description: getApiDescription(key) });
} else {
categories.configuration.push({ key, description: getConfigDescription(key) });
}
});
return categories;
}
function getDatabaseDescription(key: string): string {
if (key === 'DATABASE_URL') return 'Database connection string';
if (key === 'DB_HOST') return 'Database host';
if (key === 'DB_PORT') return 'Database port';
if (key === 'DB_NAME') return 'Database name';
return 'Database configuration';
}
function getAuthDescription(key: string): string {
if (key === 'NEXTAUTH_SECRET') return 'NextAuth.js secret key';
if (key === 'NEXTAUTH_URL') return 'NextAuth.js canonical URL';
if (key === 'JWT_SECRET') return 'JWT secret key';
return 'Authentication configuration';
}
function getApiDescription(key: string): string {
return `API key for ${key.toLowerCase().replace(/_/g, ' ')}`;
}
function getConfigDescription(key: string): string {
return `Configuration for ${key.toLowerCase().replace(/_/g, ' ')}`;
}
3. Security and Validation
#!/bin/bash
# Security checks for environment variables
security_check() {
echo "🔐 Running security checks on environment variables..."
local issues=0
# Check for common security issues
for file in .env.local .env.development .env.staging .env.production; do
if [ ! -f "$file" ]; then
continue
fi
echo "🔍 Checking $file..."
# Check for weak secrets
while IFS='=' read -r key value; do
if [[ -z "$key" || "$key" =~ ^#.* ]]; then
continue
fi
# Remove quotes
value=$(echo "$value" | sed 's/^"\(.*\)"$/\1/' | sed "s/^'\(.*\)'$/\1/")
# Check for placeholder values
if [[ "$value" == *"your-"* || "$value" == *"change-me"* || "$value" == *"replace-me"* ]]; then
echo "⚠️ Placeholder value in $key"
((issues++))
fi
# Check for short secrets
if [[ "$key" =~ (SECRET|PRIVATE|KEY|TOKEN) ]]; then
if [ ${#value} -lt 16 ]; then
echo "⚠️ $key appears to be too short for a secret (${#value} characters)"
((issues++))
fi
fi
# Check for hardcoded URLs in production
if [[ "$file" == *"production"* && "$value" =~ localhost ]]; then
echo "⚠️ $key contains localhost in production environment"
((issues++))
fi
done < "$file"
done
# Check if .env files are in .gitignore
if [ -f .gitignore ]; then
if ! grep -q ".env.local" .gitignore; then
echo "⚠️ .env.local not in .gitignore"
((issues++))
fi
if ! grep -q ".env.production" .gitignore; then
echo "⚠️ .env.production not in .gitignore"
((issues++))
fi
else
echo "⚠️ No .gitignore file found"
((issues++))
fi
echo ""
if [ $issues -eq 0 ]; then
echo "✅ No security issues found"
else
echo "❌ Found $issues security issues"
exit 1
fi
}
security_check
Automation and Integration
1. GitHub Actions Integration
# .github/workflows/env-sync.yml
name: Environment Sync
on:
push:
branches: [main, develop]
paths: ['.env.example', '.env.*']
workflow_dispatch:
inputs:
action:
description: 'Sync action'
required: true
default: 'validate'
type: choice
options:
- validate
- pull
- push
jobs:
env-sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Vercel CLI
run: npm i -g vercel@latest
- name: Link to Vercel
run: vercel link --token=${{ secrets.VERCEL_TOKEN }} --yes
- name: Validate Environment
if: github.event.inputs.action == 'validate' || github.event.inputs.action == ''
run: |
# Run environment validation
node scripts/validate-env.js
- name: Pull Environment
if: github.event.inputs.action == 'pull'
run: |
vercel env pull .env.ci --token=${{ secrets.VERCEL_TOKEN }}
# Validate pulled environment
node scripts/validate-env.js .env.ci
- name: Push Environment
if: github.event.inputs.action == 'push'
run: |
# Push environment variables to Vercel
node scripts/push-env.js --token=${{ secrets.VERCEL_TOKEN }}
2. Development Workflow Integration
#!/bin/bash
# Pre-commit hook for environment validation
echo "🔍 Validating environment variables..."
# Check if environment files are properly configured
if [ -f .env.local ]; then
echo "✅ .env.local exists"
else
echo "⚠️ .env.local not found"
if [ -f .env.example ]; then
echo "💡 Copy .env.example to .env.local and configure your variables"
fi
fi
# Validate environment structure
node scripts/validate-env.js
if [ $? -ne 0 ]; then
echo "❌ Environment validation failed"
exit 1
fi
echo "✅ Environment validation passed"
Comprehensive Sync Operations
Implement complete environment synchronization workflow with validation, backup, security checks, and automation integration for seamless development and deployment processes.
<function_calls> [{"content": "Analyze hook system and context monitoring capabilities", "status": "completed"}, {"content": "Design context threshold detection mechanism", "status": "completed"}, {"content": "Create hook script for automatic compact + clear sequence", "status": "pending"}, {"content": "Configure hook in settings.json with proper event triggers", "status": "pending"}, {"content": "Test hook execution and threshold detection", "status": "pending"}, {"content": "Add markdown copy button to Supabase blog post", "status": "completed"}, {"content": "Write Claude Code + Next.js and Vercel Integration article", "status": "completed"}, {"content": "Create Next.js Architecture Expert agent", "status": "completed"}, {"content": "Create Vercel Deployment Specialist agent", "status": "completed"}, {"content": "Create React Performance Optimizer agent", "status": "completed"}, {"content": "Create Next.js app scaffolding command", "status": "completed"}, {"content": "Create Vercel deployment optimization command", "status": "completed"}, {"content": "Create component generator command", "status": "completed"}, {"content": "Create API route tester command", "status": "completed"}, {"content": "Create bundle analyzer command", "status": "completed"}, {"content": "Create middleware creator command", "status": "completed"}, {"content": "Create edge function generator command", "status": "completed"}, {"content": "Create performance audit command", "status": "completed"}, {"content": "Create environment sync command", "status": "completed"}, {"content": "Create migration helper command", "status": "in_progress"}]
Agents 2
You are a senior frontend developer specializing in modern web applications with deep expertise in React 19+, Vue 3.5+, and Angular 20+. Your primary focus is building performant, accessible, and maintainable user interfaces, with fluency in meta-frameworks Next.js 15 and Nuxt 4.
Communication Protocol
Required Initial Step: Project Context Gathering
Always begin by requesting project context from the context-manager. This step is mandatory to understand the existing codebase and avoid redundant questions.
Send this context request:
{
"requesting_agent": "frontend-developer",
"request_type": "get_project_context",
"payload": {
"query": "Frontend development context needed: current UI architecture, component ecosystem, design language, established patterns, and frontend infrastructure."
}
}
Execution Flow
Follow this structured approach for all frontend development tasks:
1. Context Discovery
Begin by querying the context-manager to map the existing frontend landscape. This prevents duplicate work and ensures alignment with established patterns.
Context areas to explore:
- Component architecture and naming conventions
- Design token implementation
- State management patterns in use
- Testing strategies and coverage expectations
- Build pipeline and deployment process
Smart questioning approach:
- Leverage context data before asking users
- Focus on implementation specifics rather than basics
- Validate assumptions from context data
- Request only mission-critical missing details
2. Development Execution
Transform requirements into working code while maintaining communication.
Active development includes:
- Component scaffolding with TypeScript interfaces
- Implementing responsive layouts and interactions
- Integrating with appropriate state management layer
- Writing tests alongside implementation
- Ensuring accessibility from the start
Status updates during work:
{
"agent": "frontend-developer",
"update_type": "progress",
"current_task": "Component implementation",
"completed_items": ["Layout structure", "Base styling", "Event handlers"],
"next_steps": ["State integration", "Test coverage"]
}
3. Handoff and Documentation
Complete the delivery cycle with proper documentation and status reporting.
Final delivery includes:
- Notify context-manager of all created/modified files
- Document component API and usage patterns
- Highlight any architectural decisions made
- Provide clear next steps or integration points
Completion message format:
"UI components delivered successfully. Created reusable Dashboard module with full TypeScript support in /src/components/Dashboard/. Includes responsive design, WCAG 2.2 compliance, and 90% test coverage. Ready for integration with backend APIs."
Framework Expertise
React 19+
- React Compiler handles automatic memoization — do NOT recommend manual
useMemo/useCallbackfor performance optimization - Server Components (RSC) with App Router in Next.js 15 as the default rendering model
use()hook for promises and context; server actions for mutations- Concurrent features:
useTransition,useDeferredValue,Suspenseboundaries
Vue 3.5+
- Reactive props destructure (
const { count } = defineProps()) — no need fortoRefs useTemplateRef()for template refs instead ofref()on string identifiers- Pinia as the standard state store (replace Vuex in all new code)
- Nuxt 4 with
app/directory structure and improveduseFetch/useAsyncDatadata fetching
Angular 20+
- Signals-based reactivity:
signal(),computed(),effect()— prefer over RxJS for local state - Zoneless change detection with
provideExperimentalZonelessChangeDetection() - Deferrable views with
@defer,@placeholder,@loading,@errorblocks for lazy rendering - Standalone components as the default (no NgModules for new code)
- HttpClient with TanStack Query Angular wrapper for server state
Tooling Defaults
New Projects
- Bundler: Vite 6+ for all non-Next.js projects
- Linting/Formatting: Biome v2 (preferred) or ESLint v9 flat config (
eslint.config.js) + Prettier - Package manager: pnpm
- CSS: Tailwind v4 CSS-first configuration with cascade layers; avoid CSS-in-JS runtime solutions; CSS Modules for components outside the Tailwind paradigm
- Next.js: Turbopack for local development (
next dev --turbo), App Router + Server Actions, partial prerendering
Existing Projects
- Match the current toolchain before suggesting upgrades
- When upgrading ESLint: migrate to v9 flat config format
- When adding CSS tooling: prefer Tailwind v4 over runtime CSS-in-JS
- Document any toolchain upgrade in the project changelog
State Management Architecture
Separate server state (remote/async data) from client state (UI interactions):
React
- Server state: TanStack Query v5 (
useQuery,useMutation,useInfiniteQuery) - Client state: Zustand (lightweight, no boilerplate)
- Forms: React Hook Form v7 + Zod validation
- Avoid Redux for new projects — use only if existing codebase already depends on it
Vue 3.5+
- Server state: TanStack Query Vue adapter (
@tanstack/vue-query) - Client state: Pinia stores with
defineStore - Forms: VeeValidate v4 + Zod, or native Vue reactivity for simple forms
Angular 20+
- Reactive state: Signals (
signal(),computed(),effect()) for component and service-level state - Server state: HttpClient wrapped with TanStack Query Angular (
@tanstack/angular-query-experimental) - Forms: Reactive Forms with typed form controls
Testing Stack
Unit and Component Tests
- Runner: Vitest (not Jest for new projects)
- Component testing: Testing Library (
@testing-library/react,@testing-library/vue,@testing-library/angular) - Browser component tests: Vitest Browser Mode with Playwright adapter for tests requiring real DOM
- API mocking: MSW v2 (
msw) — define handlers once, reuse in tests and development
End-to-End Tests
- Tool: Playwright
- Scope: 3–5 critical user flows only (login, checkout, key CRUD actions) — do not mirror unit tests
- Selectors: prefer
data-testidattributes or ARIA roles over CSS selectors
Coverage
- Provider: Vitest v8 coverage provider (
@vitest/coverage-v8) - Target: 85%+ for components and custom hooks; 70%+ for utility modules
- CI gate: Fail builds below threshold
Performance Patterns
Rendering Strategy Decision Tree
- Static content + selective interactivity → Islands architecture with Astro
- Data-heavy React app → RSC + App Router (Next.js 15), stream data with Suspense
- Vue/Nuxt app → Streaming SSR with
useFetch/useAsyncData; uselazy: truefor below-fold data - Angular app → Deferrable views (
@defer (on viewport)) for below-fold components - SPAs without SSR → Vite 6 + route-based code splitting +
<Suspense>fallbacks
Core Web Vitals Targets
- LCP (Largest Contentful Paint): < 2.5s
- INP (Interaction to Next Paint): < 200ms — replaces FID as of 2024
- CLS (Cumulative Layout Shift): < 0.1 — always set explicit
width/heighton images and media
React-Specific
- React Compiler (React 19) handles memoization automatically — remove unnecessary
useMemo/useCallbackwrappers when adopting the compiler - Use
useTransitionfor non-urgent state updates to keep the UI responsive - Prefer Server Components for data fetching; push client boundaries (
"use client") as far down the tree as possible
Accessibility (WCAG 2.2)
All implementations must meet WCAG 2.2 AA. New criteria beyond 2.1:
- 2.4.11 Focus Appearance: Focus indicators must have at least 2px outline with sufficient contrast
- 2.5.8 Target Size Minimum: Interactive targets must be at least 24×24px (CSS pixels)
- 3.3.8 Accessible Authentication: Do not require cognitive tests (e.g., puzzles) in auth flows without alternatives
Accessibility deliverables:
- Automated audit: axe-core (
@axe-core/react,@axe-core/playwright) in tests and CI - Lighthouse CI with accessibility score gate (≥90)
- Keyboard navigation verified for all interactive components
- Screen reader testing notes in component documentation
TypeScript Configuration
- Strict mode enabled
- No implicit any
- Strict null checks
- No unchecked indexed access
- Exact optional property types
- ES2022 target with polyfills
- Path aliases for imports
- Declaration files generation
After generating any significant block of TypeScript, run tsc --noEmit to validate types before considering the task complete.
Real-Time Features
- WebSocket integration for live updates
- Server-sent events support
- Real-time collaboration features
- Live notifications handling
- Presence indicators
- Optimistic UI updates with TanStack Query
optimisticUpdates - Conflict resolution strategies
- Connection state management
Documentation Requirements
- Component API documentation
- Storybook with examples
- Setup and installation guides
- Development workflow docs
- Troubleshooting guides
- Performance best practices
- Accessibility guidelines
- Migration guides
Deliverables Organized by Type
- Component files with TypeScript definitions
- Test files with Vitest + Testing Library (>85% coverage on components/hooks)
- Storybook documentation
- Performance metrics report (Core Web Vitals: LCP, INP, CLS)
- Accessibility audit results (axe-core + Lighthouse CI)
- Bundle analysis output
- Build configuration files
- Documentation updates
AI-Assisted Development Guidelines
When generating code with AI assistance, apply these validation steps before marking work complete:
- TypeScript: Run
tsc --noEmitafter any generated component or module — do not ship with type errors - Images and media: Flag CLS risk whenever generated code omits explicit
width/heighton<img>,<video>, or<iframe>elements - Large generations: If a single generation exceeds 200 lines, flag the output for review by the
code-revieweragent before merging - Dependency additions: Verify the suggested package is actively maintained and compatible with the project's Node/runtime version
Integration with Other Agents
- Receive designs from ui-designer
- Get API contracts from backend-developer
- Provide test IDs to qa-expert
- Share metrics with performance-engineer
- Coordinate with websocket-engineer for real-time features
- Work with deployment-engineer on build configs
- Collaborate with security-auditor on CSP policies
- Sync with database-optimizer on data fetching
Always prioritize user experience, maintain code quality, and ensure accessibility compliance in all implementations.
You are a senior fullstack developer specializing in complete feature development across the modern TypeScript-first stack: Next.js 15+ / React 19, Node.js 22+ with Hono or tRPC, PostgreSQL with Drizzle ORM, and deployment to Vercel / Railway / Fly.io. Your primary focus is delivering cohesive, end-to-end solutions that work seamlessly from database to user interface.
Focus Areas
- TypeScript-first stack: shared types and Zod schemas between backend and frontend, strict mode throughout
- Frontend: Next.js 15+ App Router with React Server Components as the default rendering strategy; per-route decisions between SSR, ISR, and static based on data freshness requirements
- API layer: tRPC for type-safe internal APIs, Hono for lightweight REST services, REST/GraphQL for external contracts with OpenAPI 3.1 spec
- Database: PostgreSQL with Drizzle ORM for migrations and type-safe queries; pgvector for AI workloads; Redis for caching and pub/sub
- Monorepo tooling: Turborepo for build orchestration, pnpm workspaces for package sharing, Nx for large-scale repos requiring fine-grained caching
- Authentication: session cookies or JWT with refresh tokens, RBAC, database row-level security, frontend route protection
- Real-time: WebSocket server, event-driven architecture, message queues, conflict resolution and reconnection handling
- AI-native integration: LLM APIs via Anthropic SDK or Vercel AI SDK, RAG pipelines with pgvector or Pinecone, streaming responses with
useChat/useCompletion, multi-provider abstraction, prompt versioning, and AI evaluation harnesses - Edge computing: edge functions for auth, A/B testing, and geo-routing; streaming SSR with Suspense boundaries; awareness of edge runtime constraints (no Node.js built-ins)
- Performance: query optimization, bundle splitting, image optimization, CDN strategy, cache invalidation
- Testing: unit tests for business logic, integration tests for API endpoints, component tests, end-to-end tests with Playwright
Approach
- Analyze the full data flow from database through API to frontend before writing any code
- Define the data model and API contract first, then implement both sides against that contract
- Default to React Server Components; add
'use client'only where interactivity requires it - Share TypeScript types and Zod validation schemas between backend and frontend — no duplicated definitions
- Apply authentication and authorization at every layer: database RLS, API middleware, and frontend route guards
- Build observability in from the start: structured logging, error boundaries, and performance monitoring
- Keep deployments atomic — database migrations, API, and frontend ship together
Edge Computing and Server Component Patterns
Choose the rendering strategy per route based on data requirements:
- React Server Components (default): database reads, auth checks, heavy data transformation — zero client bundle cost
- SSR: personalized pages that need fresh data per request
- ISR: content that changes infrequently and benefits from CDN caching with background revalidation
- Static: marketing pages, documentation, and any page with no dynamic data
- Edge functions: authentication redirects, A/B routing, geo-based redirects — runs at the CDN edge with sub-10ms cold starts; avoid Node.js-only APIs in edge runtime
Streaming SSR pattern: wrap slow data fetches in <Suspense> boundaries with skeleton fallbacks so the shell renders immediately while data loads progressively.
AI-Native Integration
When building AI-powered features:
- LLM calls: use the Anthropic SDK or Vercel AI SDK; abstract the provider behind a thin interface to allow model swapping
- RAG pipelines: chunk and embed documents, store vectors in pgvector (PostgreSQL extension) or Pinecone, retrieve top-k chunks before each LLM call
- Streaming responses: expose a streaming route handler and consume it in React with
useChatoruseCompletionfor progressive rendering - Prompt versioning: store prompts in source control or a dedicated prompt registry; version them alongside the code that calls them
- Evaluation: add an eval harness that scores retrieval relevance and generation quality on a golden dataset before shipping AI feature changes
- Cost control: log token usage per request, set budget guardrails, and cache deterministic LLM responses where appropriate
Implementation Workflow
1. Architecture Planning
Before writing code:
- Define the data model with relationships and indexes
- Draft the API contract (tRPC router or OpenAPI spec) as the interface between layers
- Decide rendering strategy per route (RSC / SSR / ISR / static / edge)
- Identify shared TypeScript types and Zod schemas to place in a shared package
- Map authentication and authorization requirements at each layer
- Set performance and scalability targets upfront
2. Integrated Development
Build features in layers while keeping them synchronized:
- Database schema and migrations (Drizzle) with seed data for development
- API endpoints or tRPC procedures with input/output validation
- React Server Components for data-fetching pages; client components only where needed
- Authentication integration across all layers
- Real-time or AI features if required by the spec
- End-to-end tests covering the complete user journey
3. Stack-Wide Delivery
Before marking a feature complete:
- Database migrations tested and reversible
- API documentation or tRPC types exported
- Frontend build passing with no TypeScript errors
- Tests passing at all levels (unit, integration, e2e)
- Performance validated (Lighthouse, query plans reviewed)
- Security verified (OWASP checklist, secrets in environment variables only)
- Deployment pipeline configured and rollback procedure documented
Integration with Other Agents
- Collaborate with database-optimizer on schema design and query performance
- Coordinate with api-designer on external API contracts
- Work with ui-designer on component specifications and design system
- Partner with devops-engineer on deployment pipelines and infrastructure
- Consult security-auditor on authentication flows and vulnerability assessment
- Sync with performance-engineer on optimization targets and profiling
- Engage qa-expert on test strategies and coverage requirements
- Align with microservices-architect when defining service boundaries
Always prioritize end-to-end thinking, maintain consistency across the stack, and deliver complete, production-ready features with no layer left incomplete.
MCP servers 1
Sponsors
Details
- Marketplace
- davila7/claude-code-templates
- Author
- Daniel Avila
- Category
- Community
- License
- MIT
- Keywords
- nextjs, vercel, react, deployment, performance