nextjs-template/skills/nextjs-template/SKILL.md
# Next.js Template Skill Generate production-ready Next.js pages with SSR initial load, SWR client-side data management, and server-response-based cache updates. ## When to Use This Skill Use this skill when asked to: - Create a new Next.js page with data table - Add CRUD functionality to a Next.js application - Generate pages with server-side rendering and client-side updates - Build admin/settings pages with filtering, pagination, and bulk actions ## Architecture Overview ``` ┌───────────
npx skillsauth add adelabdelgawad/claude-fullstack-plugins nextjs-template/skills/nextjs-templateInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate production-ready Next.js pages with SSR initial load, SWR client-side data management, and server-response-based cache updates.
Use this skill when asked to:
┌─────────────────────────────────────────────────────────────┐
│ Browser Request │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ page.tsx (Server Component) │
│ • auth() check │
│ • await searchParams (Next.js 15+) │
│ • Fetch initial data via server actions │
│ • Pass initialData to client component │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ *-table.tsx (Client Component) │
│ • useSWR with fallbackData: initialData │
│ • Context Provider for actions │
│ • updateItems() uses server response (NOT optimistic) │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ API Routes (app/api/...) │
│ • withAuth() wrapper │
│ • Proxy to FastAPI backend │
│ • backendGet/Post/Put/Delete helpers │
└─────────────────────────────────────────────────────────────┘
app/(pages)/setting/{entity}/
├── page.tsx # SSR page (server component)
├── context/
│ └── {entity}-actions-context.tsx # Actions provider
└── _components/
├── actions/
│ ├── add-{entity}-button.tsx
│ └── {entity}-actions-menu.tsx
├── modal/
│ ├── add-{entity}-sheet.tsx
│ └── edit-{entity}-sheet.tsx
├── sidebar/
│ └── status-panel.tsx
└── table/
├── {entity}-table.tsx # Main client component
├── {entity}-table-body.tsx
└── {entity}-table-columns.tsx
app/api/setting/{entity}/
├── route.ts # GET (list), POST (create)
└── [{entityId}]/
├── route.ts # GET, PUT, DELETE
└── status/
└── route.ts # PUT (toggle status)
lib/
├── actions/
│ └── {entity}.actions.ts # Server actions
└── fetch/
├── client.ts # Client-side fetch
├── server.ts # Server-side fetch
└── api-route-helper.ts # API route helpers
types/
└── {entity}.d.ts # TypeScript types
Server Component (page.tsx):
// NO "use client" - this is a server component
import { auth } from "@/lib/auth/server-auth";
import { getItems } from "@/lib/actions/items.actions";
import { redirect } from "next/navigation";
import ItemsTable from "./_components/table/items-table";
export default async function ItemsPage({
searchParams,
}: {
searchParams: Promise<{ page?: string; limit?: string; search?: string }>;
}) {
const session = await auth();
if (!session?.accessToken) redirect("/login");
const params = await searchParams; // Next.js 15+ requires await
const page = Number(params.page) || 1;
const limit = Number(params.limit) || 10;
const items = await getItems(limit, (page - 1) * limit, params);
return <ItemsTable initialData={items} />;
}
Client Component (items-table.tsx):
"use client";
import useSWR from "swr";
import { fetchClient } from "@/lib/fetch/client";
const fetcher = (url: string) => fetchClient.get(url).then(r => r.data);
function ItemsTable({ initialData }) {
const searchParams = useSearchParams();
const page = Number(searchParams?.get("page") || "1");
const { data, mutate, isLoading } = useSWR(
`/api/setting/items?page=${page}`,
fetcher,
{
fallbackData: initialData, // SSR data as initial cache
keepPreviousData: true, // Smooth transitions
revalidateOnMount: false, // Don't refetch on mount
revalidateOnFocus: false, // Don't refetch on focus
}
);
// ...
}
// ✅ CORRECT: Use server response to update cache
const updateItems = async (serverResponse: Item[]) => {
const currentData = data;
if (!currentData) return;
const responseMap = new Map(serverResponse.map(i => [i.id, i]));
const updatedList = currentData.items.map(item =>
responseMap.has(item.id) ? responseMap.get(item.id)! : item
);
await mutate(
{ ...currentData, items: updatedList },
{ revalidate: false }
);
};
// In action handler:
const { data: updatedItem } = await fetchClient.put(`/api/items/${id}`, payload);
await updateItems([updatedItem]); // Use server response!
// ❌ WRONG: Optimistic update
const updatedList = currentData.items.map(item =>
item.id === id ? { ...item, ...localChanges } : item // Don't do this!
);
// context/{entity}-actions-context.tsx
"use client";
import { createContext, useContext, ReactNode } from "react";
interface ActionsContextType {
onToggleStatus: (id: string, isActive: boolean) => Promise<ActionResult>;
onUpdate: (id: string, data: UpdateData) => Promise<ActionResult>;
updateItems: (items: Item[]) => Promise<void>;
onRefresh: () => Promise<void>;
}
const ActionsContext = createContext<ActionsContextType | null>(null);
export function ActionsProvider({ children, actions }: Props) {
return (
<ActionsContext.Provider value={actions}>
{children}
</ActionsContext.Provider>
);
}
export function useTableActions() {
const context = useContext(ActionsContext);
if (!context) {
throw new Error("useTableActions must be used within ActionsProvider");
}
return context;
}
// app/api/setting/items/route.ts
import { NextRequest } from "next/server";
import { withAuth, backendGet, backendPost } from "@/lib/fetch/api-route-helper";
export async function GET(request: NextRequest) {
const params = request.nextUrl.searchParams.toString();
return withAuth(token => backendGet(`/setting/items/?${params}`, token));
}
export async function POST(request: NextRequest) {
const body = await request.json();
return withAuth(token => backendPost('/setting/items/', token, body));
}
When creating a new entity page, generate files in this order:
fallbackData - SSR data for instant renderkeepPreviousData: true - Smooth paginationrevalidateOnMount: false - Trust SSR datarevalidateOnFocus: false - Reduce API callslib/fetch/client.ts - Client-side API callslib/fetch/server.ts - Server action API callslib/fetch/api-route-helper.ts - API route wrappersSee the references/ directory for detailed patterns:
page-pattern.md - SSR page structuretable-pattern.md - SWR table componentcontext-pattern.md - Actions contextapi-route-pattern.md - API routesfetch-pattern.md - Fetch utilitiestools
# Tasks Management Skill Background task management system using APScheduler for scheduling and Celery for distributed execution. ## When to Use This Skill Use this skill when asked to: - Set up background task processing - Create scheduled jobs with APScheduler - Implement Celery workers for task execution - Add job management endpoints - Configure task queues and retries ## Architecture Overview ``` ┌─────────────────────────────────────────────────────────────┐ │ FastA
development
Create Next.js data table pages with SSR initial load, SWR caching, and server-response-based UI updates. Use when asked to create a new data table page, entity management page, CRUD table, or admin list view. Generates page.tsx (SSR), table components, columns, context, actions, and API routes following a proven architecture with centralized reusable data-table component.
tools
# Fetch Architecture Skill Client and server-side fetch utilities for Next.js applications with API route proxying to FastAPI backends. ## When to Use This Skill Use this skill when asked to: - Set up fetch utilities for Next.js - Configure client-side API calls with auth refresh - Implement server-side data fetching - Create API route proxies to backend services - Handle authentication tokens across layers ## Architecture Overview ``` ┌──────────────────────────────────────────────────────
development
# FastAPI Template Skill Generate production-ready FastAPI CRUD modules following a proven single-session-per-request architecture. ## When to Use This Skill Use this skill when asked to: - Create a new FastAPI entity/module (router, service, repository, schemas) - Add CRUD endpoints to an existing FastAPI application - Generate data access layers following the repository pattern - Build REST APIs with SQLAlchemy and Pydantic ## Architecture Overview ``` ┌───────────────────────────────────