Conceptparamsync > concepts
Clean URL Policy
The automatic parameter omission engine keeping Next.js query strings clean, human-readable, and SEO canonical.
The Problem
Standard Next.js applications using manual URLSearchParams serialize empty strings (?q=), empty lists (?tags=), and initial default parameters (?page=1&status=all). This creates unsightly URLs, ruins link sharing, harms SEO canonical parity, and pollutes analytics attribution dashboards.
The paramsync Solution
paramsync enforces a strict Clean URL Policy by default. Any parameter whose state value equals its registered default, is an empty string (""), an empty array ([]), or null/undefined is purged immediately from the query string without altering internal component state.
Key Architectural Takeaways
- Canonical URLs: Root views remain /products rather than /products?q=&page=1.
- Automatic Purge: Resetting a controlled input to empty string deletes the key from the URL instantly.
- Deep Equality Comparison: Arrays and objects are checked via areValuesEqual() against parser defaults.
- Zero Typing Lag: Controlled inputs update React state immediately while background URL updates reflect the clean policy.
Implementation Pattern
TSPattern.tsx
'use client'; import { useQueryState, parseAsString, parseAsArray, parseAsInteger } from 'paramsync'; export function CleanFilterBar() { // Omitted from URL when search is "" const [search, setSearch] = useQueryState('q', parseAsString.withDefault('')); // Omitted from URL when categories is [] const [categories, setCategories] = useQueryState('cat', parseAsArray(parseAsString)); // Omitted from URL when page is 1 const [page, setPage] = useQueryState('page', parseAsInteger.withDefault(1)); // Result when defaults are set: https://paramsync.vercel.app/products (100% Clean) // Result when filtering: https://paramsync.vercel.app/products?q=shoes&cat=running&page=2 return <div>...</div>;}main|paramsync
TypeScript JSX|UTF-8|Ln 18, Col 1
Clean URL Decision Matrix
1. value === "" (empty string) => Key removed from URL.
2. value === defaultValue => Key removed from URL.
3. Array.isArray(value) && value.length === 0 => Key removed from URL.
4. value === null || value === undefined => Key removed from URL.