{"id":15064446,"url":"https://github.com/ernxst/svelte-query-params","last_synced_at":"2026-04-06T04:07:03.704Z","repository":{"id":223190064,"uuid":"723765788","full_name":"Ernxst/svelte-query-params","owner":"Ernxst","description":"The easiest way to reactively manage query params in Svelte and SvelteKit applications, both on the server and in the browser.","archived":false,"fork":false,"pushed_at":"2025-02-24T18:47:08.000Z","size":895,"stargazers_count":13,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-06T04:06:58.582Z","etag":null,"topics":["hooks","query","query-parameters","query-params","querystring","reactivity","search","search-parameters","search-params","svelte","sveltekit","url"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ernxst.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"Ernxst"}},"created_at":"2023-11-26T17:40:41.000Z","updated_at":"2025-02-24T17:54:41.000Z","dependencies_parsed_at":"2024-02-18T22:23:15.986Z","dependency_job_id":null,"html_url":"https://github.com/Ernxst/svelte-query-params","commit_stats":null,"previous_names":["ernxst/svelte-query-params"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ernxst%2Fsvelte-query-params","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ernxst%2Fsvelte-query-params/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ernxst%2Fsvelte-query-params/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ernxst%2Fsvelte-query-params/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ernxst","download_url":"https://codeload.github.com/Ernxst/svelte-query-params/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248217083,"owners_count":21066633,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hooks","query","query-parameters","query-params","querystring","reactivity","search","search-parameters","search-params","svelte","sveltekit","url"],"created_at":"2024-09-25T00:18:35.484Z","updated_at":"2026-04-06T04:07:03.652Z","avatar_url":"https://github.com/Ernxst.png","language":"TypeScript","funding_links":["https://github.com/sponsors/Ernxst"],"categories":[],"sub_categories":[],"readme":"# Svelte Query Params\n\nThe easiest way to reactively manage query params in Svelte _and_ SvelteKit applications, both on the server and in the browser. Built for Svelte 5 and integrates with existing validation libraries to parse, coerce and transform query params into the data your application needs.\n\n## Installation\n\n[`svelte^5`](https://svelte-5-preview.vercel.app/docs/introduction) is required:\n\n```bash\nnpm install svelte-query-params svelte@next\n```\n\n```bash\npnpm install svelte-query-params svelte@next\n```\n\n```bash\nyarn add svelte-query-params svelte@next\n```\n\n```bash\nbun install svelte-query-params svelte@next\n```\n\n`svelte` requires a version of `5.0.0-next.169` or newer as it [renamed a public API](https://github.com/sveltejs/svelte/releases/tag/svelte%405.0.0-next.169) that this library uses.\n\nBy default, `svelte-query-params` uses [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) to handle interpreting the location string, which means it does not decode `null` and has limited handling of other more advanced URL parameter configurations. If you want access to those features, add a third-party library like query-string and tell [svelte-query-params to use it](#options).\n\n## Features\n\n- **Reactivity**: The library providies a reactive object that reflects the current state of query parameters.\n\n- **Browser and Server Support**: The utility is designed to work seamlessly in both browser and server environments.\n\n- **Customizable Validators**: Define validators for each query parameter to ensure proper data types and constraints.\n\n- **Debounced Updates**: Optionally debounce updates to query parameters to optimize performance.\n\n- **Event Handling**: Automatically handles `popstate` events for accurate synchronisation with browser history.\n\n- **Serialisation**: Control how query params are serialised into strings to the browser\n\n- **Multi-value params**: Supports multi-value query parameters with ease\n\n## Usage\n\nIn some lib file e.g., `src/lib/params.ts`:\n\n```javascript\nimport { createUseQueryParams } from \"svelte-query-params\";\n\n// Define validators for query parameters\nconst validators = {\n  page: (value) =\u003e typeof value === \"number\" \u0026\u0026 value \u003e 0,\n  q: (value) =\u003e typeof value === \"string\",\n};\n\n// Create the hook\nexport const useQueryParams = createUseQueryParams(validators);\n```\n\n`createUseQueryParams` returns a hook, rather than the reactive object itself, as the reactive nature may be lost when exporting and importing these files.\n\nThen you can use this hook in your Svelte components:\n\n```svelte\n\u003cscript\u003e\n  import { useQueryParams } from \"$lib/params\"; // Import assuming SvelteKit\n  import { page } from \"$app/stores\";\n\n  const [params, helpers] = useQueryParams($page.url); // You must pass the URL\n\n  // Access query parameters\n  console.log(params.page); // Current 'page' value\n  console.log(params.q); // Current 'q' value\n\n  // Set query parameters\n  params.page = 1;\n  params.q = \"example\";\n\n  // Raw query params from the browser, all as strings\n  helpers.raw;\n\n  // All query params, including those that were not set in schema\n  helpers.all;\n\n  // Readonly search string, with the ? prefix\n  helpers.search;\n\n  // Update all query parameters in bulk\n  helpers.update({ page: 2, q: 'shoes' });\n\n  // Apply partial updates to query params\n  helpers.update({ page: 3 });\n\n  // Remove query parameters\n  helpers.remove(\"q\");\n\n  // Unsubscribe from popstate events\n  helpers.unsubscribe();\n\n  // Access query keys\n  helpers.keys();\n\n  // Access entries:\n  helpers.entries();\n\u003c/script\u003e\n\n\u003cp\u003e\n  Currently on page {params.page}, searching for {params.q}\n\u003c/p\u003e\n\n\u003c!-- Bind the 'q' query param to the input --\u003e\n\u003cinput name=\"search\" bind:value={params.q}\u003e\n```\n\n## Validators\n\n`svelte-query-params` supports [`zod`](https://github.com/colinhacks/zod), [`valibot`](https://github.com/colinhacks/zod) and function validators to define the schema for query params. Therefore, you do not need to learn an extra API for validating data.\n\nWhen using `zod` or `valibot`, you do not need to wrap your schema\nin zod `z.object({ ... })` or valibot `object`:\n\n```javascript\nimport { z } from \"zod\";\nimport { createUseQueryParams } from \"svelte-query-params\";\n\nconst useQueryParams = createUseQueryParams({\n  page: z.number(),\n  q: z.string()\n});\n```\n\nBut you can if you want.\n\nNote that it is possible to mix and match the schemas if needed:\n\n```javascript\nimport { z } from \"zod\";\nimport { string } from \"valibot\";\nimport { createUseQueryParams } from \"svelte-query-params\";\n\nconst useQueryParams = createUseQueryParams({\n  page: (value) =\u003e typeof value === \"number\" \u0026\u0026 value \u003e 0,\n  sort: string(),\n  q: z.string()\n});\n```\n\n### Array Values\n\nWith a function validator, you may receive the param as either a string, an array of strings, or undefined. As a result, you must handle all three cases to support multi-value params:\n\n```javascript\nconst validators = {\n  categories: (value) =\u003e {\n    if (!value) return []\n    return Array.isArray(value) ? value : [value]\n  }\n}\n```\n\nWith Zod, you need to handle the case where there's either 0 or 1 query param value as this library will not infer this as an array beforehand. You must define your array parameter like:\n\n```javascript\nimport { z } from \"zod\";\n\nz.object({\n  categories: z\n    .union([z.string().array(), z.string()])\n    .default([])\n    .transform((c) =\u003e (Array.isArray(c) ? c : [c])),\n})\n```\n\nThe union between a string and array of strings handles 1 or more query params; a default is set to the empty array to allow the parameter to be omitted from the URL and it's transformed at the end to convert the single value param into an array.\n\nIn the same manner, with Valibot:\n\n```javascript\nimport * as v from \"valibot\";\n\nv.object({\n  categories: v.pipe(\n    v.optional(v.union([v.array(v.string()), v.string()]), []),\n    v.transform((c) =\u003e (Array.isArray(c) ? c : [c]))\n  ),\n});\n```\n\n## Options\n\n`createUseQueryParams` takes an options object as the second argument, with the following properties:\n\n| Option      | Default           | Description                                                                                                                                                                                                                           |\n|-------------|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `windowObj` | `window`          | (Optional) Provide a custom implementation of [`window`](https://developer.mozilla.org/en-US/docs/Web/API/Window). It must implement: [`Window.prototype.location`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location), [`Window.prototype.history`](https://developer.mozilla.org/en-US/docs/Web/API/Window/history), [`EventTarget.prototype.addEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) and [`EventTarget.prototype.removeEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener). |\n| `debounce`  | `0`               | (Optional) The delay in milliseconds before updating the browser URL when the reactive object is updated. This is useful in situations where URL updates happen frequently, e.g., on every keystroke. Note that this only affects the browser URL - the reactive object will always update immediately.                                                          |\n| `serialise` | `JSON.stringify`  | (Optional) Control how query params are serialized to the URL. Note that this is **NOT** for encoding values into URI components - it serializes objects into strings, which will then be encoded internally. This is used for serialising complex objects like dates.                                                                                                                              |\n| `adapter`   | [`browser`](#browser)        | (Optional) Provide a custom adapter that controls fetching/updating query params on both the server and in the browser.                                                                                                    |\n\n### Example\n\n```javascript\nimport { createUseQueryParams } from \"svelte-query-params\";\n\nconst useQueryParams = createUseQueryParams({ ... }, { \n  ... // Options here\n})\n```\n\n## Adapters\n\nAs mentioned previously, adapters control how the URL is fetched and updated, both on the server and in the browser. As such, any adapter needs to implement the following interface:\n\n- `isBrowser: () =\u003e boolean` - Returns `true` when are in the browser, and `false` otherwise.\n\n- `server` - A property with the following methods:\n  - `save(search: string) =\u003e void` - Update the server URL. Note that the `search` string has the `?` prefixed.\n\n- `browser` - A property with the following methods:\n  - `read() =\u003e URL | Location` - Retrieve the browser URL.\n  - `save(search: string, hash: string) =\u003e void` - Update the browser URL. Note that the `search` string has the `?` prefixed and the `hash` string has the `#` prefixed.\n\nTo create your own adapter, you can import the `Adapter` type from `svelte-query-params/adapter` for intellisense, or use `defineAdapter` also exported by `svelte-query-params/adapter`:\n\n```typescript\nimport type { Adapter } from 'svelte-query-params/adapter';\nimport { defineAdapter } from 'svelte-query-params/adapter';\n\nexport const myAdapter: Adapter = { ... }\nexport const myAdapter = defineAdapter({ ... });\n```\n\n### Browser\n\nThis is the default adapter when no adapter is specified and can only be used\nin the browser i.e., fetching the URL on the browser returns an empty search string and hash and updating the query params on the server is a no-op.\n\n```javascript\nimport { createUseQueryParams } from \"svelte-query-params\";\nimport { browser } from \"svelte-query-params/adapters/browser\";\n\nconst useQueryParams = createUseQueryParams({ ... }, { \n  adapter: browser({ ... })  \n})\n```\n\n#### Browser Adapter Options\n\n- `windowObj`: (Optional) Provide a custom implementation of [`window`](https://developer.mozilla.org/en-US/docs/Web/API/Window). It must implement:\n  - [`Window.prototype.location`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location)\n  - [`Window.prototype.history`](https://developer.mozilla.org/en-US/docs/Web/API/Window/history)\n  - [`EventTarget.prototype.addEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)\n  - [`EventTarget.prototype.removeEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener)\n\n- `replace`: (Optional) If this is `true`, any browser query updates will not create a new browser session history item, replacing the previous one instead. If `false`, a new item will always be added to the history.\n\n### SvelteKit\n\nFor use with SvelteKit, use this adapter, instead of the [`browser`](#browser) adapter for support for interacting with query params on the server.\n\n```javascript\nimport { createUseQueryParams } from \"svelte-query-params\";\nimport { sveltekit } from \"svelte-query-params/adapters/sveltekit\";\n\nconst useQueryParams = createUseQueryParams({ ... }, { \n  adapter: sveltekit({ ... })  \n})\n```\n\n#### SvelteKit Adapter Options\n\n- `replace`: (Optional) If this is `true`, any browser query updates will not create a new browser session history item, replacing the previous one instead. If `false`, a new item will always be added to the history.\n\n## Contributing\n\nSee [Contributing Guide](CONTRIBUTING.md).\n\n## License\n\nDistributed under the MIT License. See [`LICENSE`](LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fernxst%2Fsvelte-query-params","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fernxst%2Fsvelte-query-params","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fernxst%2Fsvelte-query-params/lists"}