Repository: 47ng/nuqs Branch: next Commit: 61e126a55651 Files: 1140 Total size: 1.6 MB Directory structure: gitextract_4cpkr29x/ ├── .agents/ │ └── docs/ │ ├── adapter-development.md │ ├── api-design.md │ ├── git-workflow.md │ ├── parser-implementation.md │ ├── quality-standards.md │ └── testing.md ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── config.yml │ ├── dependabot.yml │ └── workflows/ │ ├── analyse-nextjs-release.yml │ ├── ci-cd.yml │ ├── clear-shipping-next.yml │ ├── milestone-automation.yml │ ├── pkg.pr.new.yml │ ├── pr-base-enforcement.yml │ ├── pr-lint.yml │ └── test-against-nextjs-release.yml ├── .gitignore ├── .husky/ │ └── commit-msg ├── .node-version ├── .vscode/ │ └── settings.json ├── AGENTS.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── errors/ │ ├── NUQS-101.md │ ├── NUQS-303.md │ ├── NUQS-404.md │ ├── NUQS-409.md │ ├── NUQS-414.md │ ├── NUQS-422.md │ ├── NUQS-429.md │ ├── NUQS-500.md │ └── NUQS-501.md ├── package.json ├── packages/ │ ├── docs/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── components.json │ │ ├── content/ │ │ │ ├── blog/ │ │ │ │ ├── 2025.mdx │ │ │ │ ├── beware-the-url-type-safety-iceberg.components.tsx │ │ │ │ ├── beware-the-url-type-safety-iceberg.mdx │ │ │ │ ├── nuqs-2.5-key-isolation.client.tsx │ │ │ │ ├── nuqs-2.5.mdx │ │ │ │ ├── nuqs-2.mdx │ │ │ │ ├── open-source-pledge-recipient.tsx │ │ │ │ └── open-source-pledge.mdx │ │ │ └── docs/ │ │ │ ├── about.mdx │ │ │ ├── adapters.mdx │ │ │ ├── basic-usage.mdx │ │ │ ├── batching.mdx │ │ │ ├── debugging.mdx │ │ │ ├── installation.mdx │ │ │ ├── internal/ │ │ │ │ └── design-system.mdx │ │ │ ├── limits.mdx │ │ │ ├── meta.json │ │ │ ├── migrations/ │ │ │ │ └── v2.mdx │ │ │ ├── options.client.tsx │ │ │ ├── options.mdx │ │ │ ├── parsers/ │ │ │ │ ├── built-in.mdx │ │ │ │ ├── community/ │ │ │ │ │ ├── effect-schema-demo.tsx │ │ │ │ │ ├── effect-schema.mdx │ │ │ │ │ ├── meta.json │ │ │ │ │ ├── tanstack-table.generator.tsx │ │ │ │ │ ├── tanstack-table.mdx │ │ │ │ │ ├── zod-codecs.demo.tsx │ │ │ │ │ ├── zod-codecs.lib.ts │ │ │ │ │ ├── zod-codecs.mdx │ │ │ │ │ ├── zod-codecs.skeleton.tsx │ │ │ │ │ └── zod-codecs.source.tsx │ │ │ │ ├── demos.tsx │ │ │ │ ├── making-your-own.mdx │ │ │ │ └── meta.json │ │ │ ├── seo.mdx │ │ │ ├── server-side.mdx │ │ │ ├── testing.mdx │ │ │ ├── tips-tricks.mdx │ │ │ ├── troubleshooting.mdx │ │ │ └── utilities.mdx │ │ ├── mdx-components.tsx │ │ ├── next.config.mjs │ │ ├── package.json │ │ ├── public/ │ │ │ └── .well-known/ │ │ │ └── atproto-did │ │ ├── rehype-code.config.ts │ │ ├── sentry.edge.config.ts │ │ ├── sentry.server.config.ts │ │ ├── source.config.ts │ │ ├── src/ │ │ │ ├── app/ │ │ │ │ ├── (llms)/ │ │ │ │ │ ├── llms/ │ │ │ │ │ │ └── [...slug]/ │ │ │ │ │ │ └── route.tsx │ │ │ │ │ ├── llms-full.txt/ │ │ │ │ │ │ └── route.ts │ │ │ │ │ └── llms.txt/ │ │ │ │ │ └── route.ts │ │ │ │ ├── (pages)/ │ │ │ │ │ ├── (confs)/ │ │ │ │ │ │ ├── nextjs-conf-25/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── react-advanced-25/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ └── react-paris/ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── _landing/ │ │ │ │ │ │ ├── bundle-size.tsx │ │ │ │ │ │ ├── contributors.tsx │ │ │ │ │ │ ├── demo.client.tsx │ │ │ │ │ │ ├── demo.tsx │ │ │ │ │ │ ├── dependents.tsx │ │ │ │ │ │ ├── features.tsx │ │ │ │ │ │ ├── gha-status.tsx │ │ │ │ │ │ ├── hero.tsx │ │ │ │ │ │ ├── page-footer.tsx │ │ │ │ │ │ ├── quotes/ │ │ │ │ │ │ │ └── quotes-section.tsx │ │ │ │ │ │ ├── sponsors.tsx │ │ │ │ │ │ └── works-with.tsx │ │ │ │ │ ├── blog/ │ │ │ │ │ │ ├── [slug]/ │ │ │ │ │ │ │ ├── _components/ │ │ │ │ │ │ │ │ └── author.tsx │ │ │ │ │ │ │ ├── opengraph-image.tsx │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ └── twitter-image.tsx │ │ │ │ │ │ ├── _lib/ │ │ │ │ │ │ │ └── source.ts │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ └── rss.xml/ │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── page.tsx │ │ │ │ │ ├── stats/ │ │ │ │ │ │ ├── _components/ │ │ │ │ │ │ │ ├── downloads.client.tsx │ │ │ │ │ │ │ ├── downloads.tsx │ │ │ │ │ │ │ ├── graph.skeleton.tsx │ │ │ │ │ │ │ ├── partial-line.tsx │ │ │ │ │ │ │ ├── stars.client.tsx │ │ │ │ │ │ │ ├── stars.gazers-list.tsx │ │ │ │ │ │ │ ├── stars.tsx │ │ │ │ │ │ │ ├── versions.tsx │ │ │ │ │ │ │ ├── widget.skeleton.tsx │ │ │ │ │ │ │ └── widget.tsx │ │ │ │ │ │ ├── lib/ │ │ │ │ │ │ │ ├── format.ts │ │ │ │ │ │ │ ├── github.ts │ │ │ │ │ │ │ ├── npm.ts │ │ │ │ │ │ │ ├── svg.ts │ │ │ │ │ │ │ └── versions.ts │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ └── searchParams.ts │ │ │ │ │ └── users/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── api/ │ │ │ │ │ ├── isr/ │ │ │ │ │ │ ├── .gitignore │ │ │ │ │ │ └── route.ts │ │ │ │ │ └── search/ │ │ │ │ │ └── route.ts │ │ │ │ ├── banners.tsx │ │ │ │ ├── docs/ │ │ │ │ │ ├── [[...slug]]/ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── layout.tsx │ │ │ │ ├── global-error.tsx │ │ │ │ ├── globals.css │ │ │ │ ├── layout.tsx │ │ │ │ ├── not-found.tsx │ │ │ │ ├── playground/ │ │ │ │ │ ├── (demos)/ │ │ │ │ │ │ ├── _components/ │ │ │ │ │ │ │ └── source-on-github.tsx │ │ │ │ │ │ ├── basic-counter/ │ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── batching/ │ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── demos.ts │ │ │ │ │ │ ├── hex-colors/ │ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ ├── pagination/ │ │ │ │ │ │ │ ├── api.ts │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ ├── pagination-controls.client.tsx │ │ │ │ │ │ │ ├── pagination-controls.server.tsx │ │ │ │ │ │ │ ├── product.tsx │ │ │ │ │ │ │ ├── rendering-controls.tsx │ │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ │ └── tic-tac-toe/ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── _demos/ │ │ │ │ │ │ ├── builder-pattern/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── compound-parsers/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── crosslink/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── custom-parser/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── parsers/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── pretty-urls/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-359/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-376/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-907/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── server-side-parsing/ │ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ └── parser.ts │ │ │ │ │ │ └── throttling/ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ └── parsers.ts │ │ │ │ │ ├── debug-control.tsx │ │ │ │ │ ├── layout.tsx │ │ │ │ │ └── page.tsx │ │ │ │ ├── registry/ │ │ │ │ │ ├── [name]/ │ │ │ │ │ │ ├── author.tsx │ │ │ │ │ │ ├── opengraph-image.tsx │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ └── twitter-image.tsx │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── rss.xml/ │ │ │ │ │ └── route.ts │ │ │ │ ├── robots.ts │ │ │ │ ├── sitemap.ts │ │ │ │ ├── source.ts │ │ │ │ └── styles/ │ │ │ │ └── tweaks.css │ │ │ ├── components/ │ │ │ │ ├── 47ng.tsx │ │ │ │ ├── ai/ │ │ │ │ │ └── page-actions.tsx │ │ │ │ ├── audience.tsx │ │ │ │ ├── code-block-defs.ts │ │ │ │ ├── code-block-highlighter.skeleton.ts │ │ │ │ ├── code-block-highlighter.ts │ │ │ │ ├── code-block.client.tsx │ │ │ │ ├── code-block.tsx │ │ │ │ ├── countdown.tsx │ │ │ │ ├── favicon.tsx │ │ │ │ ├── feature-support-matrix.tsx │ │ │ │ ├── frameworks.client.tsx │ │ │ │ ├── frameworks.tsx │ │ │ │ ├── github-profile.tsx │ │ │ │ ├── kibo-ui/ │ │ │ │ │ └── contribution-graph/ │ │ │ │ │ └── index.tsx │ │ │ │ ├── link-tree.tsx │ │ │ │ ├── logo.tsx │ │ │ │ ├── og-image.tsx │ │ │ │ ├── query-spy.tsx │ │ │ │ ├── querystring.tsx │ │ │ │ ├── quote.tsx │ │ │ │ ├── react-paris.tsx │ │ │ │ ├── release-contribution-graph.client.tsx │ │ │ │ ├── release-contribution-graph.tsx │ │ │ │ ├── responsive-helpers.tsx │ │ │ │ ├── shared-layout.tsx │ │ │ │ ├── sidebar-footer.tsx │ │ │ │ ├── typography.tsx │ │ │ │ ├── ui/ │ │ │ │ │ ├── badge.tsx │ │ │ │ │ ├── breadcrumb.tsx │ │ │ │ │ ├── button.tsx │ │ │ │ │ ├── card.tsx │ │ │ │ │ ├── chart.tsx │ │ │ │ │ ├── checkbox.tsx │ │ │ │ │ ├── input.tsx │ │ │ │ │ ├── label.tsx │ │ │ │ │ ├── pagination.tsx │ │ │ │ │ ├── popover.tsx │ │ │ │ │ ├── pr-line.tsx │ │ │ │ │ ├── select.tsx │ │ │ │ │ ├── separator.tsx │ │ │ │ │ ├── slider.tsx │ │ │ │ │ ├── switch.tsx │ │ │ │ │ ├── tabs.tsx │ │ │ │ │ ├── toggle-group.tsx │ │ │ │ │ ├── toggle.tsx │ │ │ │ │ ├── tooltip-popover.tsx │ │ │ │ │ └── tooltip.tsx │ │ │ │ └── vercel-oss-badge.tsx │ │ │ ├── instrumentation-client.ts │ │ │ ├── instrumentation.ts │ │ │ ├── lib/ │ │ │ │ ├── get-last-modified.ts │ │ │ │ ├── get-llm-text.ts │ │ │ │ ├── remark-audience.ts │ │ │ │ ├── typed-links.ts │ │ │ │ ├── url.ts │ │ │ │ └── utils.ts │ │ │ └── registry/ │ │ │ ├── assemble.ts │ │ │ ├── items/ │ │ │ │ ├── adapter-inertia.json │ │ │ │ ├── adapter-inertia.md │ │ │ │ ├── adapter-onejs.json │ │ │ │ ├── adapter-onejs.md │ │ │ │ ├── adapter-onejs.source │ │ │ │ ├── adapter-react-router-v5.json │ │ │ │ ├── adapter-react-router-v5.md │ │ │ │ ├── adapter-react-router-v5.source │ │ │ │ ├── adapter-waku.json │ │ │ │ ├── adapter-waku.md │ │ │ │ ├── next-typed-links.json │ │ │ │ └── next-typed-links.md │ │ │ ├── read.ts │ │ │ ├── remote/ │ │ │ │ └── .gitignore │ │ │ └── schemas.ts │ │ ├── tsconfig.json │ │ └── turbo.json │ ├── e2e/ │ │ ├── next/ │ │ │ ├── .gitignore │ │ │ ├── next-env.d.ts │ │ │ ├── next.config.mjs │ │ │ ├── package.json │ │ │ ├── playwright.config.ts │ │ │ ├── scripts/ │ │ │ │ └── cache-components-codemod.ts │ │ │ ├── specs/ │ │ │ │ ├── cache.spec.ts │ │ │ │ ├── deferred.spec.ts │ │ │ │ ├── multitenant.spec.ts │ │ │ │ ├── persist-across-navigation.spec.ts │ │ │ │ ├── push.spec.ts │ │ │ │ ├── referential-equality.spec.ts │ │ │ │ ├── remapped-keys.spec.ts │ │ │ │ ├── repros.spec.ts │ │ │ │ ├── rewrites.spec.ts │ │ │ │ ├── routing-tour.spec.ts │ │ │ │ ├── shared/ │ │ │ │ │ ├── basic-io-agnostic.spec.ts │ │ │ │ │ ├── debounce.spec.ts │ │ │ │ │ ├── dynamic-segments.spec.ts │ │ │ │ │ ├── flush-after-navigate.spec.ts │ │ │ │ │ ├── hash-preservation.spec.ts │ │ │ │ │ ├── loader.spec.ts │ │ │ │ │ ├── popstate-queue-reset.spec.ts │ │ │ │ │ ├── push.spec.ts │ │ │ │ │ ├── render-count.spec.ts │ │ │ │ │ ├── repro-1099.spec.ts │ │ │ │ │ ├── repro-1293.spec.ts │ │ │ │ │ ├── repro-1365.spec.ts │ │ │ │ │ ├── repro-359.spec.ts │ │ │ │ │ ├── repro-982.spec.ts │ │ │ │ │ ├── shallow.spec.ts │ │ │ │ │ └── stitching.spec.ts │ │ │ │ ├── shared.spec.ts │ │ │ │ ├── transitions.spec.ts │ │ │ │ ├── useQueryState.spec.ts │ │ │ │ ├── useQueryStates-clear-all.spec.ts │ │ │ │ ├── useQueryStates.spec.ts │ │ │ │ └── useSearchParams.spec.ts │ │ │ ├── src/ │ │ │ │ ├── app/ │ │ │ │ │ ├── api/ │ │ │ │ │ │ └── app/ │ │ │ │ │ │ └── loader/ │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── (shared)/ │ │ │ │ │ │ │ ├── basic-io/ │ │ │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── conditional-rendering/ │ │ │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── debounce/ │ │ │ │ │ │ │ │ ├── other/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── dynamic-segments/ │ │ │ │ │ │ │ │ ├── catch-all/ │ │ │ │ │ │ │ │ │ └── [...segments]/ │ │ │ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ │ │ │ └── [segment]/ │ │ │ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── optional-catch-all/ │ │ │ │ │ │ │ │ └── [[...segments]]/ │ │ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── flush-after-navigate/ │ │ │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ │ │ ├── end/ │ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ │ └── start/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ │ │ │ ├── end/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── start/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── form/ │ │ │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── hash-preservation/ │ │ │ │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ │ │ │ └── [route]/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── history-sync/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── json/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── life-and-death/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── linking/ │ │ │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ │ │ ├── other/ │ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ │ │ │ ├── other/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── native-array/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── popstate-queue-reset/ │ │ │ │ │ │ │ │ ├── other/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── pretty-urls/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── push/ │ │ │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ │ │ │ │ └── [route]/ │ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ │ │ │ └── [route]/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── rate-limits/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── referential-stability/ │ │ │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── render-count/ │ │ │ │ │ │ │ │ └── [hook]/ │ │ │ │ │ │ │ │ └── [shallow]/ │ │ │ │ │ │ │ │ └── [history]/ │ │ │ │ │ │ │ │ └── [startTransition]/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── repro-1365/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── repro-359/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── repro-982/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── routing/ │ │ │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ │ │ ├── other/ │ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ │ │ │ ├── other/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── scroll/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── shallow/ │ │ │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── stitching/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── agnostic/ │ │ │ │ │ │ │ ├── basic-io/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── layout.tsx │ │ │ │ │ │ ├── cache/ │ │ │ │ │ │ │ ├── all.tsx │ │ │ │ │ │ │ ├── get.tsx │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ ├── searchParams.ts │ │ │ │ │ │ │ └── set.tsx │ │ │ │ │ │ ├── deferred/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── loader/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── multitenant/ │ │ │ │ │ │ │ └── [tenant]/ │ │ │ │ │ │ │ ├── client-tenant.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── persist-across-navigation/ │ │ │ │ │ │ │ ├── a/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── b/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── client.tsx │ │ │ │ │ │ ├── push/ │ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ └── searchParams.ts │ │ │ │ │ │ ├── referential-equality/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── remapped-keys/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-1099/ │ │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-1293/ │ │ │ │ │ │ │ ├── a/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── b/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-388/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-498/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-542/ │ │ │ │ │ │ │ ├── a/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── b/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── client.tsx │ │ │ │ │ │ ├── repro-630/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-758/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-760/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── repro-774/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── rewrites/ │ │ │ │ │ │ │ └── destination/ │ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ └── searchParams.ts │ │ │ │ │ │ ├── routing-tour/ │ │ │ │ │ │ │ ├── _components/ │ │ │ │ │ │ │ │ ├── parsers.ts │ │ │ │ │ │ │ │ └── view.tsx │ │ │ │ │ │ │ ├── a/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── b/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── c/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── d/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── start/ │ │ │ │ │ │ │ ├── client/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── server/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── template/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── transitions/ │ │ │ │ │ │ │ ├── client.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ │ │ └── [route]/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── useQueryStates/ │ │ │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ │ │ └── [route]/ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── useQueryStates-clear-all/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ └── useSearchParams/ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── providers.tsx │ │ │ │ ├── components/ │ │ │ │ │ └── pages-ready-wrapper.tsx │ │ │ │ ├── middleware.ts │ │ │ │ └── pages/ │ │ │ │ ├── _app.tsx │ │ │ │ ├── api/ │ │ │ │ │ └── pages/ │ │ │ │ │ └── loader.ts │ │ │ │ └── pages/ │ │ │ │ ├── agnostic/ │ │ │ │ │ └── basic-io.tsx │ │ │ │ ├── basic-io/ │ │ │ │ │ ├── useQueryState.tsx │ │ │ │ │ └── useQueryStates.tsx │ │ │ │ ├── conditional-rendering/ │ │ │ │ │ ├── useQueryState.tsx │ │ │ │ │ └── useQueryStates.tsx │ │ │ │ ├── debounce/ │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── other.tsx │ │ │ │ ├── dynamic-segments/ │ │ │ │ │ ├── catch-all/ │ │ │ │ │ │ └── [...segments].tsx │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ └── [segment].tsx │ │ │ │ │ └── optional-catch-all/ │ │ │ │ │ └── [[...segments]].tsx │ │ │ │ ├── flush-after-navigate/ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ ├── end.tsx │ │ │ │ │ │ └── start.tsx │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ ├── end.tsx │ │ │ │ │ └── start.tsx │ │ │ │ ├── form/ │ │ │ │ │ ├── useQueryState.tsx │ │ │ │ │ └── useQueryStates.tsx │ │ │ │ ├── hash-preservation/ │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ └── [route]/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── history-sync.tsx │ │ │ │ ├── json.tsx │ │ │ │ ├── life-and-death.tsx │ │ │ │ ├── linking/ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── other.tsx │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── other.tsx │ │ │ │ ├── loader.tsx │ │ │ │ ├── middleware.tsx │ │ │ │ ├── multitenant/ │ │ │ │ │ └── [tenant].tsx │ │ │ │ ├── native-array.tsx │ │ │ │ ├── popstate-queue-reset/ │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── other.tsx │ │ │ │ ├── pretty-urls.tsx │ │ │ │ ├── push/ │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ │ └── [route]/ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ └── [route]/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── rate-limits.tsx │ │ │ │ ├── referential-stability/ │ │ │ │ │ ├── useQueryState.tsx │ │ │ │ │ └── useQueryStates.tsx │ │ │ │ ├── render-count/ │ │ │ │ │ └── [hook]/ │ │ │ │ │ └── [shallow]/ │ │ │ │ │ └── [history]/ │ │ │ │ │ └── [startTransition]/ │ │ │ │ │ └── index.tsx │ │ │ │ ├── repro-1099/ │ │ │ │ │ ├── useQueryState.tsx │ │ │ │ │ └── useQueryStates.tsx │ │ │ │ ├── repro-1293/ │ │ │ │ │ ├── a.tsx │ │ │ │ │ └── b.tsx │ │ │ │ ├── repro-1365.tsx │ │ │ │ ├── repro-359.tsx │ │ │ │ ├── repro-982.tsx │ │ │ │ ├── routing/ │ │ │ │ │ ├── useQueryState/ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── other.tsx │ │ │ │ │ └── useQueryStates/ │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── other.tsx │ │ │ │ ├── scroll.tsx │ │ │ │ ├── shallow/ │ │ │ │ │ ├── useQueryState.tsx │ │ │ │ │ └── useQueryStates.tsx │ │ │ │ ├── stitching.tsx │ │ │ │ ├── useQueryState/ │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ └── [route]/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── useQueryStates/ │ │ │ │ ├── dynamic/ │ │ │ │ │ └── [route]/ │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ ├── tsconfig.json │ │ │ └── turbo.json │ │ ├── package.json │ │ ├── react/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── playwright.config.ts │ │ │ ├── specs/ │ │ │ │ ├── shared/ │ │ │ │ │ ├── key-isolation.spec.ts │ │ │ │ │ ├── push.spec.ts │ │ │ │ │ ├── referential-stability.spec.ts │ │ │ │ │ ├── render-count.spec.ts │ │ │ │ │ ├── repro-1099.spec.ts │ │ │ │ │ ├── repro-1365.spec.ts │ │ │ │ │ ├── repro-359.spec.ts │ │ │ │ │ ├── repro-982.spec.ts │ │ │ │ │ ├── routing.spec.ts │ │ │ │ │ ├── scroll.spec.ts │ │ │ │ │ ├── shallow.spec.ts │ │ │ │ │ └── stitching.spec.ts │ │ │ │ └── shared.spec.ts │ │ │ ├── src/ │ │ │ │ ├── layout.tsx │ │ │ │ ├── main.tsx │ │ │ │ ├── routes/ │ │ │ │ │ ├── basic-io.useQueryState.tsx │ │ │ │ │ ├── basic-io.useQueryStates.tsx │ │ │ │ │ ├── conditional-rendering.useQueryState.tsx │ │ │ │ │ ├── conditional-rendering.useQueryStates.tsx │ │ │ │ │ ├── form.useQueryState.tsx │ │ │ │ │ ├── form.useQueryStates.tsx │ │ │ │ │ ├── hash-preservation.tsx │ │ │ │ │ ├── history-sync.tsx │ │ │ │ │ ├── json.tsx │ │ │ │ │ ├── key-isolation.useQueryState.tsx │ │ │ │ │ ├── key-isolation.useQueryStates.tsx │ │ │ │ │ ├── life-and-death.tsx │ │ │ │ │ ├── linking.useQueryState.other.tsx │ │ │ │ │ ├── linking.useQueryState.tsx │ │ │ │ │ ├── linking.useQueryStates.other.tsx │ │ │ │ │ ├── linking.useQueryStates.tsx │ │ │ │ │ ├── native-array.tsx │ │ │ │ │ ├── pretty-urls.tsx │ │ │ │ │ ├── push.useQueryState.tsx │ │ │ │ │ ├── push.useQueryStates.tsx │ │ │ │ │ ├── rate-limits.tsx │ │ │ │ │ ├── referential-stability.useQueryState.tsx │ │ │ │ │ ├── referential-stability.useQueryStates.tsx │ │ │ │ │ ├── render-count.tsx │ │ │ │ │ ├── repro-1099.useQueryState.tsx │ │ │ │ │ ├── repro-1099.useQueryStates.tsx │ │ │ │ │ ├── repro-1365.tsx │ │ │ │ │ ├── repro-359.tsx │ │ │ │ │ ├── repro-982.tsx │ │ │ │ │ ├── routing.useQueryState.other.tsx │ │ │ │ │ ├── routing.useQueryState.tsx │ │ │ │ │ ├── routing.useQueryStates.other.tsx │ │ │ │ │ ├── routing.useQueryStates.tsx │ │ │ │ │ ├── scroll.tsx │ │ │ │ │ ├── shallow.useQueryState.tsx │ │ │ │ │ ├── shallow.useQueryStates.tsx │ │ │ │ │ └── stitching.tsx │ │ │ │ ├── routes.tsx │ │ │ │ └── vite-env.d.ts │ │ │ ├── tsconfig.app.json │ │ │ ├── tsconfig.json │ │ │ ├── tsconfig.node.json │ │ │ ├── turbo.json │ │ │ └── vite.config.ts │ │ ├── react-router/ │ │ │ ├── package.json │ │ │ ├── v5/ │ │ │ │ ├── .gitignore │ │ │ │ ├── README.md │ │ │ │ ├── index.html │ │ │ │ ├── package.json │ │ │ │ ├── playwright.config.ts │ │ │ │ ├── specs/ │ │ │ │ │ ├── shared/ │ │ │ │ │ │ ├── fog-of-war.spec.ts │ │ │ │ │ │ ├── push.spec.ts │ │ │ │ │ │ ├── render-count.spec.ts │ │ │ │ │ │ ├── repro-1099.spec.ts │ │ │ │ │ │ ├── repro-359.spec.ts │ │ │ │ │ │ ├── repro-982.spec.ts │ │ │ │ │ │ └── stitching.spec.ts │ │ │ │ │ └── shared.spec.ts │ │ │ │ ├── src/ │ │ │ │ │ ├── adapter.ts │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── main.tsx │ │ │ │ │ ├── react-router.tsx │ │ │ │ │ ├── routes/ │ │ │ │ │ │ ├── basic-io.useQueryState.tsx │ │ │ │ │ │ ├── basic-io.useQueryStates.tsx │ │ │ │ │ │ ├── conditional-rendering.useQueryState.tsx │ │ │ │ │ │ ├── conditional-rendering.useQueryStates.tsx │ │ │ │ │ │ ├── fog-of-war._index.tsx │ │ │ │ │ │ ├── fog-of-war.result.tsx │ │ │ │ │ │ ├── form.useQueryState.tsx │ │ │ │ │ │ ├── form.useQueryStates.tsx │ │ │ │ │ │ ├── hash-preservation.tsx │ │ │ │ │ │ ├── history-sync.tsx │ │ │ │ │ │ ├── json.tsx │ │ │ │ │ │ ├── key-isolation.useQueryState.tsx │ │ │ │ │ │ ├── key-isolation.useQueryStates.tsx │ │ │ │ │ │ ├── life-and-death.tsx │ │ │ │ │ │ ├── linking.useQueryState.other.tsx │ │ │ │ │ │ ├── linking.useQueryState.tsx │ │ │ │ │ │ ├── linking.useQueryStates.other.tsx │ │ │ │ │ │ ├── linking.useQueryStates.tsx │ │ │ │ │ │ ├── native-array.tsx │ │ │ │ │ │ ├── pretty-urls.tsx │ │ │ │ │ │ ├── push.useQueryState.tsx │ │ │ │ │ │ ├── push.useQueryStates.tsx │ │ │ │ │ │ ├── rate-limits.tsx │ │ │ │ │ │ ├── referential-stability.useQueryState.tsx │ │ │ │ │ │ ├── referential-stability.useQueryStates.tsx │ │ │ │ │ │ ├── render-count.$hook.$shallow.$history.$startTransition.no-loader.tsx │ │ │ │ │ │ ├── repro-1099.useQueryState.tsx │ │ │ │ │ │ ├── repro-1099.useQueryStates.tsx │ │ │ │ │ │ ├── repro-359.tsx │ │ │ │ │ │ ├── repro-982.tsx │ │ │ │ │ │ ├── routing.useQueryState.other.tsx │ │ │ │ │ │ ├── routing.useQueryState.tsx │ │ │ │ │ │ ├── routing.useQueryStates.other.tsx │ │ │ │ │ │ ├── routing.useQueryStates.tsx │ │ │ │ │ │ ├── scroll.tsx │ │ │ │ │ │ └── stitching.tsx │ │ │ │ │ └── vite-env.d.ts │ │ │ │ ├── tsconfig.app.json │ │ │ │ ├── tsconfig.json │ │ │ │ ├── tsconfig.node.json │ │ │ │ ├── turbo.json │ │ │ │ └── vite.config.ts │ │ │ ├── v6/ │ │ │ │ ├── .gitignore │ │ │ │ ├── README.md │ │ │ │ ├── index.html │ │ │ │ ├── package.json │ │ │ │ ├── playwright.config.ts │ │ │ │ ├── specs/ │ │ │ │ │ ├── repro-839.spec.ts │ │ │ │ │ ├── shared/ │ │ │ │ │ │ ├── debounce.spec.ts │ │ │ │ │ │ ├── dynamic-segments.spec.ts │ │ │ │ │ │ ├── flush-after-navigate.spec.ts │ │ │ │ │ │ ├── fog-of-war.spec.ts │ │ │ │ │ │ ├── key-isolation.spec.ts │ │ │ │ │ │ ├── loader.spec.ts │ │ │ │ │ │ ├── popstate-queue-reset.spec.ts │ │ │ │ │ │ ├── push.spec.ts │ │ │ │ │ │ ├── render-count.spec.ts │ │ │ │ │ │ ├── repro-1099.spec.ts │ │ │ │ │ │ ├── repro-1293.spec.ts │ │ │ │ │ │ ├── repro-1365.spec.ts │ │ │ │ │ │ ├── repro-359.spec.ts │ │ │ │ │ │ ├── repro-982.spec.ts │ │ │ │ │ │ ├── shallow.spec.ts │ │ │ │ │ │ └── stitching.spec.ts │ │ │ │ │ └── shared.spec.ts │ │ │ │ ├── src/ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── main.tsx │ │ │ │ │ ├── react-router.tsx │ │ │ │ │ ├── routes/ │ │ │ │ │ │ ├── basic-io.useQueryState.tsx │ │ │ │ │ │ ├── basic-io.useQueryStates.tsx │ │ │ │ │ │ ├── conditional-rendering.useQueryState.tsx │ │ │ │ │ │ ├── conditional-rendering.useQueryStates.tsx │ │ │ │ │ │ ├── debounce.other.tsx │ │ │ │ │ │ ├── debounce.tsx │ │ │ │ │ │ ├── dynamic-segments.catch-all.$.tsx │ │ │ │ │ │ ├── dynamic-segments.dynamic.$segment.tsx │ │ │ │ │ │ ├── flush-after-navigate.useQueryState.end.tsx │ │ │ │ │ │ ├── flush-after-navigate.useQueryState.start.tsx │ │ │ │ │ │ ├── flush-after-navigate.useQueryStates.end.tsx │ │ │ │ │ │ ├── flush-after-navigate.useQueryStates.start.tsx │ │ │ │ │ │ ├── fog-of-war._index.tsx │ │ │ │ │ │ ├── fog-of-war.result.tsx │ │ │ │ │ │ ├── form.useQueryState.tsx │ │ │ │ │ │ ├── form.useQueryStates.tsx │ │ │ │ │ │ ├── hash-preservation.tsx │ │ │ │ │ │ ├── history-sync.tsx │ │ │ │ │ │ ├── json.tsx │ │ │ │ │ │ ├── key-isolation.useQueryState.tsx │ │ │ │ │ │ ├── key-isolation.useQueryStates.tsx │ │ │ │ │ │ ├── life-and-death.tsx │ │ │ │ │ │ ├── linking.useQueryState.other.tsx │ │ │ │ │ │ ├── linking.useQueryState.tsx │ │ │ │ │ │ ├── linking.useQueryStates.other.tsx │ │ │ │ │ │ ├── linking.useQueryStates.tsx │ │ │ │ │ │ ├── loader.tsx │ │ │ │ │ │ ├── native-array.tsx │ │ │ │ │ │ ├── popstate-queue-reset.other.tsx │ │ │ │ │ │ ├── popstate-queue-reset.tsx │ │ │ │ │ │ ├── pretty-urls.tsx │ │ │ │ │ │ ├── push.useQueryState.tsx │ │ │ │ │ │ ├── push.useQueryStates.tsx │ │ │ │ │ │ ├── rate-limits.tsx │ │ │ │ │ │ ├── referential-stability.useQueryState.tsx │ │ │ │ │ │ ├── referential-stability.useQueryStates.tsx │ │ │ │ │ │ ├── render-count.$hook.$shallow.$history.$startTransition.async-loader.tsx │ │ │ │ │ │ ├── render-count.$hook.$shallow.$history.$startTransition.no-loader.tsx │ │ │ │ │ │ ├── render-count.$hook.$shallow.$history.$startTransition.sync-loader.tsx │ │ │ │ │ │ ├── repro-1099.useQueryState.tsx │ │ │ │ │ │ ├── repro-1099.useQueryStates.tsx │ │ │ │ │ │ ├── repro-1293.a.tsx │ │ │ │ │ │ ├── repro-1293.b.tsx │ │ │ │ │ │ ├── repro-1365.tsx │ │ │ │ │ │ ├── repro-359.tsx │ │ │ │ │ │ ├── repro-839.tsx │ │ │ │ │ │ ├── repro-982.tsx │ │ │ │ │ │ ├── routing.useQueryState.other.tsx │ │ │ │ │ │ ├── routing.useQueryState.tsx │ │ │ │ │ │ ├── routing.useQueryStates.other.tsx │ │ │ │ │ │ ├── routing.useQueryStates.tsx │ │ │ │ │ │ ├── scroll.tsx │ │ │ │ │ │ ├── shallow.useQueryState.tsx │ │ │ │ │ │ ├── shallow.useQueryStates.tsx │ │ │ │ │ │ └── stitching.tsx │ │ │ │ │ └── vite-env.d.ts │ │ │ │ ├── tsconfig.app.json │ │ │ │ ├── tsconfig.json │ │ │ │ ├── tsconfig.node.json │ │ │ │ ├── turbo.json │ │ │ │ └── vite.config.ts │ │ │ └── v7/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── app/ │ │ │ │ ├── layout.tsx │ │ │ │ ├── root.tsx │ │ │ │ ├── routes/ │ │ │ │ │ ├── basic-io.useQueryState.tsx │ │ │ │ │ ├── basic-io.useQueryStates.tsx │ │ │ │ │ ├── conditional-rendering.useQueryState.tsx │ │ │ │ │ ├── conditional-rendering.useQueryStates.tsx │ │ │ │ │ ├── debounce.other.tsx │ │ │ │ │ ├── debounce.tsx │ │ │ │ │ ├── dynamic-segments.catch-all.$.tsx │ │ │ │ │ ├── dynamic-segments.dynamic.$segment.tsx │ │ │ │ │ ├── flush-after-navigate.useQueryState.end.tsx │ │ │ │ │ ├── flush-after-navigate.useQueryState.start.tsx │ │ │ │ │ ├── flush-after-navigate.useQueryStates.end.tsx │ │ │ │ │ ├── flush-after-navigate.useQueryStates.start.tsx │ │ │ │ │ ├── fog-of-war._index.tsx │ │ │ │ │ ├── fog-of-war.result.tsx │ │ │ │ │ ├── form.useQueryState.tsx │ │ │ │ │ ├── form.useQueryStates.tsx │ │ │ │ │ ├── hash-preservation.tsx │ │ │ │ │ ├── history-sync.tsx │ │ │ │ │ ├── json.tsx │ │ │ │ │ ├── key-isolation.useQueryState.tsx │ │ │ │ │ ├── key-isolation.useQueryStates.tsx │ │ │ │ │ ├── life-and-death.tsx │ │ │ │ │ ├── linking.useQueryState.other.tsx │ │ │ │ │ ├── linking.useQueryState.tsx │ │ │ │ │ ├── linking.useQueryStates.other.tsx │ │ │ │ │ ├── linking.useQueryStates.tsx │ │ │ │ │ ├── loader.tsx │ │ │ │ │ ├── native-array.tsx │ │ │ │ │ ├── popstate-queue-reset.other.tsx │ │ │ │ │ ├── popstate-queue-reset.tsx │ │ │ │ │ ├── pretty-urls.tsx │ │ │ │ │ ├── push.useQueryState.tsx │ │ │ │ │ ├── push.useQueryStates.tsx │ │ │ │ │ ├── rate-limits.tsx │ │ │ │ │ ├── referential-stability.useQueryState.tsx │ │ │ │ │ ├── referential-stability.useQueryStates.tsx │ │ │ │ │ ├── render-count.$hook.$shallow.$history.$startTransition.async-loader.tsx │ │ │ │ │ ├── render-count.$hook.$shallow.$history.$startTransition.no-loader.tsx │ │ │ │ │ ├── render-count.$hook.$shallow.$history.$startTransition.sync-loader.tsx │ │ │ │ │ ├── repro-1099.useQueryState.tsx │ │ │ │ │ ├── repro-1099.useQueryStates.tsx │ │ │ │ │ ├── repro-1293.a.tsx │ │ │ │ │ ├── repro-1293.b.tsx │ │ │ │ │ ├── repro-1365.tsx │ │ │ │ │ ├── repro-359.tsx │ │ │ │ │ ├── repro-839.tsx │ │ │ │ │ ├── repro-982.tsx │ │ │ │ │ ├── routing.useQueryState.other.tsx │ │ │ │ │ ├── routing.useQueryState.tsx │ │ │ │ │ ├── routing.useQueryStates.other.tsx │ │ │ │ │ ├── routing.useQueryStates.tsx │ │ │ │ │ ├── scroll.tsx │ │ │ │ │ ├── shallow.useQueryState.tsx │ │ │ │ │ ├── shallow.useQueryStates.tsx │ │ │ │ │ └── stitching.tsx │ │ │ │ └── routes.ts │ │ │ ├── package.json │ │ │ ├── playwright.config.ts │ │ │ ├── react-router.config.ts │ │ │ ├── server.mjs │ │ │ ├── specs/ │ │ │ │ ├── repro-839.spec.ts │ │ │ │ ├── shared/ │ │ │ │ │ ├── debounce.spec.ts │ │ │ │ │ ├── dynamic-segments.spec.ts │ │ │ │ │ ├── flush-after-navigate.spec.ts │ │ │ │ │ ├── fog-of-war.spec.ts │ │ │ │ │ ├── key-isolation.spec.ts │ │ │ │ │ ├── loader.spec.ts │ │ │ │ │ ├── popstate-queue-reset.spec.ts │ │ │ │ │ ├── push.spec.ts │ │ │ │ │ ├── render-count.spec.ts │ │ │ │ │ ├── repro-1099.spec.ts │ │ │ │ │ ├── repro-1293.spec.ts │ │ │ │ │ ├── repro-1365.spec.ts │ │ │ │ │ ├── repro-359.spec.ts │ │ │ │ │ ├── repro-982.spec.ts │ │ │ │ │ ├── shallow.spec.ts │ │ │ │ │ └── stitching.spec.ts │ │ │ │ └── shared.spec.ts │ │ │ ├── tsconfig.json │ │ │ ├── turbo.json │ │ │ └── vite.config.ts │ │ ├── remix/ │ │ │ ├── .eslintrc.cjs │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── app/ │ │ │ │ ├── entry.client.tsx │ │ │ │ ├── entry.server.tsx │ │ │ │ ├── layout.tsx │ │ │ │ ├── root.tsx │ │ │ │ └── routes/ │ │ │ │ ├── basic-io.useQueryState.tsx │ │ │ │ ├── basic-io.useQueryStates.tsx │ │ │ │ ├── conditional-rendering.useQueryState.tsx │ │ │ │ ├── conditional-rendering.useQueryStates.tsx │ │ │ │ ├── debounce-other.tsx │ │ │ │ ├── debounce.tsx │ │ │ │ ├── dynamic-segments.catch-all.$.tsx │ │ │ │ ├── dynamic-segments.dynamic.$segment.tsx │ │ │ │ ├── flush-after-navigate.useQueryState.end.tsx │ │ │ │ ├── flush-after-navigate.useQueryState.start.tsx │ │ │ │ ├── flush-after-navigate.useQueryStates.end.tsx │ │ │ │ ├── flush-after-navigate.useQueryStates.start.tsx │ │ │ │ ├── fog-of-war._index.tsx │ │ │ │ ├── fog-of-war.result.tsx │ │ │ │ ├── form.useQueryState.tsx │ │ │ │ ├── form.useQueryStates.tsx │ │ │ │ ├── hash-preservation.tsx │ │ │ │ ├── history-sync.tsx │ │ │ │ ├── json.tsx │ │ │ │ ├── key-isolation.useQueryState.tsx │ │ │ │ ├── key-isolation.useQueryStates.tsx │ │ │ │ ├── life-and-death.tsx │ │ │ │ ├── linking.useQueryState.other.tsx │ │ │ │ ├── linking.useQueryState.tsx │ │ │ │ ├── linking.useQueryStates.other.tsx │ │ │ │ ├── linking.useQueryStates.tsx │ │ │ │ ├── loader.tsx │ │ │ │ ├── native-array.tsx │ │ │ │ ├── popstate-queue-reset-other.tsx │ │ │ │ ├── popstate-queue-reset.tsx │ │ │ │ ├── pretty-urls.tsx │ │ │ │ ├── push.useQueryState.tsx │ │ │ │ ├── push.useQueryStates.tsx │ │ │ │ ├── rate-limits.tsx │ │ │ │ ├── referential-stability.useQueryState.tsx │ │ │ │ ├── referential-stability.useQueryStates.tsx │ │ │ │ ├── render-count.$hook.$shallow.$history.$startTransition.async-loader.tsx │ │ │ │ ├── render-count.$hook.$shallow.$history.$startTransition.no-loader.tsx │ │ │ │ ├── render-count.$hook.$shallow.$history.$startTransition.sync-loader.tsx │ │ │ │ ├── repro-1099.useQueryState.tsx │ │ │ │ ├── repro-1099.useQueryStates.tsx │ │ │ │ ├── repro-1293.a.tsx │ │ │ │ ├── repro-1293.b.tsx │ │ │ │ ├── repro-1365.tsx │ │ │ │ ├── repro-359.tsx │ │ │ │ ├── repro-839.tsx │ │ │ │ ├── repro-982.tsx │ │ │ │ ├── routing.useQueryState.other.tsx │ │ │ │ ├── routing.useQueryState.tsx │ │ │ │ ├── routing.useQueryStates.other.tsx │ │ │ │ ├── routing.useQueryStates.tsx │ │ │ │ ├── scroll.tsx │ │ │ │ ├── shallow.useQueryState.tsx │ │ │ │ ├── shallow.useQueryStates.tsx │ │ │ │ └── stitching.tsx │ │ │ ├── package.json │ │ │ ├── playwright.config.ts │ │ │ ├── specs/ │ │ │ │ ├── popstate-queue-reset.spec.ts │ │ │ │ ├── repro-839.spec.ts │ │ │ │ ├── shared/ │ │ │ │ │ ├── debounce.spec.ts │ │ │ │ │ ├── dynamic-segments.spec.ts │ │ │ │ │ ├── flush-after-navigate.spec.ts │ │ │ │ │ ├── fog-of-war.spec.ts │ │ │ │ │ ├── key-isolation.spec.ts │ │ │ │ │ ├── loader.spec.ts │ │ │ │ │ ├── push.spec.ts │ │ │ │ │ ├── render-count.spec.ts │ │ │ │ │ ├── repro-1099.spec.ts │ │ │ │ │ ├── repro-1293.spec.ts │ │ │ │ │ ├── repro-1365.spec.ts │ │ │ │ │ ├── repro-359.spec.ts │ │ │ │ │ ├── repro-982.spec.ts │ │ │ │ │ ├── shallow.spec.ts │ │ │ │ │ └── stitching.spec.ts │ │ │ │ └── shared.spec.ts │ │ │ ├── tsconfig.json │ │ │ ├── turbo.json │ │ │ └── vite.config.ts │ │ ├── shared/ │ │ │ ├── components/ │ │ │ │ ├── display.tsx │ │ │ │ ├── hydration-marker.tsx │ │ │ │ ├── link.tsx │ │ │ │ ├── null-detector.tsx │ │ │ │ └── router.tsx │ │ │ ├── define-test.ts │ │ │ ├── lib/ │ │ │ │ └── options.ts │ │ │ ├── package.json │ │ │ ├── playwright/ │ │ │ │ ├── agent-reporter.ts │ │ │ │ ├── expect-url.ts │ │ │ │ ├── log-spy.ts │ │ │ │ ├── navigate.ts │ │ │ │ ├── reporter.ts │ │ │ │ └── url-spy.ts │ │ │ ├── playwright.config.ts │ │ │ ├── shared.spec.ts │ │ │ ├── specs/ │ │ │ │ ├── basic-io.spec.ts │ │ │ │ ├── basic-io.tsx │ │ │ │ ├── conditional-rendering.spec.ts │ │ │ │ ├── conditional-rendering.tsx │ │ │ │ ├── debounce-client.tsx │ │ │ │ ├── debounce-server.tsx │ │ │ │ ├── debounce.defs.ts │ │ │ │ ├── debounce.spec.ts │ │ │ │ ├── dynamic-segments.spec.ts │ │ │ │ ├── dynamic-segments.tsx │ │ │ │ ├── flush-after-navigate.defs.ts │ │ │ │ ├── flush-after-navigate.spec.ts │ │ │ │ ├── flush-after-navigate.tsx │ │ │ │ ├── form.spec.ts │ │ │ │ ├── form.tsx │ │ │ │ ├── hash-preservation.spec.ts │ │ │ │ ├── hash-preservation.tsx │ │ │ │ ├── history-sync.spec.ts │ │ │ │ ├── history-sync.tsx │ │ │ │ ├── json.spec.ts │ │ │ │ ├── json.tsx │ │ │ │ ├── key-isolation.spec.ts │ │ │ │ ├── key-isolation.tsx │ │ │ │ ├── life-and-death.spec.ts │ │ │ │ ├── life-and-death.tsx │ │ │ │ ├── linking.spec.ts │ │ │ │ ├── linking.tsx │ │ │ │ ├── loader.spec.ts │ │ │ │ ├── loader.tsx │ │ │ │ ├── native-array.spec.ts │ │ │ │ ├── native-array.tsx │ │ │ │ ├── popstate-queue-reset.defs.ts │ │ │ │ ├── popstate-queue-reset.spec.ts │ │ │ │ ├── popstate-queue-reset.tsx │ │ │ │ ├── pretty-urls.spec.ts │ │ │ │ ├── pretty-urls.tsx │ │ │ │ ├── push.spec.ts │ │ │ │ ├── push.tsx │ │ │ │ ├── rate-limits.tsx │ │ │ │ ├── react-router/ │ │ │ │ │ ├── fog-of-war.spec.ts │ │ │ │ │ ├── fog-of-war.tsx │ │ │ │ │ ├── repro-839-location-state-persistence.spec.ts │ │ │ │ │ └── repro-839-location-state-persistence.tsx │ │ │ │ ├── referential-stability.spec.ts │ │ │ │ ├── referential-stability.tsx │ │ │ │ ├── render-count.params.ts │ │ │ │ ├── render-count.spec.ts │ │ │ │ ├── render-count.tsx │ │ │ │ ├── repro-1099.spec.ts │ │ │ │ ├── repro-1099.tsx │ │ │ │ ├── repro-1293.spec.ts │ │ │ │ ├── repro-1293.tsx │ │ │ │ ├── repro-1365.spec.ts │ │ │ │ ├── repro-1365.tsx │ │ │ │ ├── repro-359.spec.ts │ │ │ │ ├── repro-359.tsx │ │ │ │ ├── repro-982.spec.ts │ │ │ │ ├── repro-982.tsx │ │ │ │ ├── routing.defs.ts │ │ │ │ ├── routing.spec.ts │ │ │ │ ├── routing.tsx │ │ │ │ ├── scroll.spec.ts │ │ │ │ ├── scroll.tsx │ │ │ │ ├── shallow.spec.ts │ │ │ │ ├── shallow.tsx │ │ │ │ ├── stitching.defs.ts │ │ │ │ ├── stitching.spec.ts │ │ │ │ └── stitching.tsx │ │ │ └── tsconfig.json │ │ └── tanstack-router/ │ │ ├── .cta.json │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── specs/ │ │ │ ├── shared/ │ │ │ │ ├── basic-io.spec.ts │ │ │ │ ├── conditional-rendering.spec.ts │ │ │ │ ├── form.spec.ts │ │ │ │ ├── hash-preservation.spec.ts │ │ │ │ ├── json.spec.ts │ │ │ │ ├── key-isolation.spec.ts │ │ │ │ ├── linking.spec.ts │ │ │ │ ├── native-array.spec.ts │ │ │ │ ├── pretty-urls.spec.ts │ │ │ │ ├── push.spec.ts │ │ │ │ ├── referential-stability.spec.ts │ │ │ │ ├── repro-1099.spec.ts │ │ │ │ ├── repro-1365.spec.ts │ │ │ │ ├── routing.spec.ts │ │ │ │ ├── scroll.spec.ts │ │ │ │ └── shallow.spec.ts │ │ │ ├── shared.spec.ts │ │ │ └── trailing-slash.spec.ts │ │ ├── src/ │ │ │ ├── layout.tsx │ │ │ ├── main.tsx │ │ │ └── routes/ │ │ │ ├── __root.tsx │ │ │ ├── basic-io.useQueryState.tsx │ │ │ ├── basic-io.useQueryStates.tsx │ │ │ ├── conditional-rendering.useQueryState.tsx │ │ │ ├── conditional-rendering.useQueryStates.tsx │ │ │ ├── form.useQueryState.tsx │ │ │ ├── form.useQueryStates.tsx │ │ │ ├── hash-preservation.tsx │ │ │ ├── history-sync.tsx │ │ │ ├── json.tsx │ │ │ ├── key-isolation.useQueryState.tsx │ │ │ ├── key-isolation.useQueryStates.tsx │ │ │ ├── life-and-death.tsx │ │ │ ├── linking.useQueryState.other.tsx │ │ │ ├── linking.useQueryState.tsx │ │ │ ├── linking.useQueryStates.other.tsx │ │ │ ├── linking.useQueryStates.tsx │ │ │ ├── native-array.tsx │ │ │ ├── pretty-urls.tsx │ │ │ ├── push.useQueryState.tsx │ │ │ ├── push.useQueryStates.tsx │ │ │ ├── referential-stability.useQueryState.tsx │ │ │ ├── referential-stability.useQueryStates.tsx │ │ │ ├── repro-1099.useQueryState.tsx │ │ │ ├── repro-1099.useQueryStates.tsx │ │ │ ├── repro-1365.tsx │ │ │ ├── routing.useQueryState.other.tsx │ │ │ ├── routing.useQueryState.tsx │ │ │ ├── routing.useQueryStates.other.tsx │ │ │ ├── routing.useQueryStates.tsx │ │ │ ├── scroll.tsx │ │ │ ├── shallow.useQueryState.tsx │ │ │ ├── shallow.useQueryStates.tsx │ │ │ └── trailing-slash.tsx │ │ ├── tsconfig.json │ │ ├── turbo.json │ │ └── vite.config.js │ ├── examples/ │ │ ├── next-app/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── next.config.ts │ │ │ ├── package.json │ │ │ ├── postcss.config.mjs │ │ │ ├── src/ │ │ │ │ ├── app/ │ │ │ │ │ ├── _components/ │ │ │ │ │ │ ├── filter.tsx │ │ │ │ │ │ ├── pagination.tsx │ │ │ │ │ │ └── users-list.tsx │ │ │ │ │ ├── globals.css │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── searchParams.tsx │ │ │ │ └── data.ts │ │ │ └── tsconfig.json │ │ ├── package.json │ │ └── trpc/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app/ │ │ │ ├── components/ │ │ │ │ ├── inverted-coordinates.tsx │ │ │ │ └── random-coordinates.tsx │ │ │ ├── root.tsx │ │ │ ├── routes/ │ │ │ │ ├── api/ │ │ │ │ │ └── trpc.ts │ │ │ │ └── index.tsx │ │ │ ├── routes.ts │ │ │ ├── search-params.ts │ │ │ ├── server/ │ │ │ │ └── trpc.ts │ │ │ └── utils/ │ │ │ └── trpc.ts │ │ ├── package.json │ │ ├── react-router.config.ts │ │ ├── server.mjs │ │ ├── tsconfig.json │ │ └── vite.config.ts │ ├── nuqs/ │ │ ├── .gitignore │ │ ├── adapters/ │ │ │ ├── custom.d.ts │ │ │ ├── next/ │ │ │ │ ├── app.d.ts │ │ │ │ └── pages.d.ts │ │ │ ├── next.d.ts │ │ │ ├── react-router/ │ │ │ │ ├── v6.d.ts │ │ │ │ └── v7.d.ts │ │ │ ├── react-router.d.ts │ │ │ ├── react.d.ts │ │ │ ├── remix.d.ts │ │ │ ├── tanstack-router.d.ts │ │ │ └── testing.d.ts │ │ ├── package.json │ │ ├── scripts/ │ │ │ └── prepack.sh │ │ ├── server.d.ts │ │ ├── src/ │ │ │ ├── adapters/ │ │ │ │ ├── custom.ts │ │ │ │ ├── lib/ │ │ │ │ │ ├── context.ts │ │ │ │ │ ├── defs.ts │ │ │ │ │ ├── key-isolation.ts │ │ │ │ │ ├── patch-history.browser.test.ts │ │ │ │ │ ├── patch-history.ts │ │ │ │ │ └── react-router.ts │ │ │ │ ├── next/ │ │ │ │ │ ├── app.ts │ │ │ │ │ ├── impl.app.ts │ │ │ │ │ ├── impl.pages.test.ts │ │ │ │ │ ├── impl.pages.ts │ │ │ │ │ └── pages.ts │ │ │ │ ├── next.ts │ │ │ │ ├── react-router/ │ │ │ │ │ ├── v6.ts │ │ │ │ │ └── v7.ts │ │ │ │ ├── react-router.ts │ │ │ │ ├── react.ts │ │ │ │ ├── remix.ts │ │ │ │ ├── tanstack-router.ts │ │ │ │ └── testing.ts │ │ │ ├── api.test.ts │ │ │ ├── cache.test.ts │ │ │ ├── cache.ts │ │ │ ├── defs.ts │ │ │ ├── index.server.ts │ │ │ ├── index.ts │ │ │ ├── lib/ │ │ │ │ ├── compare.test.ts │ │ │ │ ├── compare.ts │ │ │ │ ├── compose.test.ts │ │ │ │ ├── compose.ts │ │ │ │ ├── debug.test.ts │ │ │ │ ├── debug.ts │ │ │ │ ├── emitter.test.ts │ │ │ │ ├── emitter.ts │ │ │ │ ├── errors.ts │ │ │ │ ├── queues/ │ │ │ │ │ ├── debounce.test.ts │ │ │ │ │ ├── debounce.ts │ │ │ │ │ ├── rate-limiting.ts │ │ │ │ │ ├── reset.ts │ │ │ │ │ ├── throttle.test.ts │ │ │ │ │ ├── throttle.ts │ │ │ │ │ ├── useSyncExternalStores.browser.test.ts │ │ │ │ │ └── useSyncExternalStores.ts │ │ │ │ ├── safe-parse.ts │ │ │ │ ├── search-params.ts │ │ │ │ ├── sync.browser.test.tsx │ │ │ │ ├── sync.ts │ │ │ │ ├── timeout.test.ts │ │ │ │ ├── timeout.ts │ │ │ │ ├── url-encoding.browser.test.ts │ │ │ │ ├── url-encoding.ts │ │ │ │ ├── with-resolvers.test.ts │ │ │ │ └── with-resolvers.ts │ │ │ ├── loader.test.ts │ │ │ ├── loader.ts │ │ │ ├── parsers.test.ts │ │ │ ├── parsers.ts │ │ │ ├── serializer.test.ts │ │ │ ├── serializer.ts │ │ │ ├── standard-schema.test.ts │ │ │ ├── standard-schema.ts │ │ │ ├── testing.ts │ │ │ ├── useQueryState.browser.test.tsx │ │ │ ├── useQueryState.ts │ │ │ ├── useQueryStates.browser.test.tsx │ │ │ └── useQueryStates.ts │ │ ├── testing.d.ts │ │ ├── tests/ │ │ │ ├── cache.test-d.ts │ │ │ ├── components/ │ │ │ │ └── repro-1099.tsx │ │ │ ├── parsers.test-d.ts │ │ │ ├── serializer.test-d.ts │ │ │ ├── useQueryState.test-d.ts │ │ │ └── useQueryStates.test-d.ts │ │ ├── tsconfig.build.json │ │ ├── tsconfig.json │ │ ├── tsdown.config.ts │ │ ├── turbo.json │ │ ├── vitest.browser.setup.ts │ │ ├── vitest.config.ts │ │ └── vitest.setup.ts │ ├── res/ │ │ └── package.json │ └── scripts/ │ ├── next-release-analyser.ts │ ├── package.json │ ├── release-notes-automation.test.ts │ ├── release-notes-automation.ts │ └── tsconfig.json ├── pnpm-workspace.yaml └── turbo.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .agents/docs/adapter-development.md ================================================ # Adapter Development Guide for adding framework adapters to nuqs. ## Overview Adapters wrap the app root and provide the minimal translation layer between nuqs and framework routing APIs. - **Next.js app router:** `nuqs/adapters/next/app` - **Next.js pages router:** `nuqs/adapters/next/pages` - **React SPA:** `nuqs/adapters/react` - **Remix:** `nuqs/adapters/remix` - **React Router v6:** `nuqs/adapters/react-router/v6` - **React Router v7:** `nuqs/adapters/react-router/v7` - **TanStack Router:** `nuqs/adapters/tanstack-router` - **Testing:** `nuqs/adapters/testing` ## Adding a New Framework Adapter ### Checklist 1. **Mirror existing adapter API surface** - Ensure the exported provider component matches established patterns - Use consistent naming and parameter shapes 2. **Implement minimal feature parity** - Read/query: Parse current search params - Push/replace history: Update URL without full reload - Batching: Support merging multiple updates per tick 3. **Create e2e bench** - Add test application under `packages/e2e/` - Cover both App Router and Pages Router if applicable 4. **Documentation** - Update README Adapters section - Add docs content page explaining adapter setup 5. **Test coverage** - Unit tests for adapter integration - E2E tests for framework-specific behaviors ### Key Requirements - Adapter must support `shallow` option semantics (when applicable to framework) - Handle history `push` vs `replace` operations correctly - Ensure batch queue integrity (updates per key merged while preserving final state) - No memory leaks (listeners removed on unmount) ### Server-Side Utilities When adding adapter support, consider server utilities: - **Loader:** `createLoader(parsers[, { urlKeys }])` for one-off parsing - **Cache:** `createSearchParamsCache(parsers)` for nested Server Components (Next.js app router) - **Serializer:** `createSerializer(parsers[, { urlKeys }])` for canonical URLs / links - Import server helpers from `'nuqs/server'` (avoids the `"use client"` directive) These should work identically across adapters where applicable. ## Options Semantics When implementing adapter support: - **`history`:** `'replace'` (default) or `'push'` - **`shallow`** (Next.js only): Default true (client-first). Set false to trigger RSC / SSR invalidation - **`throttleMs`:** ≥50ms (ignored if lower). Only URL & server notification are throttled, not in-memory state - **`startTransition`:** Pass from `React.useTransition` when using `shallow: false` for loading states Override per-update via second argument to setter: `setValue(v, { history, shallow, throttleMs })` ## Architectural Flow 1. Hook reads initial value from current `window.location.search` 2. Local React state mirrors parsed value 3. Setter enqueues mutation intent (key → serialized value | delete) 4. Batch flush (throttled) applies merged changes to History API (push/replace) 5. Promise resolves with updated `URLSearchParams` 6. If `shallow: false`: uses router APIs to trigger server-side rendering / data fetching ## Extensibility - Prefer composition (wrapping adapter) over modifying core adapter - Keep adapter interfaces thin (translate framework navigation to common history operations) - Avoid duplicating logic across adapters (prefer shared utility) ================================================ FILE: .agents/docs/api-design.md ================================================ # API Design & Architecture Guide for maintaining API stability, designing extensions, and understanding the architecture. ## Core Architecture ### Flow 1. **Initialization:** Hook reads initial value from current `window.location.search` 2. **Local State:** React state mirrors parsed value 3. **Mutation Enqueue:** Setter enqueues mutation intent (key → serialized value | delete) 4. **Batch & Throttle:** Multiple `setState` calls in one tick are merged 5. **Flush to URL:** Batch flush (throttled ≥50ms) applies merged changes to History API (push/replace) 6. **Promise Resolution:** Returns when URL update flushes; cache per batch 7. **Server Trigger:** If `shallow: false`, uses router APIs to trigger server-side rendering / data fetching ### Batch Queue Integrity - **Key merging:** Updates for the same key within one tick are coalesced (final state wins) - **Final value preservation:** Last write for each key determines the output - **No reordering:** Order of keys in URL is stable ## Design Principles ### 1. URL as Single Source of Truth - URL shape defines state shape - Parsing must be deterministic - Serialization must be lossless ### 2. Type Safety - Hooks return typed values matching parser output - Builder chaining preserves types - Type exports are part of public API ### 3. Zero Dependencies & Bundle Size - No external dependencies - Avoid side effects in module top-level (affects tree shaking) - Keep parse/serialize fast and lightweight - Throwing in parsers has bundle cost (return `null` instead) ### 4. Backward Compatibility Before modifying core logic in `packages/nuqs`: 1. **Assess API surface impact** - Type exports - Builder chaining - Hook signatures 2. **Maintain backward compatibility** unless intentional breaking change - Breaking changes require justification - Provide migration notes in PR body 3. **Validate types** with `pnpm test --filter nuqs` (includes TS type tests) ## Performance & Reliability ### Batch Efficiency - Merging updates per key while preserving final state - Single URL write per flush cycle - No synchronous expensive operations inside parse/serialize ### Memory Management - Ensure no memory leaks - Remove listeners on unmount - Clear event handler references ### URL Determinism - Keep serialization deterministic - Use stable ordering for multiple keys - Consistent formatting ## Extensibility Guidelines When extending nuqs: ### Composition Over Modification - Prefer wrapping parsers over modifying core hook - Create adapters for new frameworks instead of baking support in core - Use builder pattern for optional behaviors ### Code Organization - Add generic utilities under internal helpers module if reused ≥2 places - Keep adapter interfaces thin - Translate framework navigation to common history operations ### Builder Pattern - Use `.withDefault()` for defaults - Use `.withOptions()` for behavior customization - Keep chaining lightweight ## Safety Checklist for Core Changes Do not: - Introduce side effects in module top-level (tree shaking impact) - Use non-standard browser APIs without guards - Increase bundle size significantly (maintain zero dependencies) - Export internal implementation details - Break existing type signatures Do: - Test types with type-level tests (`.test-d.ts`) - Provide type exports alongside implementation - Document API changes in README - Validate with full test suite ================================================ FILE: .agents/docs/git-workflow.md ================================================ # Release & Git Workflow Guide for versioning, commits, pull requests, and release process. ## Conventional Commits All commits follow the Conventional Commits specification. This is enforced by review. ### Format ``` ():