ccppccpp home

Profiles

Next.js 16

Next.js 16.4 apps (App Router, Pages Router, both) without pre-16 APIs, with explicit server/client and cache boundaries, package-manager-owned dependencies and evidenced completion. Rule IDs B, T, V, S, R, C, X, A, U, Q; NEED TO blocks.

Set this profile

ccpp cpo profile set nextjs-16

Inside Claude Code, prefix the command with ! to run it in the session. Downloading a profile needs a Builder or Team plan; listing them does not.

Policies

123 policies, grouped by what they guard.

Secrets & private data 3

Credentials, keys and personal data stay out of files, logs, commands and the conversation.

  • s03-private-env-in-client

    S03 · Client Components read only NEXT_PUBLIC_ environment variables (and NODE_ENV)

  • x05-public-secrets

    X05 · No secret-named variable is exposed to the browser (NEXT_PUBLIC_ prefix, next.config env)

  • x10-header-forwarding

    X10 · Proxy and route handlers do not copy request headers into the response

Authentication & authorization 4

Who may do what, from roles, privileges and permissions to CSRF, CORS and verified tokens.

  • x02-unguarded-actions-advice

    X01/X02 · Outside declared scopes, warns about data-writing actions and handlers without a visible guard

  • x02-unguarded-actions

    X01/X02 · Server Actions and mutating route handlers that write data call an authorization guard themselves

  • x09-unverified-webhook

    X09 · Webhook route handlers verify the provider signature before acting

  • x12-layout-only-auth

    X12 · An auth check added to a layout is not the only protection of the pages and actions below it

Untrusted input 3

Requests, downloads and tool output are validated before they reach SQL, a shell, eval or a deserializer.

  • x03-unvalidated-input

    X03 · Untrusted input (FormData, request bodies) is validated before it reaches a data write

  • x08-raw-sql

    X08 · No SQL text built from interpolated or concatenated values

  • x08-unsanitized-html

    X08 · HTML injected with dangerouslySetInnerHTML goes through a sanitizer (warning: the source may be trusted)

Weakened checks 3

Suppressions, disabled lint or CI steps and relaxed strictness need a reason or the user's approval.

  • a12-suppressions

    A12 · No blanket type-check or lint suppression (@ts-nocheck, @ts-ignore, rule-less eslint-disable)

  • a12-tsconfig-strictness

    A12 · tsconfig strictness is not weakened (strict, noImplicitAny, strictNullChecks)

  • a12-weakened-safeguards

    A12/U09 · The user confirms switching off build type errors or relaxing image security in next.config

Type safety 1

No escapes from the type checker (any, unchecked casts, non-null assertions) and explicit contracts.

  • t09-handwritten-route-types

    T09 · Route prop types come from `next typegen` (global PageProps/LayoutProps/RouteContext), not hand-written copies

Performance & resource bounds 2

Timeouts, bounded retries and fan-out, reused clients, closed resources, no N+1 queries.

  • q08-manual-memo-with-compiler

    Q08 · With reactCompiler on, new manual memoization needs a measured reason

  • u01-sequential-awaits

    U01 · Independent awaited reads start together instead of waiting for each other

Architecture & boundaries 7

Declared layers and dependency directions, no import cycles, small modules, explicit dependencies.

  • a01-import-cycle

    A01 · A new import does not close a cycle of value imports (up to three modules)

  • a02-layer-rules

    A02 · Imports respect the project's declared dependency directions (layerRules)

  • a03-route-entry-size

    A03 · Route entries and action modules stay within the project's declared size (maxRouteEntryLines)

  • a04-data-access-outside-dal

    A04 · Data clients are imported only by the declared data access layer (dataAccessPaths)

  • a07-client-export-star

    A07 · A 'use client' module re-exports named components, never `export *`

  • a07-mixed-barrel

    A07 · A barrel does not re-export client components together with server-only modules

  • a08-module-request-state

    A08 · Server modules keep no request or user state in mutable module-level variables

HTTP & APIs 1

Request and response contracts, schemas, status codes, error bodies and published API surfaces.

  • x06-mutation-in-get-or-render

    X06/X07 · GET handlers and Server Component renders write no data and no cookies

Caching 8

