Changelog
All notable changes to this project will be documented in this file.
1.6.0 (2026-09-04)
Features
- core: Support nested object serialization and deserialization in query parameters using bracket notation.
appendQuery,buildPath, and.build()serialize nested objects into standard bracket notation (e.g.{ filter: { status: "active", author: { id: 1 } } }→filter[status]=active&filter[author][id]=1). When updating existing keys,appendQueryautomatically cleans up existing nested keys. InextractQueryFromPath, bracket-notated query strings are automatically parsed back into deeply nested JavaScript objects. - next:
useNavigateTo()now returns a function with a.prefetch(path, options?)method, wrappingrouter.prefetch()fromnext/navigation. The options type is derived automatically from the Next.jsAppRoutersignature via theParametersutility type — no manual type annotation needed. - hooks & next:
useTypedSearchParams<T>()now accepts a generic type parameterT extends QueryParams. PassingTgives you a strongly-typedqueryobject and a constrained setter. OmittingTfalls back to the previous untypedQueryParamsshape — fully backwards-compatible. - types: New exported type
QueryParamValue— the union type for a single query parameter value (string | number | boolean | array | null | undefined | QueryParams). Previously this was inlined inside theQueryParamsdefinition and not accessible to consumers.
Bug Fixes
- types: Replace
anywithunknownin thesetDeepPropertyinternal helper (src/core/query.ts). Theobjandvalueparameters now useRecord<string, unknown>andunknownrespectively, eliminating implicitanyfrom the library's type surface and satisfying strictnoImplicitAny/eslint@typescript-eslint/no-explicit-anyrules. - types:
useNavigateToNext.js prefetch options were previously typed as{ kind?: any }with anas anycast. They now useParameters<ReturnType<typeof useRouter>["prefetch"]>[1], which automatically mirrors whatever Next.js exports — no risk of drift between library and framework types.
Refactoring
- next: Removed redundant
typeof window === 'undefined'SSR guards from all Next.js hooks (useActivePath,useNavigateTo,useRouteParams,useTypedSearchParams). Next.js enforces the"use client"boundary at build time, making runtime window checks unnecessary and potentially misleading to users trying to diagnose SSR issues. - next: The
useTypedSearchParamssetter now delegates to theappendQuerycore utility instead of manually constructing aURLSearchParamsstring. This guarantees consistent serialization — bracket notation for nested objects, proper array key repetition, falsy value preservation — matching the behavior ofappendQueryand.build()across the rest of the API. - hooks: The same
appendQueryrefactor applied touseTypedSearchParamsin the React Router entry point (react-routes-forge/hooks).
1.5.0 (2026-09-03)
Features
- next: Added a dedicated
react-routes-forge/nextentry point providing Next.js App Router and Pages Router equivalents of all four hooks:useActivePath,useNavigateTo,useRouteParams, anduseTypedSearchParams. All hooks are backed bynext/navigationand require"use client"in the consuming component. The API is intentionally identical to the React Router variants so switching between environments requires only changing the import path. - core: Added
buildRelativeutility for generating paths without a leading slash — useful in sub-app navigation, same-originfetchcalls, or situations where an absolute path would be incorrect. - core: Added a
localeoption tobuildPath(and.build()) for prepending an i18n locale segment to the generated URL. Accepts a locale string with or without a leading slash (e.g."fr"or"/en-US"). - hooks: Added
"use client"directives and SSR guards to React Router hooks to prevent accidental server-side execution and produce clearer error messages when hooks are called outside a client context.
Bug Fixes
- core: Improved edge case handling in
extractParamsFromPath,isActivePath, andbuildPathfor paths with consecutive slashes, empty segments, and trailing wildcards.
1.4.2 (2026-08-15)
Patch release. Internal build and type declaration fixes — no public API changes.
1.4.1 (2026-08-15)
Bug Fixes
- core:
isActivePathnow correctly respects bothexactandcaseSensitiveoptions that were previously being ignored in certain code paths. Theexact: falseprefix-matching mode was treating the path separator inconsistently. - core:
getBreadcrumbsnow orders breadcrumb items by actual path depth (number of/segments) rather than by template string length. This fixes incorrect ordering for routes whose templates happen to be longer strings but represent shallower paths.
1.4.0 (2026-08-15)
Features
- hooks: All hooks in
react-routes-forge/hooksnow work identically withreact-router-domv6,react-router-domv7,react-routerv6, andreact-routerv7 — tested and verified across all four combinations. The hooks import from a compatibility shim that resolves the correct hook regardless of which package and version is installed, eliminating the duplicate-version risk that existed when bothreact-routerandreact-router-domwere present in a monorepo.
1.3.0 (2026-08-01)
Features
- core: Static routes (paths without
:params) now have a.build(query?, options?)method attached, providing a consistent API regardless of whether a route is static or dynamic. Previously, callers had to use the route string directly for static routes and.build()only for dynamic ones. - core: Added splat (
*) segment support across the entire core API —buildPath,.build(),extractParamsFromPath,isActivePath,matchPath, andflattenRoutes. A trailing/*captures everything after it into a*param, matching React Router semantics. - core:
defineRoutesnow validates the route tree on initialization. It emits aconsole.warnin development when two different keys resolve to the same path string, or when a static route is shadowed by a more-specific dynamic route. - core: Added
appendQueryutility for appending query strings to an existing path, and updatedextractQueryFromPathto correctly ignore hash fragments when parsing. Both utilities support bracket notation for nested objects (user[name]=John) and repeated keys for arrays. - core: Added
coerceNumbersoption toextractQueryFromPathto convert numeric strings tonumbervalues (complementing the existingcoerceBooleans). Also addedclearPathCache()for resetting internal regex caches in long-running processes or between tests. - core: Exported the
RouteTreetype for annotating plain route objects before passing them todefineRoutes(). Also exportedPathParams,BuildPathOptions,FlatRoute,BreadcrumbItem,BreadcrumbOptions,StaticRoute,DynamicRoute, andMatchPathOptions. - hooks: Added
useActivePath(template, options?)— a reactive wrapper aroundisActivePaththat reads the current location viauseLocation(). Matching semantics mirror React Router'sNavLink: case-insensitive by default, trailing slashes tolerated,exact: trueby default. - hooks: Added
useTypedSearchParams(options?)— a typed, reactive wrapper for reading and writing URL query parameters. Returns a[query, setQuery]tuple; the setter generates a new URL and callsnavigate(). - hooks:
useRouteParamsnow accepts a dynamic route from yourPATHStree as an argument and infers the param names automatically from itsparamNamesarray — no manual generic required. - core:
isActivePathmatching semantics updated to mirror React Router'sNavLinkbehavior — case-insensitive by default, trailing slashes normalized,exact: truerequires a full path match. - core:
getBreadcrumbsnow accepts a staticlabelsmap ({ [routeKey]: string }) in addition to the existinglabelResolverfunction. When both are provided, the labels map takes precedence.
Bug Fixes
- core: Corrected param extraction to align with React Router's
:paramNameparsing rules. Previously, params containing uppercase letters or underscores were not matched correctly. - core: Fixed optional param segment handling (
:param?) for correct segment matching, URL encoding of param values, and correct behavior when the optional segment is absent. - hooks:
useRouteParamsnow correctly infers param types fromroute.paramNameswhen a route object is passed, rather than falling back tostring. - types:
ExtractParamskept valid for widenedDynamicRoutevalues where the template string type has been broadened tostring.
1.2.0 (2026-07-26)
Features
- core: Added hash fragment support (
#section) tobuildPathand all.build()methods via ahashoption in the options bag. The hash value is appended after the query string in the generated URL and stripped from the template when matching. - core: Added
getBreadcrumbs(routes, currentPath, options?)utility that traverses your route tree and returns a sorted array ofBreadcrumbItemobjects — one per ancestor path that is a prefix ofcurrentPath, plus the current leaf. Each item includeskey,path,label, andisCurrent. Supports alabelResolvercallback and alabelsmap for per-route label overrides. - core: Exposed
matchPath(template, options?)as a public utility. It compiles a route template into an anchoredRegExp(with optionalcaseSensitiveandendflags) for custom path matching logic outside of the hook layer.
Bug Fixes
- core: Fixed a polynomial backtracking issue in the internal route-matching regex by splitting the single regex into two sequential operations. This prevents catastrophic backtracking on deeply nested or malformed paths.
1.1.3 (2026-07-26)
Patch release. Type declaration packaging fix — no public API changes.
1.1.2 (2026-07-26)
Patch release. Build output fix for CommonJS consumers — no public API changes.
1.1.1 (2026-07-26)
Bug Fixes
- core: Fixed handling of optional param segments (
:param?) — the segment is now correctly treated as optional inbuildPath,extractParamsFromPath, andmatchPath. Previously, optional params were required at build time and caused incorrect regex matches when absent.
1.1.0 (2026-07-12)
Features
- core: Added query parameter support to
buildPathand.build(). Pass a query object as the second argument; it is serialized using repeated keys for arrays and bracket notation for nested objects. Falsy values (0,false,"") are preserved;nullandundefinedare skipped. - core: Added strict mode via
{ strict: true }in the options bag. When enabled,buildPaththrows aRangeErrorinstead of emitting aconsole.warnwhen a required param is missing. Recommended for test environments or critical navigation flows. - core: Added
flattenRoutes(routes, prefix?)utility that produces a flatFlatRoute[]array from any nested route tree — useful for sitemap generation, route auditing, or programmatic navigation menus.
Bug Fixes
- core: Implemented
appendQueryas a standalone function to replace the previous ad-hoc inline query string construction.appendQueryis used internally bybuildPathand is also exported for direct use.
1.0.3 (2026-07-11)
Patch release. Package metadata and exports field fixes.
1.0.2 (2026-07-11)
Initial public release.
- core:
defineRoutes— wraps a plain nested route object and attaches.build(params, query?, options?)to every dynamic route and.build(query?, options?)to every static route. Route values remain genuine primitive strings at runtime, ensuring they work directly with<Route path={...} />without unwrapping. - core:
buildPath(template, params, query?, options?)— standalone path builder, the underlying function powering.build(). - core:
isActivePath(pathname, template, options?)— checks whether a URL pathname matches a route template string. - core:
extractParamsFromPath(template, pathname)— extracts named param values from a real URL given a template. - core:
joinPaths(...segments)— joins path segments with correct slash handling. - core:
getParamNames(template)— returns the param names present in a template string. - core:
devWarn(message)— emits aconsole.warnin non-production environments only. - hooks:
useRouteParams<T>()— typed wrapper around React Router'suseParams. - hooks:
useNavigateTo()— typed wrapper around React Router'suseNavigatethat accepts any string or route value. - hooks:
useResolvedPath(template, params, query?, options?)— resolves a route template to a full URL string without navigating, useful forhrefgeneration.