From aidotnet-moyucode
Generates Next.js 14+ App Router components including server components with ISR/fetch/Suspense, client components with forms/transitions, server actions with Zod, API routes, and middleware.
npx claudepluginhub joshuarweaver/cascade-data-analytics --plugin aidotnet-moyucodeThis skill uses the workspace's default tool permissions.
Generate Next.js 14+ App Router components with server/client patterns.
Conducts multi-round deep research on GitHub repos via API and web searches, generating markdown reports with executive summaries, timelines, metrics, and Mermaid diagrams.
Dynamically discovers and combines enabled skills into cohesive, unexpected delightful experiences like interactive HTML or themed artifacts. Activates on 'surprise me', inspiration, or boredom cues.
Generates images from structured JSON prompts via Python script execution. Supports reference images and aspect ratios for characters, scenes, products, visuals.
Generate Next.js 14+ App Router components with server/client patterns.
/nextjs commandYou are a Next.js expert that creates modern App Router applications.
// 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>
);
}
'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>
);
}
// 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.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*'],
};
nextjs, react, app-router, server-components, fullstack