
Vercel Development
- 598 installs
- 215 repo stars
- Updated June 9, 2026
- mindrally/skills
vercel-development is a mindrally agent skill that provides concise rules for building and deploying Next.js applications on Vercel with React Server Components, Edge Functions, and the AI SDK for developers shipping pro
About
vercel-development is a mindrally/skills guide for Vercel and Next.js production development. It promotes concise TypeScript with functional patterns, minimizing use client, useEffect, and setState in favor of React Server Components, plus responsive design and Vercel platform features including Edge Functions and the Vercel AI SDK. The skill helps agents choose server-first rendering strategies, integrate AI SDK calls appropriately, and optimize deployments on Vercel's edge network. Developers reach for vercel-development when scaffolding Next.js App Router features, reviewing RSC boundaries, configuring edge routes, or aligning AI features with Vercel hosting constraints. It bridges frontend architecture decisions and Vercel deploy practices in one reference tuned to current Next.js and platform capabilities.
- Core principles for concise TypeScript, functional patterns, and React Server Components
- Project structure template with App Router, route groups, and recommended folders
- Next.js App Router file naming and routing conventions
- Vercel-specific deployment best practices including Edge Functions and AI SDK integration
- Performance optimization focused on Core Web Vitals and mobile-first Tailwind CSS
Vercel Development by the numbers
- 598 all-time installs (skills.sh)
- +16 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #570 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mindrally/skills --skill vercel-developmentAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 598 |
|---|---|
| repo stars | ★ 215 |
| Last updated | June 9, 2026 |
| Repository | mindrally/skills ↗ |
How do you deploy Next.js on Vercel with RSC?
Get concise, up-to-date rules for building and deploying Next.js applications on Vercel with React Server Components, Edge Functions, and the AI SDK.
Who is it for?
Full-stack developers shipping Next.js applications on Vercel who need RSC, Edge Functions, and AI SDK conventions enforced by agents.
Skip if: Teams deploying solely to self-hosted Node servers without Vercel or projects avoiding Next.js App Router patterns.
When should I use this skill?
The user builds or deploys Next.js on Vercel, configures Edge Functions, or integrates the Vercel AI SDK with RSC.
What you get
Vercel-ready Next.js apps with RSC boundaries, Edge Function routes, and AI SDK integration following platform best practices.
- Vercel deployment configurations
- RSC-optimized Next.js routes
Files
Vercel Development Best Practices
Overview
This skill provides comprehensive guidelines for developing and deploying applications on Vercel, with a focus on Next.js, React Server Components, Edge Functions, and the Vercel AI SDK.
Core Principles
- Write concise, technical TypeScript code with accurate examples
- Use functional and declarative programming patterns; avoid classes
- Minimize 'use client', 'useEffect', and 'setState'; favor React Server Components (RSC)
- Implement responsive design with Tailwind CSS using mobile-first approach
- Optimize for Core Web Vitals and performance
Project Structure
my-app/
├── app/ # App Router pages and layouts
│ ├── (auth)/ # Route groups
│ ├── api/ # API routes
│ ├── layout.tsx # Root layout
│ └── page.tsx # Home page
├── components/ # React components
│ ├── ui/ # UI primitives
│ └── features/ # Feature components
├── lib/ # Utility functions
├── hooks/ # Custom React hooks
├── types/ # TypeScript types
├── public/ # Static assets
└── vercel.json # Vercel configurationNext.js App Router Guidelines
File Naming Conventions
- Use lowercase with dashes for directories (e.g.,
components/auth-wizard) - Prefer named exports for components and functions
- Use
page.tsxfor route pages,layout.tsxfor layouts - Use
loading.tsxfor loading states,error.tsxfor error boundaries
Server Components (Default)
// app/users/page.tsx
import { getUsers } from '@/lib/data';
export default async function UsersPage() {
const users = await getUsers();
return (
<main>
<h1>Users</h1>
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</main>
);
}Client Components (When Needed)
'use client';
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);
}TypeScript Standards
Type Definitions
// Use interfaces over types for object shapes
interface User {
id: string;
name: string;
email: string;
createdAt: Date;
}
// Use types for unions and complex types
type Status = 'pending' | 'active' | 'inactive';
// Avoid enums; use const objects instead
const STATUS = {
PENDING: 'pending',
ACTIVE: 'active',
INACTIVE: 'inactive',
} as const;
type StatusValue = typeof STATUS[keyof typeof STATUS];Component Props
interface ButtonProps {
children: React.ReactNode;
variant?: 'primary' | 'secondary' | 'ghost';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
onClick?: () => void;
}
export function Button({
children,
variant = 'primary',
size = 'md',
disabled = false,
onClick,
}: ButtonProps) {
// Implementation
}API Routes
Route Handlers
// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
const CreateUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
});
export async function GET(request: NextRequest) {
const users = await getUsers();
return NextResponse.json(users);
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const validated = CreateUserSchema.parse(body);
const user = await createUser(validated);
return NextResponse.json(user, { status: 201 });
} catch (error) {
if (error instanceof z.ZodError) {
return NextResponse.json(
{ error: 'Validation failed', details: error.errors },
{ status: 400 }
);
}
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}Edge Runtime
// app/api/edge-function/route.ts
export const runtime = 'edge';
export async function GET(request: Request) {
return new Response(JSON.stringify({ message: 'Hello from the edge!' }), {
headers: { 'Content-Type': 'application/json' },
});
}Vercel AI SDK Integration
Streaming Chat UI
'use client';
import { useChat } from 'ai/react';
export function Chat() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
api: '/api/chat',
});
return (
<div className="flex flex-col h-full">
<div className="flex-1 overflow-y-auto">
{messages.map(message => (
<div key={message.id} className={message.role === 'user' ? 'text-right' : ''}>
<p>{message.content}</p>
</div>
))}
</div>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
placeholder="Type a message..."
disabled={isLoading}
/>
</form>
</div>
);
}AI API Route
// app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
export async function POST(request: Request) {
const { messages } = await request.json();
const result = await streamText({
model: openai('gpt-4-turbo'),
messages,
system: 'You are a helpful assistant.',
});
return result.toDataStreamResponse();
}Error Handling for AI
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
export async function POST(request: Request) {
try {
const { messages } = await request.json();
const result = await streamText({
model: openai('gpt-4-turbo'),
messages,
});
return result.toDataStreamResponse();
} catch (error) {
// Handle rate limiting
if (error.message?.includes('rate limit')) {
return new Response('Rate limit exceeded. Please try again later.', {
status: 429,
});
}
// Handle quota exceeded
if (error.message?.includes('quota')) {
return new Response('API quota exceeded.', { status: 402 });
}
// Fallback to alternative model
console.error('Primary model failed:', error);
return new Response('Service temporarily unavailable.', { status: 503 });
}
}Data Fetching
Server-Side Data Fetching
// Fetch data in Server Components
async function getData() {
const res = await fetch('https://api.example.com/data', {
next: { revalidate: 3600 }, // Cache for 1 hour
});
if (!res.ok) {
throw new Error('Failed to fetch data');
}
return res.json();
}
export default async function Page() {
const data = await getData();
return <div>{/* Render data */}</div>;
}URL State Management
// Use URL query parameters for server state
import { useSearchParams, useRouter } from 'next/navigation';
export function Filters() {
const searchParams = useSearchParams();
const router = useRouter();
const updateFilter = (key: string, value: string) => {
const params = new URLSearchParams(searchParams);
params.set(key, value);
router.push(`?${params.toString()}`);
};
return (/* Filter UI */);
}Performance Optimization
Image Optimization
import Image from 'next/image';
export function Hero() {
return (
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={600}
priority // Load immediately for LCP
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
/>
);
}Dynamic Imports
import dynamic from 'next/dynamic';
// Lazy load heavy components
const HeavyChart = dynamic(() => import('@/components/heavy-chart'), {
loading: () => <div>Loading chart...</div>,
ssr: false, // Disable SSR if needed
});Suspense Boundaries
import { Suspense } from 'react';
export default function Page() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<Loading />}>
<AsyncComponent />
</Suspense>
</div>
);
}Error Handling
Error Boundaries
// app/error.tsx
'use client';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={reset}>Try again</button>
</div>
);
}Global Error Handler
// app/global-error.tsx
'use client';
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={reset}>Try again</button>
</body>
</html>
);
}Vercel Configuration
vercel.json
{
"framework": "nextjs",
"regions": ["iad1"],
"crons": [
{
"path": "/api/cron/cleanup",
"schedule": "0 0 * * *"
}
],
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Access-Control-Allow-Origin", "value": "*" }
]
}
]
}Environment Variables
// Use environment variables for sensitive data
const apiKey = process.env.API_KEY;
const publicUrl = process.env.NEXT_PUBLIC_APP_URL;
// Validate required env vars
if (!apiKey) {
throw new Error('API_KEY environment variable is required');
}Deployment
Preview Deployments
- Every pull request gets a preview deployment
- Use preview URLs for testing and review
- Share preview links with stakeholders
Production Deployment
# Connect repo to Vercel (one-click from GitHub)
# Or use Vercel CLI
vercel --prodEdge Config
import { get } from '@vercel/edge-config';
export async function getFeatureFlag(flag: string) {
const flags = await get('featureFlags');
return flags?.[flag] ?? false;
}UI and Styling
Tailwind CSS Setup
// Use mobile-first responsive design
export function Card({ children }: { children: React.ReactNode }) {
return (
<div className="p-4 md:p-6 lg:p-8 rounded-lg bg-white shadow-sm">
{children}
</div>
);
}Shadcn UI Components
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogTrigger } from '@/components/ui/dialog';
export function ConfirmDialog() {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="destructive">Delete</Button>
</DialogTrigger>
<DialogContent>
<p>Are you sure?</p>
</DialogContent>
</Dialog>
);
}Accessibility
Best Practices
export function AccessibleButton() {
return (
<button
aria-label="Close dialog"
aria-expanded={isOpen}
aria-controls="dialog-content"
className="focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
<XIcon aria-hidden="true" />
</button>
);
}Common Pitfalls to Avoid
1. Using 'use client' unnecessarily 2. Not implementing proper error boundaries 3. Ignoring Core Web Vitals optimization 4. Not using TypeScript strictly 5. Hardcoding environment variables 6. Missing Suspense boundaries for async components 7. Not optimizing images 8. Ignoring accessibility requirements
Related skills
How it compares
Pick vercel-development over generic Next.js skills when deployment targets Vercel with Edge Functions and the AI SDK, not static export-only sites.
FAQ
What Next.js patterns does vercel-development prioritize?
vercel-development from mindrally/skills prioritizes React Server Components and server-first data fetching while minimizing use client, useEffect, and setState. It favors concise TypeScript, functional patterns, and responsive design aligned with Vercel deployment.
Which Vercel platform features does vercel-development cover?
vercel-development covers deploying Next.js on Vercel, configuring Edge Functions, and integrating the Vercel AI SDK alongside performance optimization guidance. Agents use it when shipping App Router apps to Vercel infrastructure.