npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zvk/next-kit

v0.2.3

Published

Next App Router adapters for server actions, cache invalidation, form data, and route handlers.

Readme

@zvk/next-kit

Next App Router adapters for server actions, cache invalidation, FormData parsing, and route handlers.

import { formDataToObject } from "@zvk/next-kit";
import {
  createMappedNextMutationAction,
  createNextMutationAction,
  parseFormDataActionInput,
  parseZodFormDataActionInput,
  createPassthroughNextMutationAction,
  createPassthroughNextMutationActionFactory,
  createZodPassthroughNextMutationAction,
  createZodPassthroughNextMutationActionFactory,
  type ParseFormDataActionInput,
  type ParseZodFormDataActionInput,
} from "@zvk/next-kit/actions";
import { createNextRouteHandler, jsonErrorResponse, parseJsonRequestBody, parseZodJsonRequestBody, readJsonRequestBody, readRequestBody } from "@zvk/next-kit/route-handlers";
import { captureRedirectPath, createJsonRequest, createNextNavigationRedirectMock } from "@zvk/next-kit/test-utils";
import { buildAppUrl, safeNextPath } from "@zvk/next-kit/url";

The package keeps its runtime helpers narrow. It depends on @zvk/contracts, @zvk/feature-kit, @zvk/server-kit, server-only, and a Next 15 || 16 peer, but it does not add React components, React Query, Supabase, Drizzle, or app-specific policy.

See ../../docs/package-boundary-matrix.md for the package-family runtime boundary matrix. The actions, cache, and route-handlers subpaths are server-only; the root export stays browser-safe.

@zvk/next-kit/actions intentionally keeps both layers of action helpers. Use createNextMutationAction when you want the canonical contract ActionResult wrapper from @zvk/contracts, and use the mapped or passthrough helpers when the app owns the flattened result envelope or needs app-owned wrapper output.

Use @zvk/next-kit/cache for path and tag cache invalidation in Next App Router server code. Path targets call revalidatePath; tag targets call revalidateTag. The package expects the Next 15 or 16 next/cache APIs.

Use @zvk/next-kit/url for framework-safe URL construction, next-path sanitization, and search-param appending. Redirect destinations and route names remain application policy. safeNextPath accepts unknown external values, including form-derived values, and falls back unless the input is a same-origin local path.

Use createMappedNextMutationAction when an application owns a flattened action result envelope and needs to map shared contract success/error results into that shape.

Use parseFormDataActionInput when a redirecting or custom server action needs to convert FormData and validate it through a schema adapter while keeping redirect destinations, auth policy, and product copy in the app. Use parseZodFormDataActionInput when the app already validates with Zod-like schemas and should not compose the schema adapter locally. Use ParseFormDataActionInput or ParseZodFormDataActionInput for app-local wrappers that preserve package parser input typing while adding app-owned redirect policy or response mapping. Pass values for server-owned fields, such as organization IDs or fixed return paths, that must override any submitted form values before validation.

Use createPassthroughNextMutationAction when run already returns the application-owned envelope and package-owned validation, authorization, dependency, or revalidation failures should be mapped into that same envelope. Use createZodPassthroughNextMutationAction when the caller already owns a Zod-like schema and should avoid local schema-adapter glue. When passing revalidate, also pass shouldRevalidate so app-level error envelopes do not accidentally invalidate cache targets. Use createPassthroughNextMutationActionFactory when an app already owns schema adapters and wants to bind its package-error mapper and default app-envelope revalidation predicate once. Use createZodPassthroughNextMutationActionFactory when an app wants to bind its package-error mapper and default revalidation predicate once, then create many app-envelope actions without repeating that wiring.

const createAppMutation = createPassthroughNextMutationActionFactory<
  AppActionResult<Project>,
  AppActionResult<Project>
>({
  mapError: actionErrorFromContractError,
  shouldRevalidate: (result) => result.status === "ok",
});

export const saveProject = createAppMutation({
  schema: projectInputSchemaAdapter,
  getContext: requireProjectContext,
  run: saveProjectInput,
  revalidate: ["/projects"],
});

Keep public action envelopes, redirect targets, auth/session policy, product copy, and route-specific revalidation predicates in the application wrapper.

Use readRequestBody when a custom Route Handler needs content-type-aware JSON, text, form, or empty body parsing while receiving malformed or unsupported body failures as contract validation errors. Use parseJsonRequestBody for streaming or custom-response Route Handlers that cannot use createNextRouteHandler but still need shared JSON parsing and schema validation before returning an app-owned response. Use parseZodJsonRequestBody when the route already owns a Zod-like schema. Use readJsonRequestBody only when the route needs raw body control before app-owned validation. Use jsonResponse, jsonErrorResponse, and jsonResultResponse for small custom JSON Route Handler responses. Pass mapper functions for app-owned envelopes, product copy, and error details; the package only owns response serialization, status, and headers.

Use createJsonRequest from @zvk/next-kit/test-utils for App Router tests that need deterministic JSON Request objects, including raw malformed bodies. Use createNextNavigationRedirectMock and captureRedirectPath when testing redirecting actions that import next/navigation. They let tests mock redirects without adding a dependency on a specific test runner. Use createRedirectTestDouble only when the redirect function is injected directly.

Repo Skill

Use .codex/skills/use-zvk-next-kit/SKILL.md when maintaining this package.

See ../../docs/package-boundary-matrix.md for the browser-safe and server-only subpaths.