Skip to content


This package provides a set of helpers to be sync with the url, search parameters, change it and react to it changes.


npm i @reatom/url


Base primitive is urlAtom, it contains URL and by default initiates with a browser location.href (see Behavior for details).

You can call the urlAtom.go action with a root path to navigate programmatically.

Search parameters

There is also searchParamsAtom which derives from urlAtom and allow you to handle search params reactively. You could pick needed parameter by searchParamsAtom.lens method just by passed key or specify the type of the parameter by providing optional parse and serialize functions.

import { searchParamsAtom } from '@reatom/url'

export const filterAtom = searchParamsAtom.lens('filters')

In the code below filterAtom is a mutable atom which changes will be synced with the passed search parameter. If you want to setup the sync for some other atom, you could use withSearchParamsPersist decorator.

import { reatomNumber } from '@reatom/primitives'
import { withSearchParamsPersist } from '@reatom/url'

export const pageAtom = reatomNumber(0, 'pageAtom').pipe(
  withSearchParamsPersist('page', Number),

Now you have handy increment and decrement actions in pageAtom and synchronization with “page” search parameter.


Here are the types of the key features.

// exported by `urlAtom`
export interface UrlAtom extends AtomMut<URL> {
  go: Action<[path: `/${string}`], URL>
  settingsAtom: AtomMut<AtomUrlSettings>

// exported by `searchParamsAtom`
export interface SearchParamsAtom extends Atom<Rec<string>> {
  set: Action<[key: string, value: string], void>
  /** create AtomMut which will synced with the specified search parameter */
  lens: <T = string>(
    key: string,
    parse?: (value?: string) => T,
    serialize?: (value: T) => string,
  ) => AtomMut<T>


When urlAtom is first read (directly or indirectly through searchParamsAtom), a subscription to the popstate event and interception of the document.body click appears. If you don’t want to handle and prevent link clicks, you could call setupUrlAtomBrowserSettings(ctx, /* shouldCatchLinkClick: */false) action.

If you need to run your code in a different environment (unit tests or SSR) you could replace the url handling behavior by calling setupUrlAtomSettings action with a function for getting URL (init parameter) and optional sync parameter for subscription to URL change.

// a server handler
export const handler = async (req) => {
  const ctx = createCtx()
  const url = new URL(req.url!, `http://${}`)
  setupUrlAtomSettings(ctx, () => url)
  // do your stuff...