Cache scopes, lifetimes and invalidation stated explicitly.

  • c02-use-cache-contract

    C02 · 'use cache' needs cacheComponents enabled and an async function (every export of a file-level 'use cache' module)

  • c03-segment-config-with-cache-components

    C03/C04 · With Cache Components on, no dynamic/revalidate/fetchCache/dynamicParams segment config nor edge runtime

  • c05-request-apis-in-cache

    C05/C06/C07 · A 'use cache' scope reads no request API or identity and does not inspect pass-through children

  • c08-cache-lifetime

    C08 · A new 'use cache' scope states its freshness (cacheLife) or its invalidation (cacheTag)

  • c09-revalidate-tag-profile

    C09 · revalidateTag is called with its cache-life profile (the one-argument form is deprecated)

  • c10-action-only-cache-apis

    C10 · updateTag() and refresh() from next/cache are called from Server Actions only

  • c14-use-cache-on-route-handler

    C14 · 'use cache' sits in a helper called by a GET handler, not in the HTTP export itself

  • c17-cache-components-segment-options

    C17 · ensureStatic, instant and prefetch segment exports are used only with cacheComponents (and never prefetch = 'auto')

Framework conventions 30

Routing, server and client boundaries, hooks and plugins the way the framework expects them.

  • b03-architecture-choices

    B03 · The user confirms changing the app's declared rendering, output, bundler and routing choices in next.config

  • c13-use-search-params-page

    C13 · A client page does not read useSearchParams() at its top level (prerendering needs a Suspense boundary)

  • q06-static-export-features

    Q06 · With output: 'export', code uses no server-only feature (actions, proxy, request APIs, non-GET handlers, optimized images)

  • q07-ephemeral-filesystem

    Q07 · Route handlers and Server Actions do not use the local filesystem as storage

  • r01-route-file-exports

    R01 · page, layout and route files export only what their convention allows (and pages/layouts a default component)

  • r02-root-layout-document

    R02 · A root layout renders <html> and <body>; nested layouts never do

  • r03-page-route-conflict

    R03 · One owner per URL: no page and route in one segment, no App and Pages route for one path

  • r03-route-group-collision

    R03 · Route groups and slots never give one URL two pages or handlers

  • r04-route-handler-contract

    R04 · App Router route handlers use Web Request/Response, not the Pages API contract

  • r05-proxy-matcher-static

    R05 · The proxy/middleware matcher is a literal Next.js can analyze at build time

  • r06-proxy-without-matcher

    R06 · A proxy states which requests it intercepts (a matcher scoping out assets and images)

  • r07-redirect-in-try

    R07 · redirect()/notFound()/forbidden()/unauthorized() are not swallowed by a try/catch

  • r08-error-boundaries

    R08 · error files are Client Components; global-error also renders <html> and <body>

  • r10-server-exports-in-client

    R10 · Client Components export no metadata or route segment config (they only work in Server Components)

  • s01-directive-placement

    S01 · 'use client' / 'use server' sit in the module's directive prologue, spelled exactly, never both

  • s02-async-client-component

    S02 · Components in a 'use client' module are synchronous functions

  • s03-server-code-in-client

    S03 · Client Components import no server-only module, database client or Node.js built-in (followed through aliases and re-exports)

  • s04-server-only-marker

    S04 · Modules holding data access or secrets import 'server-only'

  • s05-client-route-entry

    S05 · A page or layout becomes a Client Component only for a reason (smallest client boundary)

  • s06-handlers-in-server-component

    S06 · Server Components pass no event handler to host elements (functions cannot cross to the client)

  • s07-server-component-in-client

    S07 · Client Components receive Server Components as children/props instead of importing them

  • s08-browser-globals-in-render

    S08 · Code that also renders on the server reads no browser global during module init or render

  • s09-ssr-false-in-server

    S09 · next/dynamic with `ssr: false` is declared inside a Client Component

  • s10-use-server-exports

    S10 · A 'use server' module exports only async functions; Client Components define no inline Server Action

  • s11-client-hooks-in-server-component

    S11 · Server route entries call no client-only hook (state, effects, context, navigation hooks)

  • t11-dev-server-foreground

    T11 · Long-running dev/start servers run in the background, never blocking the Bash tool

  • u02-server-self-fetch

    U02 · Server code calls the data function directly instead of fetching its own Route Handler

  • u03-actions-as-queries

    U03 · Client Components read data with server reads or client fetching, not Server Actions called from Effects

  • u04-ad-hoc-client-fetching

    U04 · Client data fetching reuses the project's data library instead of fetch-in-useEffect

