
Nextjs Data Fetching
Implement Next.js App Router fetch caching with ISR, on-demand revalidateTag/revalidatePath, cache tags, and no-store patterns your agent can apply consistently.
Overview
Next.js Data Fetching is an agent skill for the Build phase that teaches App Router fetch caching, ISR, tag-based invalidation, and on-demand revalidation patterns.
Install
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill nextjs-data-fetchingWhat is this skill?
- Time-based revalidation (ISR) via fetch next.revalidate intervals
- On-demand revalidation with revalidateTag and revalidatePath in Route Handlers or Server Actions
- Stable cache tags for selective invalidation across readers
- Guidance to opt out of caching for highly dynamic data
- Coordinates read paths and write-time invalidation with predictable tags
Adoption & trust: 1k installs on skills.sh; 271 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are building Next.js pages but your agent keeps fetching uncached, over-cached, or stale data because ISR, tags, and revalidate routes are inconsistent.
Who is it for?
Indie builders on Next.js App Router who need agent-aligned recipes for ISR, revalidateTag, and coordinated cache tags.
Skip if: Pages Router-only projects, static sites with zero server fetch, or teams that need database query optimization instead of Next cache APIs.
When should I use this skill?
Implementing or refactoring Next.js App Router data fetching and you need ISR, tags, or on-demand revalidation wired correctly.
What do I get? / Deliverables
Your Next.js read and write paths share clear revalidate intervals, stable cache tags, and Route Handler invalidation so data stays fresh after updates.
- Fetch helpers with revalidate and tags configured
- Revalidation Route Handler or Server Action snippets
- Documented cache opt-out for dynamic routes
Recommended Skills
Journey fit
Data fetching and cache strategy is core product construction in the Build phase before you optimize ship-time perf audits. Frontend subphase is the canonical shelf because examples center on fetch options in Server Components and Route Handlers.
How it compares
Skill package for Next.js cache semantics—not an MCP server and not a substitute for full backend API design.
Common Questions / FAQ
Who is nextjs-data-fetching for?
Solo builders and small teams implementing Next.js App Router server data loading who want consistent caching and revalidation in agent-generated code.
When should I use nextjs-data-fetching?
Use it during Build while wiring fetch in server components, adding ISR intervals, or creating revalidate Route Handlers after form submissions or CMS updates.
Is nextjs-data-fetching safe to install?
It is documentation-style procedural knowledge without inherent network side effects; review the Security Audits panel on this page before adding any third-party skill pack to your agent.
SKILL.md
READMESKILL.md - Nextjs Data Fetching
# Caching and Revalidation Strategies ## Time-based Revalidation (ISR) Use time-based revalidation when stale data is acceptable for a bounded period. ```tsx async function getPosts() { const res = await fetch('https://api.example.com/posts', { next: { revalidate: 60, }, }); return res.json(); } ``` Choose the revalidation interval based on how often the data changes. ## On-Demand Revalidation Use Route Handlers or Server Actions with `revalidateTag()` or `revalidatePath()` when data should refresh immediately after a write. ```tsx // app/api/revalidate/route.ts import { revalidateTag } from 'next/cache'; import { NextRequest } from 'next/server'; export async function POST(request: NextRequest) { const tag = request.nextUrl.searchParams.get('tag'); if (tag) { revalidateTag(tag); return Response.json({ revalidated: true }); } return Response.json({ revalidated: false }, { status: 400 }); } ``` Keep invalidation tags stable and descriptive so read and write paths stay coordinated. ## Tag Cached Data for Selective Invalidation Attach cache tags when the same data source is read in multiple places. ```tsx async function getPosts() { const res = await fetch('https://api.example.com/posts', { next: { tags: ['posts'], revalidate: 3600, }, }); return res.json(); } ``` Use a small set of predictable tags instead of dynamically generating unnecessary tag variants. ## Opt Out of Caching Disable caching for highly dynamic or user-specific data. ```tsx async function getRealTimeData() { const res = await fetch('https://api.example.com/data', { cache: 'no-store', }); return res.json(); } export const dynamic = 'force-dynamic'; ``` Use `no-store` intentionally because it trades performance for freshness. ## Cache Selection Checklist - Use ISR when the page can tolerate bounded staleness. - Use tags when a mutation needs to refresh multiple consumers. - Use `no-store` for real-time, user-specific, or security-sensitive responses. - Avoid sharing cache entries across different user contexts. ## Example: Blog Page with ISR **Input:** Create a blog page that fetches posts and updates every hour. ```tsx // app/blog/page.tsx async function getPosts() { const res = await fetch('https://api.example.com/posts', { next: { revalidate: 3600 }, }); return res.json(); } export default async function BlogPage() { const posts = await getPosts(); return ( <main> <h1>Blog Posts</h1> {posts.map((post) => ( <article key={post.id}> <h2>{post.title}</h2> <p>{post.excerpt}</p> </article> ))} </main> ); } ``` **Output:** The page is cached and revalidated every hour. # Client-Side Data Fetching Use client-side libraries when the component needs browser-driven refresh, optimistic interactions, or local cache coordination. ## SWR Integration Choose SWR for lightweight refresh and revalidation behavior. Install with `npm install swr`. ```tsx 'use client'; import useSWR from 'swr'; const fetcher = (url: string) => fetch(url).then((r) => r.json()); export function Posts() { const { data, error, isLoading } = useSWR('/api/posts', fetcher, { refreshInterval: 5000, revalidateOnFocus: true, }); if (isLoading) return <div>Loading...</div>; if (error) return <div>Failed to load posts</div>; return ( <ul> {data.map((post: any) => ( <li key={post.id}>{post.title}</li> ))} </ul> ); } ``` Use SWR when the data model is simple and the main need is background refresh. ## React Query Integration Choose React Query when you need structured query keys, richer cache invalidation, or advanced mutation flows. Install with `npm install @tanstack/react-query`. ```tsx // app/providers.tsx 'use client'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useState } from 'react'; export function Providers({ children }: {