next-js/skills/skills/api-hook-wiring/SKILL.md
Create API service modules and wire them up with React Query hooks (useQuery, useMutation, useInfiniteQuery) for data fetching, mutations, and paginated lists. Use this skill whenever the user needs to connect a frontend feature to a backend API, add data fetching to a page or component, set up mutations for form submissions, create API service functions, add infinite scrolling, or wire up any client-server data flow. Trigger on: "fetch data", "API call", "connect to backend", "mutation", "infinite scroll", "paginated list", "data fetching", "useQuery", "useMutation", or when the user describes any feature that reads or writes data.
npx skillsauth add spuneiartur/claude-agent-specs api-hook-wiringInstall 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.
Connect frontend features to backend APIs using the project's Axios + React Query system. The project provides custom hooks that wrap React Query with automatic URL building, toast notifications, query invalidation, and router redirects.
API Service (api/*.js) → defines HTTP calls using axios instances
↓
Custom Hooks (hooks/*.js) → wraps React Query with project defaults
↓
Components → consume hooks for data + mutations
Create api/{resource}.js. Choose the right axios instance:
axiosAuth from @lib — for authenticated endpoints (admin, user-specific)axios from @lib — for public endpoints (no auth header)import { axiosAuth } from '@lib';
// Read operations
export const get{Resource} = (id) => axiosAuth.get(`/admin/{resources}/${id}`);
export const get{Resources} = (params) => axiosAuth.get('/admin/{resources}', { params });
// Write operations
export const create{Resource} = (data) => axiosAuth.post('/admin/{resources}', data);
export const update{Resource} = ({ id, data }) => axiosAuth.put(`/admin/{resources}/${id}`, data);
export const delete{Resource} = (id) => axiosAuth.delete(`/admin/{resources}/${id}`);
For public endpoints:
import { axios } from '@lib';
export const getPublic{Resources} = () => axios.get('/public/{resources}');
import { useQuery } from '@hooks';
// Fetch by ID (URL is both the endpoint and the cache key)
const { data: resource, status } = useQuery(`admin/{resources}/${id}`);
// Fetch with query params (options become URL query params)
const { data, status } = useQuery('admin/{resources}', { status: 'active', page: 1 });
How useQuery works internally:
query-string: stringifyUrl({ url, query: options })axiosAuth for internal URLs, plain axios for external URLs (starting with http)import { useInfiniteQuery } from '@hooks';
const { data, status, ...paginationProps } = useInfiniteQuery('admin/{resources}', options);
How useInfiniteQuery works internally:
per_page: 30options as query paramsgetNextPageParam from pageParams.hasNextdata.pages is an array of page arrays, data.pageParams has pagination metadataUse with table components:
<TableColumns pageParams={data?.pageParams} />
{status === 'loading' && <TableLoading name="{resources}" columns={columns} />}
{status === 'error' && <TableError name="{resources}" columns={columns} />}
{status === 'success' && (
<>
<TableSuccess name="{resources}" columns={columns} data={data} {...paginationProps} />
<LoadMoreOnClick {...paginationProps} />
</>
)}
import { useMutation } from '@hooks';
import { createResource } from '@api/resource';
const mutation = useMutation(createResource, {
invalidateQueries: 'admin/{resources}', // refetch list after mutation
successCallback: () => router.push('/admin/{resources}'), // redirect on success
// errorCallback: () => {}, // optional error handler
// redirectOnSuccess: '/admin/{resources}', // alternative to successCallback
});
// Trigger the mutation
const handleSubmit = async (data) => mutation.mutateAsync(data);
How useMutation works internally:
data.message, redirects, calls callbackerr.message, calls error callbackmutateAsync, isPending, isError, etc.)For update mutations, the API function receives { id, data }:
const mutation = useMutation(updateResource, { invalidateQueries: 'admin/{resources}' });
const handleSubmit = async (data) => mutation.mutateAsync({ id: resource._id, data });
For delete mutations:
const mutation = useMutation(deleteResource, { invalidateQueries: 'admin/{resources}' });
const handleDelete = async () => { await mutation.mutateAsync(id); };
Always handle all three states when using useQuery or useInfiniteQuery:
const { data, status } = useQuery(url);
{status === 'loading' && <LoadingComponent />}
{status === 'error' && <ErrorComponent />}
{status === 'success' && <SuccessComponent data={data} />}
The project has two axios instances in lib/:
| Instance | File | Auth | Use For |
|----------|------|------|---------|
| axiosAuth | lib/axios-auth.js | Bearer token from Redux store | Admin and user endpoints |
| axios | lib/axios.js | None | Public endpoints |
Both instances:
res.data via response interceptoraxiosAuth additionally handles 401 → token refresh → retry flowFor pages that need data at render time, use getServerSideProps:
export async function getServerSideProps(context) {
try {
const data = await publicApi.getResources();
return { props: { data } };
} catch {
return { props: { data: [] } };
}
}
For admin pages, combine with auth check:
export async function getServerSideProps(context) {
return await checkAuth(context);
}
| What | Import From |
|------|------------|
| useQuery, useInfiniteQuery, useMutation | @hooks |
| axiosAuth, axios | @lib |
| TableColumns, TableLoading, TableError, TableSuccess | @components/Tables |
| LoadMoreOnClick | @components/Buttons |
| checkAuth | @auth |
tools
Replace with description of the skill and when Claude should use it.
tools
Comprehensive website performance audit and optimization skill. Identifies and automatically fixes performance issues including image optimization, video compression, lazy loading, Core Web Vitals, bundle size, and rendering strategy. Uses Lighthouse (via CLI or MCP when available), ffmpeg for media processing, and the project's existing Image component with blur-up lazy loading. Use this skill whenever the user mentions: website speed, page load time, performance audit, Core Web Vitals, Lighthouse, optimize images, compress videos, lazy loading, LCP, CLS, FID, INP, slow website, speed up, performance optimization, image compression, video optimization, blur placeholder, WebP conversion, media audit, bundle size, or wants to improve their website's loading performance. Also trigger when the user says "my site is slow", "optimize for speed", "reduce load time", "improve performance", or asks about image/video optimization in any context.
tools
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
tools
Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.