Versions & deprecated APIs 31

Code matches the installed version, without removed, renamed or deprecated APIs.

  • b01-installed-version

    B01/B02 · At session start, Claude learns the installed Next.js version and where its version-matched docs are

  • b02-agents-managed-block

    B02 · The user confirms removing or rewriting the Next.js-managed block of AGENTS.md

  • b02-docs-before-code

    B02 · Before its first Next.js-specific change of a session, Claude is pointed at the bundled docs (once)

  • b02-docs-ledger

    B02 · Records that Claude read the version-matched docs in node_modules/next/dist/docs

  • t08-codemod-markers

    T08 · Codemod markers (@next-codemod-error, UnsafeUnwrapped casts) are resolved before the turn ends (once per stop)

  • t12-obsolete-next-packages

    T12 · No package that Next.js replaced with a built-in (@next/font, next-transpile-modules, next-images, @zeit/next-*…)

  • t13-legacy-eslintrc

    T13 · ESLint is configured with a flat eslint.config.* (what eslint-config-next 16 ships), not a new .eslintrc

  • v02-sync-request-apis

    V02 · cookies(), headers(), draftMode(), params and searchParams are awaited (or use()d) before their values are read

  • v03-metadata-image-id

    V03 · Metadata image and sitemap generators await their `id` (and image `params`); generateImageMetadata keeps sync params

  • v04-pages-apis-in-app

    V04 · App Router code imports no Pages Router API (next/router, next/head, next/document, data fetching exports); Pages code no next/headers

  • v05-next-lint-command

    V05 · No removed `next lint` command or `next build --no-lint` flag

  • v05-next-lint-scripts

    V05 · package.json scripts drop the removed `next lint` and `next build --no-lint`

  • v06-runtime-config

    V06 · No import of the removed next/config (getConfig)

  • v07-experimental-ppr-export

    V07 · No `experimental_ppr` route segment export (removed in Next.js 16)

  • v07-removed-config-options

    V05/V06/V07/V12/C15 · next.config holds no option removed by Next.js 16 or earlier majors (eslint, runtime config, PPR flags, AMP…) and no partialPrefetching without cacheComponents

  • v08-moved-config-options

    V08/V13/B06/C16 · next.config uses the stable location of moved options (turbopack, reactCompiler, adapterPath, proxy names, remotePatterns…), recorded experiments, explicit partialPrefetching

  • v08-stabilized-apis

    V08 · next/cache uses stable names (cacheLife, cacheTag); no removed unstable_rootParams

  • v09-webpack-under-turbopack

    V09 · A custom webpack config is not silently left behind by the default Turbopack build

  • v10-proxy-runtime

    V10 · proxy files set no runtime (Proxy always runs on Node.js)

  • v11-middleware-rename-command

    V11 · Migrating middleware to proxy goes through the official codemod, not a bare rename

  • v11-middleware-to-proxy

    V11 · New request interception uses proxy, never both proxy and middleware entries

  • v13-legacy-image-api

    V13 · next/image code uses the 16.x API: no next/legacy/image, priority or onLoadingComplete

  • v14-argv-phase

    V14 · next.config detects the phase with the phase argument or NODE_ENV, not process.argv

  • v15-parallel-slot-default

    V15 · Every parallel route slot (@slot) touched this turn has a default file (once per stop)

  • v16-build-metrics

    V16 · Build-size reasoning does not rely on the removed `size` / `First Load JS` columns of next build

  • v17-next-export

    V17 · Static export is `output: 'export'` + `next build`, never the removed `next export`

  • v18-router-object-members

    V18 · The App Router's useRouter() object is used without the Pages Router members (pathname, query, events…)

  • v20-legacy-packages

    V20 · No package or import that Next.js or React replaced (@next/font, next/amp, react-dom render/hydrate, react-dom/test-utils, useFormState)

  • v21-request-geo-ip

    V21 · Proxy and route handlers read no removed NextRequest.geo / NextRequest.ip

  • v22-edge-runtime

    V22 · Route segments keep the default Node.js runtime: no new deprecated `runtime = 'edge'` / 'experimental-edge'

