- Home
- Skills
- Frontend & Web Apps
- Next.js 16 + React 19 Production Pack
Works with the AI Agents you already use
Next.js 16 + React 19 Production Pack
Seven agent skills and three CI-ready checks that make your AI agent ship Next.js 16 right: Cache Components, Server Actions security, Web Vitals, upgrades.
$24
Next.js 16 + React 19 Production Pack
Example session with this skill installed
We just turned on cacheComponents in our Next.js 16 notes app and the build fails. Fix it properly, not by making everything dynamic, and check the actions while you're at it.
Their code
import { cookies } from 'next/headers'
import { cacheTag } from 'next/cache'
import { db } from '@/lib/db'
import { addNote } from './actions'
export const dynamic = 'force-dynamic'
async function getNotes() {
'use cache'
cacheTag('notes')
const userId = (await cookies()).get('session')?.value ?? ''
return db.notes.listByOwner(userId)
}
export default async function NotesPage() {
const notes = await getNotes()
return (
<main>
<ul>
{notes.map((n) => (
<li key={n.id}>{n.title}</li>
))}
</ul>
<form action={addNote}>
<input name="title" />
<input type="hidden" name="ownerId" />
<button>Add</button>
</form>
</main>
)
}
'use server'
import { revalidateTag } from 'next/cache'
import { redirect } from 'next/navigation'
import { db } from '@/lib/db'
export async function addNote(formData: FormData) {
const data = Object.fromEntries(formData)
try {
await db.notes.create(String(data.ownerId), String(data.title))
revalidateTag('notes')
redirect('/notes')
} catch (e) {
console.error(e)
}
}
plus next.config.ts with cacheComponents: true and images.domains, and a middleware.ts that redirects /notes without a session cookie.
- Read your context and instructions
- Compiled the next js 16
next build stops at the first problem (Route segment config "dynamic" is not compatible with nextConfig.cacheComponents). The agent loads nextjs-production, runs the three checks, and gets the whole list at once:
$ node audit-upgrade.mjs .
next 16.4.0 -> target 16 (security data checked 2026-10-14)
WARN images-domains next.config.ts:5 images.domains is deprecated. Use images.remotePatterns with a pathname.
WARN middleware-deprecated middleware.ts:1 middleware.ts is deprecated in 16. Rename to proxy.ts and the function to proxy (codemod: middleware-to-proxy).
ERROR revalidate-tag-one-arg app/notes/actions.ts:11 revalidateTag(tag) needs a second argument in 16: revalidateTag(tag, 'max'), or updateTag(tag) in a Server Action.
1 error(s), 2 warning(s), 0 note(s)
$ node lint-cache.mjs .
Cache Components: on
WARN partial-prefetching-unset next.config.ts:1 cacheComponents is on but partialPrefetching is not set. Set partialPrefetching: true (Next.js 16.3+); unset logs a warning and behaves like false.
ERROR revalidate-tag-one-arg app/notes/actions.ts:11 revalidateTag() with one argument is deprecated and a type error in Next.js 16. Use revalidateTag(tag, 'max'), revalidateTag(tag, { expire: 0 }), or updateTag(tag) in a Server Action.
ERROR cache-runtime-api app/notes/page.tsx:11 cookies() inside "use cache" (getNotes()). Read it outside the cached scope and pass the value as an argument, or use "use cache: private".
WARN cache-no-life app/notes/page.tsx:9 "use cache" in getNotes() has no cacheLife(). The implicit default profile (revalidate 15m, expire never) applies; set the lifetime explicitly.
ERROR segment-config-cache-components app/notes/page.tsx:6 export const dynamic is not compatible with cacheComponents and fails the build. Delete it and move caching into 'use cache' scopes.
3 error(s), 2 warning(s), 0 note(s)
$ node check-server-actions.mjs .
Server Actions found: 1
WARN action-no-auth app/notes/actions.ts:7 Action addNote has no authentication call. Every action is a public POST endpoint: check the session inside it (or pass your helper with --auth).
WARN action-no-validation app/notes/actions.ts:7 Action addNote takes arguments but validates none of them. Parse every argument with a schema (zod safeParse) before use.
WARN action-form-entries app/notes/actions.ts:8 Action addNote uses Object.fromEntries(formData): it includes every client-sent field and $ACTION_ keys. Parse named fields with a schema.
ERROR navigation-in-try app/notes/actions.ts:12 redirect() inside try { } is caught by the catch block, so it never takes effect. Call it after the try/catch, or call unstable_rethrow(error) first in the catch.
1 error(s), 3 warning(s), 0 note(s)
It explains the three build blockers: dynamic is gone under Cache Components, cookies() cannot run inside 'use cache' (here it fails the prerender; inside a route that already renders per request the same mistake only fails under next start, after a green build), and one-argument revalidateTag no longer type-checks. Deleting 'use cache' and wrapping everything in <Suspense> would build, but would query the database on every request. It also flags what would have hurt in production: anyone can POST to addNote with any ownerId from the hidden field, and the redirect is swallowed by the catch, so the page never refreshes after a save. From nextjs-caching and nextjs-server-actions it rewrites both files: the session is read outside the cache and passed in as the key, the action takes the owner from the session, validates with zod, and uses updateTag for read-your-own-writes.
'use server'
import { z } from 'zod'
import { updateTag } from 'next/cache'
import { getSession } from '@/lib/auth'
import { db } from '@/lib/db'
const CreateNote = z.object({
title: z.string().trim().min(1, 'Title is required').max(120),
})
export type CreateNoteState = {
ok: boolean
errors?: { title?: string[] }
message?: string
}
export async function createNote(
_prev: CreateNoteState,
formData: FormData,
): Promise<CreateNoteState> {
const session = await getSession()
if (!session) return { ok: false, message: 'Sign in first.' }
const parsed = CreateNote.safeParse({ title: formData.get('title') })
if (!parsed.success) {
return { ok: false, errors: z.flattenError(parsed.error).fieldErrors }
}
await db.notes.create(session.userId, parsed.data.title)
updateTag(`notes-${session.userId}`)
return { ok: true, message: 'Saved.' }
}
import { Suspense } from 'react'
import { cacheLife, cacheTag } from 'next/cache'
import { getSession } from '@/lib/auth'
import { db } from '@/lib/db'
import { NoteForm } from './note-form'
export default function NotesPage() {
return (
<main>
<h1>Notes</h1>
<Suspense fallback={<p>Loading notes</p>}>
<UserNotes />
</Suspense>
</main>
)
}
async function UserNotes() {
const session = await getSession()
if (!session) return <p>Sign in to see your notes.</p>
const notes = await getNotes(session.userId)
return (
<>
<ul>
{notes.map((n) => (
<li key={n.id}>{n.title}</li>
))}
</ul>
<NoteForm />
</>
)
}
async function getNotes(userId: string) {
'use cache'
cacheLife('minutes')
cacheTag(`notes-${userId}`)
const notes = await db.notes.listByOwner(userId)
return notes.map(({ id, title, done }) => ({ id, title, done }))
}
NoteForm is the useActionState client form from nextjs-server-actions (field errors, pending state, aria-live message). getSession lives in a server-only module and reads the cookie with React.cache. The config gets partialPrefetching: true and images.remotePatterns: [new URL('https://images.example.com/products/**')]; middleware.ts becomes proxy.ts exporting proxy with the same matcher. Then it reruns everything:
$ node audit-upgrade.mjs . && node lint-cache.mjs . && node check-server-actions.mjs .
0 error(s), 0 warning(s), 0 note(s)
0 error(s), 0 warning(s), 0 note(s)
Server Actions found: 1
0 error(s), 0 warning(s), 0 note(s)
$ npx next build
- Cache Components enabled
- Partial Prefetching enabled
├ ◐ /notes
ƒ Proxy (Middleware)
All of the above was run on Next.js 16.4.0 with zod 4.6 (script output from a Windows run, path separators shown as /). In a production browser session, a whitespace-only title returned Title is required, a valid note appeared in the list in the same response with no reload, and a Server Action POST to /notes with a foreign Origin header was rejected by the framework's CSRF check. Finally it walks the nextjs-production pre-flight list and points out that NEXT_SERVER_ACTIONS_ENCRYPTION_KEY must be set before they scale past one container.
Connects securely to your tools. The creator never sees your data.
About this skill
Agents write a Next.js page fine. They get production wrong, because most of what they learned describes Next.js 13 to 15: export const dynamic = 'force-dynamic' next to cacheComponents: true (build error), cookies() inside 'use cache' (fails at request time, after the build passed), revalidateTag('posts') with one argument (deprecated and a type error), redirect() inside a try block (swallowed, the user never moves), Server Actions with no auth check because "the page is protected by middleware", whole database rows passed to Client Components, middleware.ts renamed to proxy.ts even though it needed the Edge runtime, priority on images that now wants preload, quality={80} that the 16 optimizer rejects with a 400, notFound() inside Suspense that quietly returns 200, and a Next.js 14 app left on a line that received no fixes for 2026's RCE and SSRF advisories.
This pack gives the agent current rules, checked against the docs bundled in next@16.4.0, npm, react.dev and GitHub security advisories, and proven in a real 16.4.0 app:
- nextjs-production: routing between skills, pre-flight checklist, current versions, the 2026 security floor, version boundaries from 15.0 to 16.4.
- nextjs-app-router: Server/Client boundaries, async
paramswithPageProps/LayoutProps/RouteContext, Suspense placement,error.tsxretry,catchError, parallel routes and 16.4 strict matching,proxy.ts, route handlers, metadata, React 19.3 (ViewTransition, Fragment refs,browser()). - nextjs-caching: Cache Components,
use cacheand itsprivate/remotevariants,cacheLifeprerender thresholds,updateTagvsrevalidateTag(tag, 'max')vsrefresh, a verified webhook handler,partialPrefetching,instant,ensureStatic, and a migration table from the old segment configs. - nextjs-server-actions:
useActionStateforms with zod 4, auth and ownership inside every action, mass assignment, DAL withserver-only, the CSRF origin check tested with forged and missingOriginheaders,allowedOrigins, encryption keys, deployment skew. - nextjs-performance: LCP/INP/CLS diagnosis,
next/image16 defaults with verified 400s,next/font,next/script,next analyze, React Compiler, field vitals reporting. - nextjs-migration: every breaking change from 14 to 15 to 16 with its codemod, Turbopack and custom webpack, removed config, Pages Router to App Router mapping.
- nextjs-self-hosting: standalone output and Docker (verified), env vars at build vs runtime, cache handlers and multi-instance tag coordination, CDN headers, nginx streaming, CSP with and without nonces, advisories for self-hosters.
Three zero-dependency Node scripts, each with --json and a non-zero exit for CI: audit-upgrade.mjs (security floor, versions, removed config, middleware, sync request APIs, image props, parallel defaults), lint-cache.mjs (runtime APIs in cached scopes, missing cacheLife, segment config conflicts, one-argument revalidateTag, updateTag outside actions), and check-server-actions.mjs (missing auth and validation, raw records returned, Object.fromEntries(formData), redirect in try, invalid 'use server' exports, secret env reads in client files).
Works with Claude Code (skills folder or plugin), Codex, Gemini CLI and Cursor. Plain Agent Skills format.
Versions: Next.js 16.4 (notes back to 15.0, migration from 14), React 19.3, React Compiler 1.0, eslint-config-next 16.4. Reviewed after every Next.js minor release and every new next or React Server Components advisory.
How to use
Skills on Agensi run inside your AI agent. Copy the prompt, paste it into your agent, and it connects to Agensi and installs this skill for you. If a payment is needed, your agent shows it to you first.
Reviews
No reviews yet
Be one of the first to try it. Every listed skill passes our trust checks below.
Security scanned
Passed our 8-point scan before listing
Fresh listing
Recently published to Agensi
Money-back guarantee
Doesn't do what its page promises? You get your money back.
Trust & safety
Security scanned
Verified clean 6 days ago
- Passed all security checks, Safe to install
Requires