Next.js App Skill

SkillDev tools

Generates Next.js 14+ App Router components, including server components, client components, API routes, middleware, and data fetching patterns.

Then ask your AI: use the Next.js App Skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add it as a step in a pipeline you build on Ahel, or connect Ahel to Claude, ChatGPT, Cursor, Claude Code or Codex and ask your AI to use it.

What this skill tells your AI

The instructions your AI receives, as published by aidotnet/moyucode in skills/community/nextjs-app/SKILL.md and read by Ahel’s review.

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

// 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

'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

// 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

// 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: ✅

Signals

GitHub stars
85
Forks
17
Last commit
Jan 2026
Advanced
Item type
skill
Key
nextjs-app
Source
github.com/aidotnet/moyucode