{"id":211,"url":"https://github.com/thoughtspile/awesome-tiny-js","name":"awesome-tiny-js","description":"🤏 A collection of tiny JS libraries (under 2 kB) to put your bundle on a diet","projects_count":90,"last_synced_at":"2026-06-08T12:00:32.649Z","repository":{"id":117183931,"uuid":"608234505","full_name":"thoughtspile/awesome-tiny-js","owner":"thoughtspile","description":"🤏 A collection of tiny JS libraries (under 2 kB) to put your bundle on a diet","archived":false,"fork":false,"pushed_at":"2024-09-24T10:21:03.000Z","size":134,"stargazers_count":771,"open_issues_count":5,"forks_count":13,"subscribers_count":15,"default_branch":"main","last_synced_at":"2026-05-22T22:24:51.104Z","etag":null,"topics":["awesome","awesome-list","javascript","tiny","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thoughtspile.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":"contributing.md","funding":null,"license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-03-01T15:44:35.000Z","updated_at":"2026-05-17T14:56:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"70dfe962-494d-40a1-89a9-86576a796f84","html_url":"https://github.com/thoughtspile/awesome-tiny-js","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/thoughtspile/awesome-tiny-js","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtspile%2Fawesome-tiny-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtspile%2Fawesome-tiny-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtspile%2Fawesome-tiny-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtspile%2Fawesome-tiny-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thoughtspile","download_url":"https://codeload.github.com/thoughtspile/awesome-tiny-js/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtspile%2Fawesome-tiny-js/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34061123,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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"}},"created_at":"2024-01-04T17:19:34.873Z","updated_at":"2026-06-08T12:00:32.649Z","primary_language":"JavaScript","list_of_lists":false,"displayable":true,"categories":["UI Frameworks","Dates and Time","Unique ID Generation","Colors","Text Search","Footnotes","API Layer","State Managers","Routers and URL Utils","Generic Utilities","I18N","Event Emitters","Validation","Touch Gestures"],"sub_categories":["Reactive Programming","Fuzzy search","Signals"],"readme":"# Awesome Tiny JS [![Awesome](https://awesome.re/badge-flat.svg)](https://awesome.re)\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/thoughtspile/awesome-tiny-js#readme\"\u003e\n    \u003cimg src=\"./awesome-logo.png\" width=\"300\" height=\"207\"\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\nTiny front-end libraries to put your bundle on a diet. Rules:\n\n- Size is under 2 kB-ish, min + gzip, with all dependencies, except where noted.\n- For multi-purpose libraries, the size of a useful subset must be under 2 kB-ish.\n- Useful client-side. I haven't figured out participation rules for node-only libraries, and I'm not too worried about them.\n- Second-level libraries only allowed for React, Vue, Angular, svelte. \n- 100+ GitHub stars _or_ 500+ weekly npm installs to focus on tools with some community review.\n- No zero-JS (CSS- or type-only) libraries. It's not awesome-css or something.\n\n## Contents\n\n- [UI Frameworks](#ui-frameworks)\n- [Event Emitters](#event-emitters)\n- [State Managers](#state-managers)\n  - [Signals](#signals)\n  - [Reactive Programming](#reactive-programming)\n- [Routers and URL Utils](#routers-and-url-utils)\n- [API Layer](#api-layer)\n- [I18N](#i18n)\n- [Dates and Time](#dates-and-time)\n- [Generic Utilities](#generic-utilities)\n- [Validation](#validation)\n- [Unique ID Generation](#unique-id-generation)\n- [Colors](#colors)\n- [Touch Gestures](#touch-gestures)\n- [Text Search](#text-search)\n\n## UI Frameworks\n\nUI frameworks (libraries?) provide declarative templates, event bindings, and observable state to update the view. I've been generous and expanded the size limit for this category to 4.5 kB (if you're boring, count them as 2 libraries), but also increased the star limit to 2K. \n\n- [preact](https://github.com/preactjs/preact) - React-like API (pre-hooks). Cool ecosystem of similarly tiny tools and components. Highly recommended. \u003cimg align=\"top\" height=\"24\" src=\"./img/preact.svg\"\u003e\n\nThe following libraries are small and cool, but note they're about [500x less popular than preact.](https://npmtrends.com/preact-vs-hyperapp-vs-redom) Kudos for deconstrucing the very essence of a \"framework\":\n\n- [hyperapp](https://github.com/jorgebucaran/hyperapp) - vDOM framework with pure JS syntax and immutable state, \u003cimg align=\"top\" height=\"24\" src=\"./img/hyperapp.svg\"\u003e\n- [redom](https://github.com/redom/redom) - Hyperapp-style templates with _imperative_ event listeners and updates, \u003cimg align=\"top\" height=\"24\" src=\"./img/redom.svg\"\u003e\n\nNow, for the [openly experimental](https://npmtrends.com/@arrow-js/core-vs-fre-vs-hyperapp-vs-redom-vs-superfine-vs-vanjs-core) UI libraries:\n\n- [fre](https://github.com/frejs/fre) - React-like library with hooks and concurrency, \u003cimg align=\"top\" height=\"24\" src=\"./img/fre.svg\"\u003e\n- [van](https://github.com/vanjs-org/van) - vDOM-based framework optimized for no-build setups, \u003cimg align=\"top\" height=\"24\" src=\"./img/vanjs-core.svg\"\u003e\n- [superfine](https://github.com/jorgebucaran/superfine) - Hyperapp with state \u0026 effect hooks removed, \u003cimg align=\"top\" height=\"24\" src=\"./img/superfine.svg\"\u003e\n- [arrowjs](https://github.com/justin-schroeder/arrow-js) - Tagged templates + reactive data, \u003cimg align=\"top\" height=\"24\" src=\"./img/arrow-jscore.svg\"\u003e\n\nAnd if being declarative is not your thing:\n\n- [umbrella](https://github.com/franciscop/umbrella) - jQuery-style DOM manipulation library, \u003cimg align=\"top\" height=\"24\" src=\"./img/umbrellajs.svg\"\u003e\n\n## Event Emitters\n\nEvent emitter pattern is fairly easy to implement yourself, but why bother when you have these cool tools? With an arms race to build the smallest one, the limit is 0.5 kB.\n\n- [mitt](https://github.com/developit/mitt) - Plain event emitter that I use on most projects, \u003cimg align=\"top\" height=\"24\" src=\"./img/mitt.svg\"\u003e\n- [nanoevents](https://github.com/ai/nanoevents) - Nicer unsubscribe API, but no `*` event, \u003cimg align=\"top\" height=\"24\" src=\"./img/nanoevents.svg\"\u003e\n- [onfire.js](https://github.com/hustcc/onfire.js) - Also has `.once` method, \u003cimg align=\"top\" height=\"24\" src=\"./img/onfirejs.svg\"\u003e\n\n## State Managers\n\nState managers combine observable state with actions and framework bindings, intended for app-wide state.\n\n- [zustand](https://github.com/pmndrs/zustand) - Simple stores with pleasant actions and selectors. Vanilla \u003cimg align=\"top\" height=\"24\" src=\"./img/zustandvanilla.svg\"\u003e, React \u003cimg align=\"top\" height=\"24\" src=\"./img/zustand.svg\"\u003e\n- [nanostores](https://github.com/nanostores/nanostores) - Modular store with good tree-shaking support, \u003cimg align=\"top\" height=\"24\" src=\"./img/nanostores.svg\"\u003e vanilla, + React \u003cimg align=\"top\" height=\"24\" src=\"./img/nanostoresreact.svg\"\u003e extra. Supports all the top frameworks.\n- [exome](https://github.com/marcisbee/exome) - Atomic stores with lots of framework connectors, \u003cimg align=\"top\" height=\"24\" src=\"./img/exome.svg\"\u003e + React \u003cimg align=\"top\" height=\"24\" src=\"./img/exomereact.svg\"\u003e extra. Supports all the top frameworks.\n- [storeon](https://github.com/storeon/storeon) - Minimal redux-styled store with lots of framework connectors, \u003cimg align=\"top\" height=\"24\" src=\"./img/storeon.svg\"\u003e. React extra \u003cimg align=\"top\" height=\"24\" src=\"./img/storeonreact.svg\"\u003e + Vue, Svelte, Angular.\n- [unistore](https://github.com/developit/unistore) - Centralized store with actions, \u003cimg align=\"top\" height=\"24\" src=\"./img/unistore.svg\"\u003e + React \u003cimg align=\"top\" height=\"24\" src=\"./img/unistorereact.svg\"\u003e\n- [teaful](https://github.com/teafuljs/teaful) - Store with useState-like API, \u003cimg align=\"top\" height=\"24\" src=\"./img/teaful.svg\"\u003e, including React / preact connector.\n\n### Signals\n\nA signal-styled state manager provides observable values (aka _signals_), derived values and effects.\n\n- [@preact/signals](https://github.com/preactjs/signals) - The OG signals from preact \u003cimg align=\"top\" height=\"24\" src=\"./img/preactsignals-core.svg\"\u003e core, \u003cimg align=\"top\" height=\"24\" src=\"./img/preactsignals-react.svg\"\u003e with react integration.\n- [usignal](https://github.com/WebReflection/usignal) - A smaller signal implementation, \u003cimg align=\"top\" height=\"24\" src=\"./img/usignal.svg\"\u003e\n- [hyperactiv](https://github.com/elbywan/hyperactiv) - 4 functions to make objects observable and listen to changes, \u003cimg align=\"top\" height=\"24\" src=\"./img/hyperactiv.svg\"\u003e\n- [flimsy](https://github.com/fabiospampinato/flimsy) - Signals from Solid (it _almost_ fit into UI frameworks category itself). Author warning: _it's probably buggy._ \u003cimg align=\"top\" height=\"24\" src=\"./img/flimsy.svg\"\u003e\n\nHonorable mention: [oby](https://github.com/vobyjs/oby) _could_ make it _if_ it had tree-shaking, but otherwise is around 7 kB.\n\n### Reactive Programming\n\nAnother well-known state management approach is reactive programmning — operating on event streams, applying filters and transforms to end up with an observable value. Think RxJS, but tiny:\n\n- [flyd](https://github.com/paldepind/flyd) - Rx-styled event streams, \u003cimg align=\"top\" height=\"24\" src=\"./img/flyd.svg\"\u003e\n- [callbag-basics](https://github.com/staltz/callbag-basics) - Rx-style event streams, \u003cimg align=\"top\" height=\"24\" src=\"./img/callbag-basics.svg\"\u003e\n\n## Routers and URL Utils\n\nDo stuff on URL / history changes, with path matching and parsing:\n\n- [wouter](https://github.com/molefrog/wouter) - Declarative router for React / preact, \u003cimg align=\"top\" height=\"24\" src=\"./img/wouter.svg\"\u003e, also available as a standalone hook: \u003cimg align=\"top\" height=\"24\" src=\"./img/wouteruse-browser-location.svg\"\u003e\n- [@nanostores/router](https://github.com/nanostores/router) - Routes as a nanostores store (framework-agnostic), \u003cimg align=\"top\" height=\"24\" src=\"./img/nanostoresrouter.svg\"\u003e\n- [navaid](https://github.com/lukeed/navaid) - History-based observable router, \u003cimg align=\"top\" height=\"24\" src=\"./img/navaid.svg\"\u003e\n\nJust want to parse or match URL paths without observing them? Here you go:\n\n- [matchit](https://github.com/lukeed/matchit) - Route parser and matcher in \u003cimg align=\"top\" height=\"24\" src=\"./img/matchit.svg\"\u003e\n- [regexparam](https://github.com/lukeed/regexparam) - Convert path to regexp in \u003cimg align=\"top\" height=\"24\" src=\"./img/regexparam.svg\"\u003e\n- [qss](https://github.com/lukeed/qss) - Parse querystrings in \u003cimg align=\"top\" height=\"24\" src=\"./img/qss.svg\"\u003e. Not sure you need it, [URL API](https://developer.mozilla.org/en-US/docs/Web/API/URL) support is good. \n\n## API Layer\n\n`fetch` API has some boilerplate associated with it: serialize \u0026 parse data, reject on non-200 response, etc. These tiny packages handle it for you:\n\n- [redaxios](https://github.com/developit/redaxios) - Drop-in axios replacement for modern browsers, \u003cimg align=\"top\" height=\"24\" src=\"./img/redaxios.svg\"\u003e\n- [wretch](https://github.com/elbywan/wretch) - Chainable API with error processing and lots of extra plugins, \u003cimg align=\"top\" height=\"24\" src=\"./img/wretch.svg\"\u003e\n- [gretchen](https://github.com/truework/gretchen) - Chainable API with type-safe errors, \u003cimg align=\"top\" height=\"24\" src=\"./img/gretchen.svg\"\u003e\n\nIf for some reason you still need a fetch polyfill, try this one:\n\n- [unfetch](https://github.com/developit/unfetch) - Loose fetch polyfill, \u003cimg align=\"top\" height=\"24\" src=\"./img/unfetch.svg\"\u003e\n\n## I18N\n\nA map of strings might seem enough to translate an app, but these tools also handle interpolation and some extra goodies:\n\n- [@nanostores/i18n](https://github.com/nanostores/i18n) - Detect locale, load dictionaries, format dates / numbers, \u003cimg align=\"top\" height=\"24\" src=\"./img/nanostoresin.svg\"\u003e including nanostores.\n- [eo-locale](https://github.com/ibitcy/eo-locale) - Interpolation and dates / numbers, \u003cimg align=\"top\" height=\"24\" src=\"./img/eo-localecore.svg\"\u003e, or \u003cimg align=\"top\" height=\"24\" src=\"./img/eo-localereact.svg\"\u003e with react bindings.\n- [rosetta](https://github.com/lukeed/rosetta) - Bare-bones template strings (`{{hello}}, {{username}}`) and custom functions for everyting else, \u003cimg align=\"top\" height=\"24\" src=\"./img/rosetta.svg\"\u003e\n- [lingui](https://github.com/lingui/js-lingui) - Small core with template strings, \u003cimg align=\"top\" height=\"24\" src=\"./img/linguicore.svg\"\u003e\n\n## Dates and Time\n\nDate and time manipulation in pure JS is verbose. Luckily, two of the top date libraries have sensible size:\n\n- [date-fns](https://github.com/date-fns/date-fns/) - Not tiny as a whole, but [most functions](https://bundlephobia.com/package/date-fns) are under 1 kB each (format and parse are quite heavy).\n- [dayjs](https://github.com/iamkun/dayjs) - _Almost_ moment.js-compatible API, covers most use cases, \u003cimg align=\"top\" height=\"24\" src=\"./img/dayjsesm.svg\"\u003e\n\nAnd some more packages that only do formatting:\n\n- [tinytime](https://github.com/aweary/tinytime) - Simple date / time formatter: `{h}:{mm} -\u003e 9:33`, \u003cimg align=\"top\" height=\"24\" src=\"./img/tinytime.svg\"\u003e\n- [tinydate](https://github.com/lukeed/tinydate) - Date / time formatter, only supports padded numeric output (`September -\u003e 09`), \u003cimg align=\"top\" height=\"24\" src=\"./img/tinydate.svg\"\u003e\n- [time-stamp](https://github.com/jonschlinkert/time-stamp) - More of the same, \u003cimg align=\"top\" height=\"24\" src=\"./img/time-stamp.svg\"\u003e\n- [ms](https://github.com/vercel/ms) - Parse \u0026 format ms durations, e.g. `\"1m\" \u003c-\u003e 60000`, \u003cimg align=\"top\" height=\"24\" src=\"./img/ms.svg\"\u003e\n- [timeago.js](https://github.com/hustcc/timeago.js) - Format dates into stuff like _X minutes ago_ or _in X hours,_ \u003cimg align=\"top\" height=\"24\" src=\"./img/timeagojs.svg\"\u003e\n- [fromnow](https://github.com/lukeed/fromnow) - More of the same, \u003cimg align=\"top\" height=\"24\" src=\"./img/fromnow.svg\"\u003e\n\nNote that the built-in [`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat) has decent support.\n\n## Generic Utilities\n\nSomething you'd find in lodash or ramda, but smaller. Most are pretty similar and very small, with minor differences in package structure (single / package-per-helper) and tree shaking vs direct helper import.\n\n- [remeda](https://github.com/remeda/remeda) - 90 tree-shakable helpers [(list).](https://bundlephobia.com/package/remeda)\n- [rambda](https://github.com/selfrefactor/rambda) - 187 tree-shakable helpers [(list).](https://bundlephobia.com/package/rambda)\n- [just](https://github.com/angus-c/just) - 82 helpers in separate packages [(list).](https://anguscroll.com/just/)\n- [@fxts/core](https://github.com/marpple/FxTS) - 96 tree-shakable helpers. Lazy evaluation support.\n\nHonorable mention: [underscore,](https://github.com/jashkenas/underscore) contains many sub-1 kB helpers. It does not tree-shake as well as the libraries above due to codebase structure.\n\nNote: lodash itself is not tree-shakable, but has made many attempts at modulaity with `lodash.method` packages, imports from `lodash/method`, and `lodash-es`, none of which work well in practice.\n\nAlso note that much of the original lodash functionality comes built-in with modern ES. Prefer native versions over libraries as your browser target allows.\n\n## Validation\n\nTo check if an object matches an expected schema, you'd often use zod, yup, joi or ajv. But 90% of the time you can get what you need in under 2 kB. _Note:_ I compare a base validation subset (core + object / array + string / number / boolean) under tree-shaking to avoid punishing libs that have more features.\n\n- [v8n](https://github.com/imbrn/v8n) - zod-style API with fine-grained checks: `v8n().string().minLength(5).first(\"H\").last(\"o\")`. No tree shaking, \u003cimg align=\"top\" height=\"24\" src=\"./img/vn.svg\"\u003e\n- [banditypes](https://github.com/thoughtspile/banditypes) - The smallest validation library: \u003cimg align=\"top\" height=\"24\" src=\"./img/banditypes.svg\"\u003e\n- [superstruct](https://github.com/ianstormtaylor/superstruct) - The most popular modular validation library with good tree-shaking, \u003cimg align=\"top\" height=\"24\" src=\"./img/superstruct.svg\"\u003e\n- [valibot](https://github.com/fabian-hiller/valibot) - Another modular validation library, \u003cimg align=\"top\" height=\"24\" src=\"./img/valibot.svg\"\u003e\n- [deep-waters](https://github.com/antonioru/deep-waters) - Composable functional validators, \u003cimg align=\"top\" height=\"24\" src=\"./img/deep-waterscompose-deep-watershasShape-deep-watersarrayOf-deep-watersisString-deep-watersisNumber-deep-watersisBoolean.svg\"\u003e.\n\n## Unique ID Generation\n\nUnique ID generation does not take a lot of code, but it's not someting I'd want to write myself. Limit is 500 bytes. Also note that the [native `crypto.randomUUID`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID) has [OK support.](https://caniuse.com/mdn-api_crypto_randomuuid)\n\n- [@lukeed/uuid](https://github.com/lukeed/uuid) - Real UUIDs, \u003cimg align=\"top\" height=\"24\" src=\"./img/lukeeduuid.svg\"\u003e\n- [nanoid](https://github.com/ai/nanoid) - Random IDs with larger alphabet, \u003cimg align=\"top\" height=\"24\" src=\"./img/nanoid.svg\"\u003e\n- [uid](https://github.com/lukeed/uid) - More of the same, \u003cimg align=\"top\" height=\"24\" src=\"./img/uid.svg\"\u003e\n- [hexoid](https://github.com/lukeed/hexoid) - Hexadecimal IDs, \u003cimg align=\"top\" height=\"24\" src=\"./img/hexoid.svg\"\u003e\n\n## Colors\n\nColor manipulation is rare in pure UI development, but very helpful for data visualization, and uses [freaky math.](https://en.wikipedia.org/wiki/HSL_and_HSV#Color_conversion_formulae) Don't fry your brain, take these:\n\n- [colord](https://github.com/omgovich/colord) - Manipulate colors and convert between spaces, \u003cimg align=\"top\" height=\"24\" src=\"./img/colord.svg\"\u003e. Extra features come as plugins, 150b to 1.5 kB each.\n- [colr](https://github.com/stayradiated/colr) - More of the same, \u003cimg align=\"top\" height=\"24\" src=\"./img/colr.svg\" \u003e\n- [polychrome](https://github.com/cdonohue/polychrome) - More of the same, \u003cimg align=\"top\" height=\"24\" src=\"./img/polychrome.svg\"\u003e\n- [randomcolor](https://github.com/davidmerfield/randomColor) - Attractive random colors with configuration. \u003cimg align=\"top\" height=\"24\" src=\"./img/randomcolor.svg\"\u003e\n\n## Touch Gestures\n\nTouch gestures like swipe, drag, pinch or doubletap are a staple of mobile UX, but recognizing a series of touchmove / pointer events as a gesture is tricky, and testing is painful. Here are two libraries that do the heavy lifting for you:\n\n- [alloyfinger](https://github.com/AlloyTeam/AlloyFinger) - Pan, swipe, tap, doubletap, longpress, _and_ pinch / rotate. My personal favorite. \u003cimg align=\"top\" height=\"24\" src=\"./img/alloyfinger.svg\"\u003e.\n- [tinygesture](https://github.com/sciactive/tinygesture) - Configurable pan, swipe, tap, doubletap, longpress. \u003cimg align=\"top\" height=\"24\" src=\"./img/tinygesture.svg\"\u003e.\n\nEven if you want to detect gestures yourself, juggling mouse, touch and pointer events is hard enough, and browser inconsistencies don't help. Here are two more libraries to assist with that:\n\n- [pointer-tracker](https://github.com/GoogleChromeLabs/pointer-tracker) - Unified interface for mouse, touch and pointer events, \u003cimg align=\"top\" height=\"24\" src=\"./img/pointer-tracker.svg\"\u003e\n- [detect-it](https://github.com/rafgraph/detect-it) - Detect present and primary input method (touch / mouse) and supported events, \u003cimg align=\"top\" height=\"24\" src=\"./img/detect-it.svg\"\u003e\n\nHonorable mentions: [any-touch](https://github.com/any86/any-touch) attempts a modular approach to gesture detection, but the core is around 2 kB without any gesture recognizers. [rc-gesture,](https://github.com/react-component/gesture) used in ant design system, could be the only react component on the list, but babel-runtime / corejs polyfills hard-wired into the build push the ~2.5 kB size to over 10 kB.\n\n## Text Search\n\nText search is important for client-side filtering and autosuggests. Naive `option.includes(search)` has no sensible order on the results, and ignoring word boundaries gives unexpected matches like _spa -\u003e newSPAper._ First, here are some libraries that prioritize word matches:\n\n- [js-search](https://github.com/bvaughn/js-search) - Feature-rich and customizable: multi-field indices, stop words, custom stemmers and tokenizers. \u003cimg align=\"top\" height=\"24\" src=\"./img/js-search.svg\"\u003e\n- [ndx](https://github.com/localvoid/ndx) - Similar to js-search, differs in [ranking](https://kmwllc.com/index.php/2020/03/20/understanding-tf-idf-and-bm-25/) and is less strict for multi-word queries [(compare)](https://leeoniya.github.io/uFuzzy/demos/compare.html?libs=js-search,ndx,Wade\u0026search=twilight%20sag). Supports field weights. \u003cimg align=\"top\" height=\"24\" src=\"./img/ndx-ndxquery.svg\"\u003e\n- [wade](https://github.com/kbrsh/wade) - Also similar, [(compare)](https://leeoniya.github.io/uFuzzy/demos/compare.html?libs=js-search,Wade,ndx\u0026search=twilight%20sag) \u003cimg align=\"top\" height=\"24\" src=\"./img/wade.svg\"\u003e\n- [libsearch](https://github.com/thesephist/libsearch) - Index-free search (slower, but easier to use) with sane ordering \u003cimg align=\"top\" height=\"24\" src=\"./img/libsearch.svg\"\u003e\n\nOne way to find sensible inexact matches is _stemming_ — converting words to a root form. _Walked_ will match _walking,_ etc. Here are a few [Porter stemmers](https://vijinimallawaarachchi.com/2017/05/09/porter-stemming-algorithm/) for English language:\n\n- [stemmer](https://github.com/words/stemmer) - \u003cimg align=\"top\" height=\"24\" src=\"./img/stemmer.svg\"\u003e\n- [porter-stemmer](https://github.com/jedp/porter-stemmer) - \u003cimg align=\"top\" height=\"24\" src=\"./img/porter-stemmer.svg\"\u003e\n\nFor non-English words, I only have honorable mentions: [snowball-js](https://github.com/fortnightlabs/snowball-js) is 17 kB with 15 languages, [lunr-languages](https://github.com/MihaiValentin/lunr-languages) supports 30 languages but only works with [lunr,](https://github.com/olivernn/lunr.js) the most promising one is [natural](https://github.com/NaturalNode/natural/tree/master/lib/natural/stemmers) but it depends on Node.js.\n\n### Fuzzy search\n\n__Fuzzy search__ is another take on inexact matching — the words can be modified. First, we have libraries that only allow insertion: spacecat -\u003e SPACECrAfT. Not perfect for general-purpose text search, but great for filename, command, or URL lookups.\n\n- [fuzzy](https://github.com/mattyork/fuzzy) - Index-free, can highlight matches. \u003cimg align=\"top\" height=\"24\" src=\"./img/fuzzy.svg\"\u003e\n- [fuzzy-search](https://github.com/wouterrutgers/fuzzy-search) - With stateful index. \u003cimg align=\"top\" height=\"24\" src=\"./img/fuzzy-search.svg\"\u003e\n- [fzy.js](https://github.com/jhawthorn/fzy.js) - Matches one string at a time, tree-shakeable scores and match highlighting. \u003cimg align=\"top\" height=\"24\" src=\"./img/fzyjs.svg\"\u003e total, or ~150 bytes for `hasMatch` only.\n- [fuzzysearch](https://github.com/bevacqua/fuzzysearch) -  One string at a time, does not compute score / rank. \u003cimg align=\"top\" height=\"24\" src=\"./img/fuzzysearch.svg\"\u003e\n- [liquidmetal](https://github.com/rmm5t/liquidmetal) - Quicksilver algorithm, prioritizes matches at start of word for command abbreviations (e.g. `gp` -\u003e `git push`). One string at a time. \u003cimg align=\"top\" height=\"24\" src=\"./img/liquidmetal.svg\"\u003e\n- [quick-score](https://github.com/fwextensions/quick-score) - Another quicksilver-based lib, tweaked for long strings. Built-in list filtering and sorting, \u003cimg align=\"top\" height=\"24\" src=\"./img/quick-score.svg\"\u003e or 1.2 kB for single-string scoring.\n\nFinally, one library is specifically built for spellchecking:\n\n- [fuzzyset](https://github.com/Glench/fuzzyset.js) - Find misspellings, e.g. missipissi -\u003e Missisipi, \u003cimg align=\"top\" height=\"24\" src=\"./img/fuzzyset.svg\"\u003e Commercial usage costs $42.\n\n\n## Contributing\n\nSuggestions welcome! See [contributing.md](contributing.md), or drop an [issue](https://github.com/thoughtspile/awesome-tiny-js/issues).\n\n## Footnotes\n\nSee [WIP](wip.md) for possibly awesome libraries I have found, but not yet analyzed deeply, and [incubate](incubate.md) for awesome libraries that don't meet popularity criteria yet.\n\nCollected and reviewed by [Vladimir Klepov](https://blog.thoughtspile.tech) in 2023.\n","projects_url":"https://awesome.ecosyste.ms/api/v1/lists/thoughtspile%2Fawesome-tiny-js/projects"}