Provides setup and API documentation for managing URL query state in Next.js projects using nuqs.

Install

mkdir -p .claude/skills/nuqs-marlanperumal && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/12317" && unzip -o skill.zip -d .claude/skills/nuqs-marlanperumal && rm skill.zip

Installs to .claude/skills/nuqs-marlanperumal

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Install: `just add-web-dep nuqs`
32 chars · catalog descriptionno explicit “when” trigger
Beginner

Key capabilities

  • Sync component state with URL query parameters
  • Parse query parameters as various types (integer, string, boolean)
  • Batch URL writes for multiple parameter updates
  • Set default values for query parameters
  • Configure history and scroll behavior for URL changes
  • Use `parseAsJson` for complex nested data

How it works

The skill provides hooks and parsers to synchronize component state with URL query parameters. It allows defining single or multiple parameters, parsing them into various types, and configuring URL update behavior.

Inputs & outputs

You give it
Component state, user interactions, URL query parameters
You get back
Updated URL query parameters, component state reflecting URL, parsed query values

When to use nuqs

  • Managing search filters in URL
  • Syncing state with query params
  • Handling URL state in Next.js
  • Parsing URL search parameters

About this skill

nuqs — URL Query State (v2.x, Next.js App Router)

Setup

Install: just add-web-dep nuqs

Wrap the root layout body with NuqsAdapter (server component, no 'use client' needed):

// apps/web/src/app/layout.tsx
import { NuqsAdapter } from 'nuqs/adapters/next/app'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <NuqsAdapter>{children}</NuqsAdapter>
      </body>
    </html>
  )
}

Core API

Single param

import { useQueryState, parseAsInteger } from 'nuqs'

const [page, setPage] = useQueryState('page', parseAsInteger.withDefault(1))

Multiple params (preferred — batches URL writes)

import { useQueryStates, parseAsString, parseAsInteger, parseAsStringLiteral } from 'nuqs'

const [params, setParams] = useQueryStates(
  {
    mode: parseAsStringLiteral(['crosstab', 'trend'] as const).withDefault('crosstab'),
    ds: parseAsInteger,   // null when absent
    q: parseAsString,     // null when absent
  },
  { history: 'replace', scroll: false }
)

// Partial update — only specified keys change
setParams({ mode: 'trend' })

Built-in Parsers

ParserTypeNotes
parseAsStringstring | nullno-op, any value
parseAsIntegernumber | nullparseInt base 10
parseAsFloatnumber | nullparseFloat
parseAsBooleanboolean | null
parseAsStringLiteral(['a','b'] as const)'a' | 'b' | nullvalidates against list
parseAsArrayOf(parseAsString)string[] | nullcomma-separated by default
parseAsJson<T>((v) => v as T)T | nullJSON encode/decode; requires a validator function (breaking change in newer nuqs)
parseAsIsoDateTimeDate | nullISO 8601

All parsers support .withDefault(value) to replace null with a default, and .withOptions({...}) for per-param options.

Options

OptionDefaultDescription
history'replace''replace' or 'push' (adds browser history entry)
scrollfalsescroll to top on change
shallowtrueset false to notify server (re-renders Server Components)
clearOnDefaulttrueomit param from URL when value equals default

Options can be set globally via <NuqsAdapter defaultOptions={...}> or per-hook as the second argument.

Project Convention

This project wraps a QueryConfig domain type in a thin hook (useAnalyticsState) that maps between QueryConfig and flat URL params. Keep this pattern: domain types stay in analytics-types.ts, URL mapping lives in the hook.

URL key shorthand — use short keys (ds, col, bd, mt, md) via useQueryStates with the urlKeys option, or just name them directly. Short keys keep URLs legible.

Complex nested data (e.g. filters with levels) — use parseAsJson<T>((v) => v as T) rather than flattening. The validator is required; a simple cast is fine if you trust the URL source.

Storybook

Use NuqsTestingAdapter from nuqs/adapters/testingnot the next/app adapter. The next/app adapter calls useRouter() internally and throws invariant expected app router to be mounted because Storybook doesn't mount the Next.js App Router. NuqsTestingAdapter is a self-contained in-memory URL store that works in any non-router environment.

// AnalyticsPage.stories.tsx
import { NuqsTestingAdapter } from "nuqs/adapters/testing"

const meta = {
  decorators: [
    (Story) => (
      <NuqsTestingAdapter>
        <Story />
      </NuqsTestingAdapter>
    ),
  ],
} satisfies Meta<typeof MyComponent>

Testing

Mock only useQueryStates, let real parsers run (they're pure functions):

vi.mock('nuqs', async (importActual) => {
  const actual = await importActual<typeof import('nuqs')>()
  return { ...actual, useQueryStates: vi.fn() }
})

beforeEach(() => {
  vi.mocked(useQueryStates).mockReturnValue([defaultParams, mockSetP])
})

When not to use it

  • When not using Next.js App Router
  • When using `useRouter()` in Storybook without `NuqsTestingAdapter`

Limitations

  • Requires `NuqsAdapter` to wrap the root layout body
  • Requires `NuqsTestingAdapter` for Storybook environments
  • The `parseAsJson` validator is required for complex nested data

How it compares

This skill offers a structured and type-safe way to manage URL query state in Next.js App Router applications, simplifying the synchronization of component state with the URL compared to manual URL manipulation.

Compared to similar skills

nuqs side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
nuqs (this skill)04moNo flagsBeginner
ai-model-web12moReviewIntermediate
rdc-setup16moReviewIntermediate
tanstack-query-expert03moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

ai-model-web

TencentCloudBase

Use this skill when developing browser/Web applications (React/Vue/Angular, static websites, SPAs) that need AI capabilities. Features text generation (generateText) and streaming (streamText) via @cloudbase/js-sdk. Built-in models include Hunyuan (hunyuan-2.0-instruct-20251111 recommended) and DeepSeek (deepseek-v3.2 recommended). NOT for Node.js backend (use ai-model-nodejs), WeChat Mini Program (use ai-model-wechat), or image generation (Node SDK only).

13

rdc-setup

reactive

Install and set up @data-client/react or @data-client/vue in a project. Detects project type (NextJS, Expo, React Native, Vue, plain React) and protocol (REST, GraphQL, custom), then hands off to protocol-specific setup skills.

10

tanstack-query-expert

Anhvu1107

ALWAYS use this when the request matches Tanstack Query Expert: Expert in TanStack Query (React Query) — asynchronous state management.

00

algolia-search

aiskillstore

Expert patterns for Algolia search implementation, indexing strategies, React InstantSearch, and relevance tuning Use when: adding search to, algolia, instantsearch, search api, search functionality.

00

hr-portal-skill

hariventures2000-ship-it

Use this skill when developing, testing, debugging, or modifying code inside the HR Portal frontend (apps/hr-portal). It applies to handling HR administration tasks such as employee roster management, contract seeding, leave request approvals, attendance monitoring, payroll calculation, and recruitm

00

dapp

salazarsebas

Stellar dApp / frontend development. Covers the JavaScript stellar-sdk (browser + Node.js), Freighter wallet, Stellar Wallets Kit (multi-wallet), Wallet Standard, smart accounts with passkeys, transaction building / signing / submission, Soroban contract invocation from the client, simulation, and e

00

Search skills

Search the agent skills registry