sveltekit-search-params: query parameters that behave like Svelte state
The easiest way to read and WRITE from query parameters in sveltekit.
At a glance
- What is it?
- sveltekit-search-params turns the URL query string into a reactive object you can both read and write, with per-parameter encoding, decoding and default values. It is SvelteKit only, by design, and the README is blunt that the default value behaviour does not work during server side rendering.
- Who is it for?
- sveltekit-search-params fits a SvelteKit app where filters, tabs, pagination and sort order live in the URL and the user expects the back button to work, and where the developer wants typed access to those values rather than string comparisons. It does not fit a plain Svelte project, because it uses APIs only SvelteKit provides, and it does not fit a server-rendered page that must show the right value on first paint.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Reading and writing the query string as if it were state
sveltekit-search-params describes itself as the fastest way to read and write from query search params in SvelteKit, and the writing half is the interesting part. The entry point is a single function, queryParameters, which returns an object of the parameters present on the page.
<script lang="ts">
import { queryParameters } from 'sveltekit-search-params';
const params = queryParameters();
</script>
<pre>
{JSON.stringify(params, null, 2)}
</pre>Because the returned object is reactive, assigning to a property of it updates the URL, and the README's own framing is that you can treat your query parameters just like normal state in Svelte. An input bound to a parameter value becomes the filter for the page. That is the difference from the usual approach of reading page.url.searchParams in a load function and pushing values back with goto, where every state change becomes a navigation call you have to write by hand. Here the store is the URL and the URL is the store. The default type of every value is string, which the README states plainly.
Declaring the parameters you expect, and what happens when they are missing
Most of the time you know which parameters a page depends on, and the library lets you say so at initialization. You pass an object of expected parameters, and those are merged with the actual query parameters whether or not they are present in the URL.
<script lang="ts">
import { queryParameters } from 'sveltekit-search-params';
const params = queryParameters({
username: true,
});
</script>On a page at /?framework=svelte&isCool=true the result gains a username key with a null value, and if the URL includes username=paoloricciuti then the same key holds that string instead. The value is the point of the feature. A parameter you declared is guaranteed to exist as a property, so the component can bind to it and read it without a null check, and the URL stays the single source of truth. The tradeoff is that a declared parameter is also a parameter the component will write into the URL once it has a value, which is convenient for filters and surprising if you wanted a read-only parameter.
Encode and decode per parameter, so the URL stops being a string soup
The problem the library is really solving is that query parameters are strings while application state is not. During initialization you can specify an object with an encode and a decode property for a parameter, and those transform the value in both directions.
<script lang="ts">
import { queryParameters } from 'sveltekit-search-params';
const params = queryParameters({
username: true,
isCool: {
encode: (booleanValue) => booleanValue.toString(),
decode: (stringValue) =>
stringValue !== null && stringValue !== 'false',
},
});
</script>With a decode function that treats the string 'false' as false and null as false, the isCool parameter arrives at the component as a real boolean. The same logic has to work in reverse when the value is written back, which is what the encode half is for. The README also handles the case where the parameter is missing entirely, and the decoding of a missing value still produces false rather than undefined, which matters because a boolean filter and an undefined filter behave differently in a template.
Default values, and the server side rendering catch
There is a third field in the parameter object, defaultValue, and the README gives a worked example with a count parameter that decodes to a parsed integer and defaults to 10.
<script lang="ts">
import { queryParameters } from 'sveltekit-search-params';
const params = queryParameters({
username: true,
count: {
encode: (value: number) => value.toString(),
decode: (value: string | null) => (value ? parseInt(value) : null),
defaultValue: 10,
},
});
</script>The behaviour is worth reading carefully. The default value makes the query parameter take that value and the URL change as soon as the page is rendered in the browser, but only if the parameter is not already present, and only the first time the application renders. The warning underneath is the real limitation: you cannot run goto on the server, so if the page is server side rendered it will still have the default value but will not actually navigate until the client bundle loads. In other words, the default is applied on the server for the initial HTML, and the URL catches up once the client hydrates. If the URL and the rendered output need to agree at first paint, this is the part of the library to think hard about.
ssp helpers for the transforms you would otherwise write by hand
Writing an encode and a decode pair is easy and tedious in equal measure, and the library ships helpers for the common cases, exported under the name ssp from the same package.
<script lang="ts">
import { ssp, queryParameters } from 'sveltekit-search-params';
const params = queryParameters({
username: true,
isCool: ssp.boolean(),
});
</script>The README says there are six helpers in total, all exported from that ssp object, and that using them produces the same output as the hand-written version while being far more readable. The helper also accepts a default, so ssp.count(10) gives a numeric parameter with a default of 10 in a single expression rather than an object with three fields. This is a small feature that removes a lot of repetition, since most applications end up needing the same handful of transforms for booleans, numbers and lists.
A SvelteKit-only package, and a major version that broke things
The README opens with a warning that is worth heeding. The package is meant to be used with SvelteKit, as the name suggests, and because it uses APIs that are only present in SvelteKit it will not work in a normal Svelte project. That is a real constraint, not a caveat. The library reaches into the routing and navigation internals that SvelteKit provides, which is exactly what lets it write to the URL reactively, and that mechanism does not exist outside the framework. The release history shows a major version jump: v4.0.1 on 2026-10-06, then v3.0.0 on 2024-07-28, then v2.1.2 in March 2024. A gap of two years between 3.0.0 and 4.0.1 suggests a substantial change in the API, so code written against v3 is worth checking against the current documentation. The repository is not archived and the last push was on 2026-10-20.
Small project, careful release process
The repository is small and focused. The source sits in a src directory, there is a playground directory for manual testing, a tests directory, a static directory for the landing page, and the usual configuration files including a prettier config, an eslint config, a vite config and a svelte config. The package scripts show a release process built on changesets, with the release script running the build and then changeset publish, and the contributing section asking that function changes intended for release include a changeset. The build script runs svelte-kit sync, then svelte-package, then publint, which is the linter that catches packaging mistakes before they reach npm. Tests are split into unit tests run by vitest and integration tests run by playwright, with a UI mode for the integration suite, and there is a playwright config at the root. The library is MIT licensed, authored by Paolo Ricciuti, and the homepage is a Netlify-hosted documentation site.
Editorial conclusion
sveltekit-search-params fits a SvelteKit app where filters, tabs, pagination and sort order live in the URL and the user expects the back button to work, and where the developer wants typed access to those values rather than string comparisons. It does not fit a plain Svelte project, because it uses APIs only SvelteKit provides, and it does not fit a server-rendered page that must show the right value on first paint. Verify first that your parameters need two-way binding rather than one-way reading, read the server side rendering warning before relying on default values, and pin version 4.x since the jump from 3.0 changed the API.
Frequently asked questions
How do I install sveltekit-search-params?
Install it with npm, using npm install sveltekit-search-params@latest -D. The README notes the package is meant for SvelteKit only, because it uses APIs that are not present in a normal Svelte project.
How do I write to query parameters in sveltekit-search-params?
Assign to a property of the object returned by queryParameters. The returned object is reactive, so changing a property updates the URL, which means you can bind an input directly to a parameter and treat query parameters like normal Svelte state.
How do I decode a query parameter into a boolean or a number?
Pass an object with encode and decode functions for that parameter when you call queryParameters, so the value is transformed in both directions. You can also use the built-in helpers exported as ssp, such as ssp.boolean() or ssp.count(10) which also sets a default value.
Does the default value work with server side rendering?
Partly. The README warns that you cannot run goto on the server, so a server side rendered page will have the default value but will not actually navigate until the client bundle loads. The URL also only changes if the parameter is not already present, and only on the first render.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/paoloricciuti-sveltekit-search-params)Was this useful?