npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tanstack-router-persist-search

v0.3.0

Published

Persist and restore TanStack Router search params per route via sessionStorage/localStorage

Readme

tanstack-router-persist-search

Remembers search params of a TanStack Router route and restores them when the user comes back to it.

Typical case: a list page with filters and pagination. The user sets ?page=3&status=active, opens an item, then clicks "Users" in the menu. Without this package they land on page 1 with no filters. With it, they are redirected back to ?page=3&status=active.

  • Zero dependencies (only @tanstack/react-router as a peer)
  • sessionStorage by default, any Storage via options
  • SSR-safe: does nothing when storage is unavailable
  • ~1 KB

Install

npm i tanstack-router-persist-search

Usage

import { createFileRoute } from '@tanstack/react-router'
import { persistSearch } from 'tanstack-router-persist-search'

export const Route = createFileRoute('/users')({
  beforeLoad: persistSearch,
})

The route id is taken from the beforeLoad context (ctx.routeId), so you don't pass it yourself.

With options, or together with other logic in beforeLoad:

beforeLoad: (ctx) => {
  persistSearch(ctx, { include: ['page', 'status'] })
  // ...the rest
},

persistSearch may throw a redirect, so code after it won't run in that case. Put anything that must always run before the call.

How it works

"Empty" below means no tracked params (see include/exclude); without options every param is tracked.

| cause | Search is empty | Search is not empty | | --------- | -------------------------- | ------------------- | | enter | redirect to saved search (if any) | save it | | stay | remove saved entry | save it | | preload | ignored | ignored |

  • Keys with undefined values are dropped before saving and when checking for emptiness, so { page: undefined } counts as empty.
  • The redirect uses replace: true, so no extra history entry is created.
  • Each route is stored separately under its route id (e.g. /users, /_layout/users/).
  • To share saved params between several routes, give them the same slot: persistSearch(ctx, { routeId: 'users-filters' }).

Persist only some params

Pass include or exclude as the second argument:

// save and restore only pagination and filters
beforeLoad: (ctx) => persistSearch(ctx, { include: ['page', 'status'] }),

// save everything except one-off params
beforeLoad: (ctx) => persistSearch(ctx, { exclude: ['token', 'highlight'] }),
  • Keys are type-checked against the route's validateSearch, with autocomplete. On routes without validateSearch any string is accepted.
  • If both are given, include is applied first, then exclude.
  • Only tracked params count when deciding whether to restore. Entering /users?tab=info with include: ['page', 'status'] redirects to /users?tab=info&page=3&status=active: untracked params from the URL are kept and saved ones are added.
  • If any tracked param is already in the URL, nothing is restored; the URL wins and is saved.
  • Saved data is filtered with the current options on restore, so changing include/exclude later never brings back a param you stopped tracking.

Custom storage

import { createSearchPersistence } from 'tanstack-router-persist-search'

export const filters = createSearchPersistence({
  key: 'my-app:search',          // default: 'search-storage'
  storage: () => localStorage,   // default: sessionStorage
})

// in a route
beforeLoad: filters.persistSearch,

API

createSearchPersistence(options?)

| Option | Type | Default | | --------- | ------------------------------- | ------------------ | | key | string | 'search-storage' | | storage | () => Storage \| undefined | sessionStorage (undefined on the server) |

Returns:

  • persistSearch(ctx, options?) — use in beforeLoad; options is { include?, exclude?, routeId? }. routeId defaults to ctx.routeId; if neither is available, it throws an error.
  • get(routeId) — saved search or undefined
  • save(routeId, search, options?) — save manually, with the same filtering
  • clear(routeId?) — clear one route, or everything when called without arguments

Default instance exports

persistSearch, getPersistedSearch, savePersistedSearch, clearPersistedSearch — the same functions bound to sessionStorage and the 'search-storage' key.

Example: a "Reset filters" button

clearPersistedSearch('/users')
navigate({ to: '/users', search: {} })

Requirements

  • @tanstack/react-router 1.x
  • TypeScript 5.4+ (the types use NoInfer)

License

MIT