Skip to content
Back to skills

Nextjs App

ASecurity

生成Next.js 14+ App Router组件,包括服务端组件、客户端组件、API路由、中间件和数据获取模式。

  • 85 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added February 7, 2026
developmentreactnextjsapifullstack

Works with

  • claude code
  • cli
  • api

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add AIDotNet/MoYuCode --skill nextjs-app --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Nextjs App?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Nextjs App
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/aidotnet-nextjs-app/badge)](https://www.skillsdirectory.com/skills/aidotnet-nextjs-app)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: nextjs-app
description: 生成Next.js 14+ App Router组件,包括服务端组件、客户端组件、API路由、中间件和数据获取模式。
metadata:
  short-description: 生成Next.js App Router代码
---

# Next.js App Skill

## Description
Generate Next.js 14+ App Router components with server/client patterns.

## Trigger
- `/nextjs` command
- User requests Next.js code
- User needs App Router patterns

## Prompt

You are a Next.js expert that creates modern App Router applications.

### Server Component with Data Fetching

```tsx
// app/users/page.tsx
import { Suspense } from 'react';

interface User {
  id: string;
  name: string;
  email: string;
}

async function getUsers(): Promise<User[]> {
  const res = await fetch('https://api.example.com/users', {
    next: { revalidate: 60 }, // ISR: revalidate every 60 seconds
  });
  if (!res.ok) throw new Error('Failed to fetch users');
  return res.json();
}

async function UserList() {
  const users = await getUsers();
  
  return (
    <ul className="space-y-2">
      {users.map(user => (
        <li key={user.id} className="p-4 bg-white rounded-lg shadow">
          <h3 className="font-semibold">{user.name}</h3>
          <p className="text-gray-600">{user.email}</p>
        </li>
      ))}
    </ul>
  );
}

export default function UsersPage() {
  return (
    <main className="container mx-auto p-4">
      <h1 className="text-2xl font-bold mb-4">Users</h1>
      <Suspense fallback={<div>Loading users...</div>}>
        <UserList />
      </Suspense>
    </main>
  );
}
```

### Client Component with Form

```tsx
'use client';

import { useState, useTransition } from 'react';
import { useRouter } from 'next/navigation';
import { createUser } from './actions';

export function CreateUserForm() {
  const router = useRouter();
  const [isPending, startTransition] = useTransition();
  const [error, setError] = useState<string | null>(null);

  async function handleSubmit(formData: FormData) {
    setError(null);
    startTransition(async () => {
      const result = await createUser(formData);
      if (result.error) {
        setError(result.error);
      } else {
        router.push('/users');
        router.refresh();
      }
    });
  }

  return (
    <form action={handleSubmit} className="space-y-4">
      {error && <div className="text-red-600">{error}</div>}
      
      <input
        name="name"
        placeholder="Name"
        required
        className="w-full p-2 border rounded"
      />
      <input
        name="email"
        type="email"
        placeholder="Email"
        required
        className="w-full p-2 border rounded"
      />
      
      <button
        type="submit"
        disabled={isPending}
        className="w-full p-2 bg-blue-600 text-white rounded disabled:opacity-50"
      >
        {isPending ? 'Creating...' : 'Create User'}
      </button>
    </form>
  );
}
```

### Server Action

```tsx
// app/users/actions.ts
'use server';

import { revalidatePath } from 'next/cache';
import { z } from 'zod';

const CreateUserSchema = z.object({
  name: z.string().min(1),
  email: z.string().email(),
});

export async function createUser(formData: FormData) {
  const validated = CreateUserSchema.safeParse({
    name: formData.get('name'),
    email: formData.get('email'),
  });

  if (!validated.success) {
    return { error: 'Invalid input' };
  }

  try {
    await fetch('https://api.example.com/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(validated.data),
    });
    
    revalidatePath('/users');
    return { success: true };
  } catch {
    return { error: 'Failed to create user' };
  }
}
```

### Middleware

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

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')?.value;
  
  // Protect dashboard routes
  if (request.nextUrl.pathname.startsWith('/dashboard')) {
    if (!token) {
      return NextResponse.redirect(new URL('/login', request.url));
    }
  }
  
  return NextResponse.next();
}

export const config = {
  matcher: ['/dashboard/:path*'],
};
```

## Tags
`nextjs`, `react`, `app-router`, `server-components`, `fullstack`

## Compatibility
- Codex: ✅
- Claude Code: ✅

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.