Clean URL Policy
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 JSXLn 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.
;