Configuration 1

Settings read once at a boundary, validated, with units and without unsafe defaults.

  • x11-public-env-dynamic

    X11 · Browser code reads NEXT_PUBLIC_ variables literally (process.env.NEXT_PUBLIC_X), never by dynamic lookup

UI & styling 6

Markup, styles, images and accessibility of web interfaces.

  • a09-effect-derived-state

    A09 · Render-derived values are computed, not mirrored into state by an Effect

  • u06-keys-and-cleanup

    U06 · List keys are stable and Effects that subscribe clean up after themselves

  • u07-image-contract

    U07 · next/image elements have alt, intrinsic size or fill, and a configured remote source

  • u08-image-loading

    U08 · Image qualities are configured and preloading is reserved to the above-the-fold image

  • u10-framework-facilities

    U10 · Pages use next/image, next/script, next/font and the Metadata API instead of raw <img>, <script>, font links and <head>

  • u10-script-contract

    U10 · next/script inline scripts have an id; beforeInteractive scripts live in the root layout

Dependencies & toolchain 13

Packages change through the package manager, lockfiles stay consistent and the project's tools are used.

  • t01-new-manifest

    T01/T02 · A new package.json comes from create-next-app or `npm init`, and gets its dependencies from the package manager

  • t02-hand-written-manifest

    T02 · A new package.json without dependencies is initialized with the package manager

  • t03-manual-dependency-edit

    T03 · Dependencies change through the package manager (add/remove/update), never by editing package.json by hand

  • t03-package-manager-call

    T03/T06 · Records the tool calls that run a package manager (they may rewrite package.json and lockfiles)

  • t04-version-lookups

    T04 · Registry version lookups are not a step before installing

  • t04-version-pins

    T04 · Packages are installed by name: no guessed exact version, no --save-exact without a reason

  • t05-package-manager

    T05 · Dependencies are installed with the project's package manager (packageManager field, lockfile)

  • t05-second-lockfile

    T05 · No second lockfile next to another package manager's lockfile

  • t06-hand-edited-lockfile

    T06 · Lockfiles are written by the package manager only (no hand edit, no script rewriting them)

  • t06-stale-lockfile

    T06 · A turn that changes package.json dependencies also updates the lockfile next to it (once per stop)

  • t07-ci-frozen-install

    T07 · CI and image builds install from the lockfile (npm ci, frozen/immutable installs)

  • t08-upgrade-via-codemod

    T08 · Next.js upgrades go through `next upgrade` / the upgrade codemod, not a bare install

  • t10-forced-installs

    T10 · Dependency conflicts are repaired, not masked with --force, --legacy-peer-deps or broad overrides

Generated files 1

Build outputs, generated code and tool-owned files are regenerated, never edited by hand.

  • b07-generated-files

    B07 · Generated Next.js output (.next/, next-env.d.ts, out/) is regenerated, never edited

Tests 1

Tests assert behavior, stay deterministic and are not removed or skipped silently.

  • q04-async-server-component-unit-test

    Q04 · Unit tests do not render async Server Components (Vitest/Jest cannot); test them end to end

Completion evidence 8

A turn ends with its checks run and passing; claims of success need proof after the last edit.

  • a11-placeholders

    A11 · New placeholders (TODO, not-implemented stubs) are flagged before completion

  • a11-truncation-markers

    A11 · Written code contains no elision marker standing for code that is not there (// ... existing code ...)

  • c19-default-caching-claims

    C19 · Final messages do not claim that fetch or GET handlers are cached by default (they are not since Next.js 15)

  • nx-turn-baseline

    Records the work tree when a prompt starts: the baseline of the Next.js end-of-turn checks (T06, V15, Q01–Q03)

  • q-evidence-ledger

    Q01–Q03/Q09 · Records, per session, Claude's edits and the lint, typecheck, build and test runs that succeeded after them

  • q01-new-type-errors

    Q01 · A turn adds no TypeScript errors to the changed files or their importers (language server, once per stop)

  • q02-required-checks

    Q01–Q03 · A turn that changed app code ends only after the configured lint, typecheck and build succeeded on the final files (once per stop)

  • q09-completion-claims

    Q09 · A final message claiming passing lint, types, build or tests needs a successful run after Claude's last edit