## 1. Project Overview & Quickstart (kentcdodds/match-sorter) --- **[Demo](https://codesandbox.io/s/wyk856yo48)** [![Build Status][build-badge]][build] [![Code Coverage][coverage-badge]][coverage] [![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends] [![MIT License][license-badge]][license] [ [![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Examples][examples-badge]][examples] ## The problem 1. You have a list of dozens, hundreds, or thousands of items 2. You want to filter and sort those items intelligently (maybe you have a filter input for the user) 3. You want simple, expected, and deterministic sorting of the items (no fancy math algorithm that fancily changes the sorting as they type) ## This solution This follows a simple and sensible (user friendly) algorithm that makes it easy for you to filter and sort a list of items based on given input. Items are ranked based on sensible criteria that result in a better user experience. To explain the ranking system, I'll use countries as an example: 1. **CASE SENSITIVE EQUALS**: Case-sensitive equality trumps all. These will be first. (ex. `France` would match `France`, but not `france`) 2. **EQUALS**: Case-insensitive equality (ex. `France` would match `france`) 3. **STARTS WITH**: If the item starts with the given value (ex. `Sou` would match `South Korea` or `South Africa`) 4. **WORD STARTS WITH**: If the item has multiple words, then if one of those words starts with the given value (ex. `Repub` would match `Dominican Republic`) 5. **CONTAINS**: If the item contains the given value (ex. `ham` would match `Bahamas`) 6. **ACRONYM**: If the item's acronym is the given value (ex. `us` would match `United States`) 7. **SIMPLE MATCH**: If the item has letters in the same order as the letters of the given value (ex. `iw` would match `Zimbabwe`, but not `Kuwait` because it must be in the same order). Furthermore, if the item is a closer match, it will rank higher (ex. `ua` matches `Uruguay` more closely than `United States of America`, therefore `Uruguay` will be ordered before `United States of America`) This ranking seems to make sense in people's minds. At least it does in mine. Feedback welcome! - [Installation](#installation) - [Usage](#usage) - [Advanced options](#advanced-options) - [keys: `[string]`](#keys-string) - [threshold: `number`](#threshold-number) - [keepDiacritics: `boolean`](#keepdiacritics-boolean) - [baseSort: `function(itemA, itemB): -1 | 0 | 1`](#basesort-functionitema-itemb--1--0--1) - [sorter: `function(rankedItems): rankedItems`](#sorter-functionrankeditems-rankeditems) - [Recipes](#recipes) - [Match PascalCase, camelCase, snake_case, or kebab-case as words](#match-pascalcase-camelcase-snake_case-or-kebab-case-as-words) - [Match many words across multiple fields (table filtering)](#match-many-words-across-multiple-fields-table-filtering) - [Inspiration](#inspiration) - [Other Solutions](#other-solutions) - [Issues](#issues) - [πŸ› Bugs](#-bugs) - [πŸ’‘ Feature Requests](#-feature-requests) - [Contributors ✨](#contributors-) - [LICENSE](#license) ## Installation This module is distributed via [npm][npm] which is bundled with [node][node] and should be installed as one of your project's `dependencies`: ``` npm install match-sorter ``` ## Usage ```javascript import {matchSorter} from 'match-sorter' // or const {matchSorter} = require('match-sorter') // or window.matchSorter.matchSorter const list = ['hi', 'hey', 'hello', 'sup', 'yo'] matchSorter(list, 'h') // ['hello', 'hey', 'hi'] matchSorter(list, 'y') // ['yo', 'hey'] matchSorter(list, 'z') // [] ``` If you need the ranking metadata that `match-sorter` computes internally, use `matchSorterWithRankInfo`: ```javascript import {matchSorterWithRankInfo} from 'match-sorter' const rankedResults = matchSorterWithRankInfo(list, 'h') // [ // { // item: 'hello', // rankedValue: 'hello', // rank: 5, // keyIndex: -1, // keyThreshold: undefined, // index: 2, // }, // // ... // ] ``` ## Advanced options ### keys: `[string]` _Default: `undefined`_ By default it just uses the value itself as above. Passing an array tells match-sorter which keys to use for the ranking. ```javascript const objList = [ {name: 'Janice', color: 'Green'}, {name: 'Fred', color: 'Orange'}, {name: 'George', color: 'Blue'}, {name: 'Jen', color: 'Red'}, ] matchSorter(objList, 'g', {keys: ['name', 'color']}) // [{name: 'George', color: 'Blue'}, {name: 'Janice', color: 'Green'}, {name: 'Fred', color: 'Orange'}] matchSorter(objList, 're', {keys: ['color', 'name']}) // [{name: 'Jen', color: 'Red'}, {name: 'Janice', color: 'Green'}, {name: 'Fred', color: 'Orange'}, {name: 'George', color: 'Blue'}] ``` **Array of values**: When the specified key matches an array of values, the best match from the values of in the array is going to be used for the ranking. ```javascript const iceCreamYum = [ {favoriteIceCream: ['mint', 'chocolate']}, {favoriteIceCream: ['candy cane', 'brownie']}, {favoriteIceCream: ['birthday cake', 'rocky road', 'strawberry']}, ] matchSorter(iceCreamYum, 'cc', {keys: ['favoriteIceCream']}) // [{favoriteIceCream: ['candy cane', 'brownie']}, {favoriteIceCream: ['mint', 'chocolate']}] ``` **Nested Keys**: You can specify nested keys using dot-notation. ```javascript const nestedObjList = [ {name: {first: 'Janice'}}, {name: {first: 'Fred'}}, {name: {first: 'George'}}, {name: {first: 'Jen'}}, ] matchSorter(nestedObjList, 'j', {keys: ['name.first']}) // [{name: {first: 'Janice'}}, {name: {first: 'Jen'}}] const nestedObjList = [ {name: [{first: 'Janice'}]}, {name: [{first: 'Fred'}]}, {name: [{first: 'George'}]}, {name: [{first: 'Jen'}]}, ] matchSorter(nestedObjList, 'j', {keys: ['name.0.first']}) // [{name: {first: 'Janice'}}, {name: {first: 'Jen'}}] // matchSorter(nestedObjList, 'j', {keys: ['name[0].first']}) does not work ``` This even works with arrays of multiple nested objects: just specify the key using dot-notation with the `*` wildcard instead of a numeric index. ```javascript const nestedObjList = [ {aliases: [{name: {first: 'Janice'}}, {name: {first: 'Jen'}}]}, {aliases: [{name: {first: 'Fred'}}, {name: {first: 'Frederic'}}]}, {aliases: [{name: {first: 'George'}}, {name: {first: 'Georgie'}}]}, ] matchSorter(nestedObjList, 'jen', {keys: ['aliases.*.name.first']}) // [{aliases: [{name: {first: 'Janice'}},{name: {first: 'Jen'}}]}] matchSorter(nestedObjList, 'jen', {keys: ['aliases.0.name.first']}) // [] ``` **Property Callbacks**: Alternatively, you may also pass in a callback function that resolves the value of the key(s) you wish to match on. This is especially useful when interfacing with libraries such as Immutable.js ```javascript const list = [{name: 'Janice'}, {name: 'Fred'}, {name: 'George'}, {name: 'Jen'}] matchSorter(list, 'j', {keys: [item => item.name]}) // [{name: 'Janice'}, {name: 'Jen'}] ``` For more complex structures, expanding on the `nestedObjList` example above, you can use `map`: ```javascript const nestedObjList = [ { name: [ {first: 'Janice', last: 'Smith'}, {first: 'Jon', last: 'Doe'}, ], }, { name: [ {first: 'Fred', last: 'Astaire'}, {first: 'Jenny', last: 'Doe'}, {first: 'Wilma', last: 'Flintstone'}, ], }, ] matchSorter(nestedObjList, 'doe', { keys: [ item => item.name.map(i => i.first), item => item.name.map(i => i.last), ], }) // [name: [{ first: 'Janice', last: 'Smith' },{ first: 'Jon', last: 'Doe' }], name: [{ first: 'Fred', last: 'Astaire' },{ first: 'Jenny', last: 'Doe' },{ first: 'Wilma', last: 'Flintstone' }]] ``` **Threshold**: You may specify an individual threshold for specific keys. A key will only match if it meets the specified threshold. _For more information regarding thresholds [see below](#threshold-number)_ ```javascript const list = [ {name: 'Fred', color: 'Orange'}, {name: 'Jen', color: 'Red'}, ] matchSorter(list, 'ed', { keys: [{threshold: matchSorter.rankings.STARTS_WITH, key: 'name'}, 'color'], }) //[{name: 'Jen', color: 'Red'}] ``` **Min and Max Ranking**: You may restrict specific keys to a minimum or maximum ranking by passing in an object. A key with a minimum rank will only get promoted if there is at least a simple match. ```javascript const tea = [ {tea: 'Earl Grey', alias: 'A'}, {tea: 'Assam', alias: 'B'}, {tea: 'Black', alias: 'C'}, ] matchSorter(tea, 'A', { keys: ['tea', {maxRanking: matchSorter.rankings.STARTS_WITH, key: 'alias'}], }) // without maxRanking, Earl Grey would come first because the alias "A" would be CASE_SENSITIVE_EQUAL // `tea` key comes before `alias` key, so Assam comes first even though both match as STARTS_WITH // [{tea: 'Assam', alias: 'B'}, {tea: 'Earl Grey', alias: 'A'},{tea: 'Black', alias: 'C'}] ``` ```javascript const tea = [ {tea: 'Milk', alias: 'moo'}, {tea: 'Oolong', alias: 'B'}, {tea: 'Green', alias: 'C'}, ] matchSorter(tea, 'oo', { keys: ['tea', {minRanking: matchSorter.rankings.EQUAL, key: 'alias'}], }) // minRanking bumps Milk up to EQUAL from CONTAINS (alias) // Oolong matches as STARTS_WITH // Green is missing due to no match // [{tea: 'Milk', alias: 'moo'}, {tea: 'Oolong', alias: 'B'}] ``` ### threshold: `number` _Default: `MATCHES`_ Thresholds can be used to specify the criteria used to rank the results. Available thresholds (from top to bottom) are: - CASE_SENSITIVE_EQUAL - EQUAL - STARTS_WITH - WORD_STARTS_WITH - CONTAINS - ACRONYM - MATCHES _(default value)_ - NO_MATCH ```javascript const fruit = ['orange', 'apple', 'grape', 'banana'] matchSorter(fruit, 'ap', {threshold: matchSorter.rankings.NO_MATCH}) // ['apple', 'grape', 'orange', 'banana'] (returns all items, just sorted by best match) const things = ['google', 'airbnb', 'apple', 'apply', 'app'], matchSorter(things, 'app', {threshold: matchSorter.rankings.EQUAL}) // ['app'] (only items that are equal) const otherThings = ['fiji apple', 'google', 'app', 'crabapple', 'apple', 'apply'] matchSorter(otherThings, 'app', {threshold: matchSorter.rankings.WORD_STARTS_WITH}) // ['app', 'apple', 'apply', 'fiji apple'] (everything that matches with "word starts with" or better) ``` ### keepDiacritics: `boolean` _Default: `false`_ By default, match-sorter will strip diacritics before doing any comparisons. This is the default because it makes the most sense from a UX perspective. You can disable this behavior by specifying `keepDiacritics: true` ```javascript const thingsWithDiacritics = [ 'jalapeΓ±o', 'Γ  la carte', 'cafΓ©', 'papier-mΓ’chΓ©', 'Γ  la mode', ] matchSorter(thingsWithDiacritics, 'aa') // ['jalapeΓ±o', 'Γ  la carte', 'Γ  la mode', 'papier-mΓ’chΓ©'] matchSorter(thingsWithDiacritics, 'aa', {keepDiacritics: true}) // ['jalapeΓ±o', 'Γ  la carte'] matchSorter(thingsWithDiacritics, 'Γ ', {keepDiacritics: true}) // ['Γ  la carte', 'Γ  la mode'] ``` ### baseSort: `function(itemA, itemB): -1 | 0 | 1` _Default: `(a, b) => String(a.rankedValue).localeCompare(b.rankedValue)`_ By default, match-sorter uses the `String.localeCompare` function to tie-break items that have the same ranking. This results in a stable, alphabetic sort. ```javascript const list = ['C apple', 'B apple', 'A apple'] matchSorter(list, 'apple') // ['A apple', 'B apple', 'C apple'] ``` _You can customize this behavior by specifying a custom `baseSort` function:_ ```javascript const list = ['C apple', 'B apple', 'A apple'] // This baseSort function will use the original index of items as the tie breaker matchSorter(list, 'apple', {baseSort: (a, b) => (a.index < b.index ? -1 : 1)}) // ['C apple', 'B apple', 'A apple'] ``` ### sorter: `function(rankedItems): rankedItems` _Default: `matchedItems => matchedItems.sort((a, b) => sortRankedValues(a, b, baseSort))`_ By default, match-sorter uses an internal `sortRankedValues` function to sort items after matching them. _You can customize the core sorting behavior by specifying a custom `sorter` function:_ Disable sorting entirely: ```javascript const list = ['appl', 'C apple', 'B apple', 'A apple', 'app', 'applebutter'] matchSorter(list, 'apple', {sorter: rankedItems => rankedItems}) // ['C apple', 'B apple', 'A apple', 'applebutter'] ``` Return the unsorted rankedItems, but in reverse order: ```javascript const list = ['appl', 'C apple', 'B apple', 'A apple', 'app', 'applebutter'] matchSorter(list, 'apple', {sorter: rankedItems => [...rankedItems].reverse()}) // ['applebutter', 'A apple', 'B apple', 'C apple'] ``` ## Recipes ### Match PascalCase, camelCase, snake_case, or kebab-case as words By default, `match-sorter` assumes spaces to be the word separator. However, if your data has a different word separator, you can use a property callback to replace your separator with spaces. For example, for `snake_case`: ```javascript const list = [ {name: 'Janice_Kurtis'}, {name: 'Fred_Mertz'}, {name: 'George_Foreman'}, {name: 'Jen_Smith'}, ] matchSorter(list, 'js', {keys: [item => item.name.replace(/_/g, ' ')]}) // [{name: 'Jen_Smith'}, {name: 'Janice_Kurtis'}] ``` ### Match many words across multiple fields (table filtering) By default, `match-sorter` will return matches from objects where one of the properties matches _the entire_ search term. For multi-column data sets it can be beneficial to split words in search string and match each word separately. This can be done by chaining `match-sorter` calls. The benefit of this is that a filter string of "two words" will match both "two" and "words", but will return rows where the two words are found in _different_ columns as well as when both words match in the same column. For single-column matches it will also return matches out of order (column = "wordstwo" will match just as well as column="twowords", the latter getting a higher score). ```javascript function fuzzySearchMultipleWords( rows, // array of data [{a: "a", b: "b"}, {a: "c", b: "d"}] keys, // keys to search ["a", "b"] filterValue: string, // potentially multi-word search string "two words" ) { if (!filterValue || !filterValue.length) { return rows } const terms = filterValue.split(' ') if (!terms) { return rows } // reduceRight will mean sorting is done by score for the _first_ entered word. return terms.reduceRight( (results, term) => matchSorter(results, term, {keys}), rows, ) } ``` [Multi-column code sandbox](https://codesandbox.io/s/match-sorter-example-forked-1ko35) ## Inspiration Actually, most of this code was extracted from the _very first_ library I ever wrote: [genie][genie]! ## Other Solutions You might try [Fuse.js](https://github.com/krisk/Fuse). It uses advanced math fanciness to get the closest match. Unfortunately what's "closest" doesn't always really make sense. So I extracted this from [genie][genie]. ## Issues _Looking to contribute? Look for the [Good First Issue][good-first-issue] label._ ### πŸ› Bugs Please file an issue for bugs, missing documentation, or unexpected behavior. [**See Bugs**][bugs] ### πŸ’‘ Feature Requests Please file an issue to suggest new features. Vote on feature requests by adding a πŸ‘. This helps maintainers prioritize what to work on. [**See Feature Requests**][requests] ## Contributors ✨ Thanks goes to these people ([emoji key][emojis]): | [**Kent C. Dodds**](https://kentcdodds.com)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=kentcdodds) [πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=kentcdodds) [πŸš‡](#infra-kentcdodds) [⚠️](https://github.com/kentcdodds/match-sorter/commits?author=kentcdodds) [πŸ‘€](https://github.com/kentcdodds/match-sorter/pulls?q=is%3Apr+reviewed-by%3Akentcdodds) | [**Conor Hastings**](http://conorhastings.com)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=conorhastings) [πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=conorhastings) [⚠️](https://github.com/kentcdodds/match-sorter/commits?author=conorhastings) [πŸ‘€](https://github.com/kentcdodds/match-sorter/pulls?q=is%3Apr+reviewed-by%3Aconorhastings) | [**Rogelio Guzman**](https://github.com/rogeliog)[πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=rogeliog) | [**ClaudΓ©ric Demers**](http://ced.io)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=clauderic) [πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=clauderic) [⚠️](https://github.com/kentcdodds/match-sorter/commits?author=clauderic) | [**Kevin Davis**](kevindav.us)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=osfan501) [⚠️](https://github.com/kentcdodds/match-sorter/commits?author=osfan501) | [**Denver Chen**](https://github.com/nfdjps)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=nfdjps) [πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=nfdjps) [⚠️](https://github.com/kentcdodds/match-sorter/commits?author=nfdjps) | [**Christian Ruigrok**](http://ruigrok.info)[πŸ›](https://github.com/kentcdodds/match-sorter/issues?q=author%3AChrisRu) [πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=ChrisRu) [πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=ChrisRu) | | --- | --- | --- | --- | --- | --- | --- | | [**Hozefa**](https://github.com/hozefaj)[πŸ›](https://github.com/kentcdodds/match-sorter/issues?q=author%3Ahozefaj) [πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=hozefaj) [⚠️](https://github.com/kentcdodds/match-sorter/commits?author=hozefaj) [πŸ€”](#ideas-hozefaj) | [**pushpinder107**](https://github.com/pushpinder107)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=pushpinder107) | [**Mordy Tikotzky**](https://github.com/tikotzky)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=tikotzky) [πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=tikotzky) [⚠️](https://github.com/kentcdodds/match-sorter/commits?author=tikotzky) | [**Steven Brannum**](https://github.com/sdbrannum)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=sdbrannum) [⚠️](https://github.com/kentcdodds/match-sorter/commits?author=sdbrannum) | [**Christer van der Meeren**](https://github.com/cmeeren)[πŸ›](https://github.com/kentcdodds/match-sorter/issues?q=author%3Acmeeren) | [**Samuel Petrosyan**](http://securitynull.net/)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=samyan) [πŸ›](https://github.com/kentcdodds/match-sorter/issues?q=author%3Asamyan) | [**Brandon Kalinowski**](https://brandonkalinowski.com)[πŸ›](https://github.com/kentcdodds/match-sorter/issues?q=author%3Abrandonkal) | | [**Eric Berry**](https://codefund.io)[πŸ”](#fundingFinding-coderberry) | [**Skubie Doo**](https://github.com/skube)[πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=skube) | [**MichaΓ«l De Boey**](https://michaeldeboey.be)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=MichaelDeBoey) [πŸ‘€](https://github.com/kentcdodds/match-sorter/pulls?q=is%3Apr+reviewed-by%3AMichaelDeBoey) | [**Tanner Linsley**](https://tannerlinsley.com)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=tannerlinsley) [⚠️](https://github.com/kentcdodds/match-sorter/commits?author=tannerlinsley) | [**Victor**](https://github.com/SweVictor)[πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=SweVictor) | [**Rebecca Stevens**](https://github.com/RebeccaStevens)[πŸ›](https://github.com/kentcdodds/match-sorter/issues?q=author%3ARebeccaStevens) [πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=RebeccaStevens) | [**Marco Moretti**](https://github.com/marcosvega91)[πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=marcosvega91) | | [**Ricardo Busquet**](https://ricardobusquet.com)[πŸ€”](#ideas-rbusquet) [πŸ‘€](https://github.com/kentcdodds/match-sorter/pulls?q=is%3Apr+reviewed-by%3Arbusquet) [πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=rbusquet) | [**Weyert de Boer**](https://github.com/weyert)[πŸ€”](#ideas-weyert) [πŸ‘€](https://github.com/kentcdodds/match-sorter/pulls?q=is%3Apr+reviewed-by%3Aweyert) | [**Philipp Garbowsky**](https://github.com/PhilGarb)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=PhilGarb) | [**Mart**](https://github.com/mart-jansink)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=mart-jansink) [⚠️](https://github.com/kentcdodds/match-sorter/commits?author=mart-jansink) [πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=mart-jansink) | [**Aleksey Levenstein**](https://github.com/levenleven)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=levenleven) | [**Take Weiland**](https://github.com/diesieben07)[πŸ’»](https://github.com/kentcdodds/match-sorter/commits?author=diesieben07) | [**Amit Abershitz**](https://github.com/AmitAber)[πŸ“–](https://github.com/kentcdodds/match-sorter/commits?author=AmitAber) | This project follows the [all-contributors][all-contributors] specification. Contributions of any kind welcome! ## LICENSE MIT [npm]: https://www.npmjs.com [node]: https://nodejs.org [build-badge]: https://img.shields.io/github/actions/workflow/status/kentcdodds/match-sorter/validate.yml?logo=github&style=flat-square&branch=main [build]: https://github.com/kentcdodds/match-sorter/actions?query=workflow%3Avalidate [coverage-badge]: https://img.shields.io/codecov/c/github/kentcdodds/match-sorter.svg?style=flat-square [coverage]: https://codecov.io/github/kentcdodds/match-sorter [version-badge]: https://img.shields.io/npm/v/match-sorter.svg?style=flat-square [package]: https://www.npmjs.com/package/match-sorter [downloads-badge]: https://img.shields.io/npm/dm/match-sorter.svg?style=flat-square [npmtrends]: https://www.npmtrends.com/match-sorter [license-badge]: https://img.shields.io/npm/l/match-sorter.svg?style=flat-square [license]: https://github.com/kentcdodds/match-sorter/blob/master/LICENSE [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square [prs]: http://makeapullrequest.com [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square [coc]: https://github.com/kentcdodds/match-sorter/blob/master/CODE_OF_CONDUCT.md [examples-badge]: https://img.shields.io/badge/%F0%9F%92%A1-examples-8C8E93.svg?style=flat-square [examples]: https://github.com/kentcdodds/match-sorter/blob/master/other/EXAMPLES.md [emojis]: https://github.com/all-contributors/all-contributors#emoji-key [all-contributors]: https://github.com/all-contributors/all-contributors [all-contributors-badge]: https://img.shields.io/github/all-contributors/kentcdodds/match-sorter?color=orange&style=flat-square [bugs]: https://github.com/kentcdodds/match-sorter/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Acreated-desc+label%3Abug [requests]: https://github.com/kentcdodds/match-sorter/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement [good-first-issue]: https://github.com/kentcdodds/match-sorter/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement+label%3A%22good+first+issue%22 [genie]: https://github.com/kentcdodds/genie ## 2. Official Technical Reference & Guides (kentcdodds/kentcdodds.github.io) # Kent C. Dodds personal website [](https://app.netlify.com/sites/kentcdodds/deploys) [ ## Contributors Thanks goes to these wonderful people ([emoji key](https://github.com/all-contributors/all-contributors#emoji-key)): | [**Kent C. Dodds**](https://kentcdodds.com)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=kentcdodds) [πŸš‡](#infra-kentcdodds) | [**Jonas Gierer**](https://github.com/jgierer12)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=jgierer12) | [**Vojta Holik**](https://github.com/vojtaholik)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=vojtaholik) [🎨](#design-vojtaholik) | [**Joel Hooks**](http://joelhooks.com)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=joelhooks) | [**Taylor Bell**](https://github.com/tayiorbeii)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=tayiorbeii) | [**Jason Lengstorf**](https://lengstorf.com)[πŸ€”](#ideas-jlengstorf) [⚠️](https://github.com/kentcdodds/kentcdodds.com/commits?author=jlengstorf) [πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=jlengstorf) | [**Robin Wieruch**](https://www.robinwieruch.de)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=rwieruch) | | --- | --- | --- | --- | --- | --- | --- | | [**Ahmed T. Ali**](https://ahmed.sd)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=z0al) | [**Maciej LeszczyΕ„ski**](http://asista.pl)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=asistapl) | [**Ken Greeff**](http://www.kengreeff.com)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=kengreeff) | [**Andrew Torres**](https://andrewjtorr.es)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=ajtorres9) | [**Gokulakrishnan Kalaikovan**](https://gokul.site)[πŸ–‹](#content-gokulkrishh) | [**Piotr lasota**](https://github.com/lasota-piotr)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=lasota-piotr) [πŸ–‹](#content-lasota-piotr) | [**Chris Lusk**](https://www.chrismlusk.com)[πŸ–‹](#content-chrismlusk) | | [**Adam Laycock**](https://adamlaycock.ca)[πŸ–‹](#content-alaycock) | [**Zama Khan Mohammed**](https://www.linkedin.com/in/mohammedzamakhan)[πŸ›](https://github.com/kentcdodds/kentcdodds.com/issues?q=author%3Amohammedzamakhan) | [**Juan David Castro**](http://juandc.co)[πŸ›](https://github.com/kentcdodds/kentcdodds.com/issues?q=author%3Ajuandc) | [**Sung M. Kim**](https://twitter.com/dance2die)[πŸ–‹](#content-dance2die) | [**Michael Fix**](https://www.buymeacoffee.com/fix)[πŸ–‹](#content-mfix22) | [**Christian Hansen**](http://Chriswcs.github.io)[πŸ›](https://github.com/kentcdodds/kentcdodds.com/issues?q=author%3AChrisWcs) | [**danielo**](https://twitter.com/danielofair)[πŸ–‹](#content-danielart) | | [**Brian Mitchell**](https://brianm.me/)[πŸ–‹](#content-BrianMitchL) | [**Jeff Wen**](https://sinchang.me)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=sinchang) | [**Georgi Yanev**](https://georgiyanev.dev)[πŸ–‹](#content-jumpalottahigh) | [**Edward Kim**](http://edykim.com)[🌍](#translation-edykim) | [**Eli Levit**](https://github.com/jediyozh)[πŸ–‹](#content-jediyozh) | [**Christian Takle**](https://github.com/christiantakle)[πŸ–‹](#content-christiantakle) | [**Dimitrios Lytras**](https://dimitrioslytras.com)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=dimitrisnl) | | [**Frank Calise**](http://frankcalise.com)[πŸ–‹](#content-frankcalise) | [**Ivar Nilsen**](https://github.com/ivarni)[πŸ–‹](#content-ivarni) | [**Christopher Biscardi**](http://www.christopherbiscardi.com/)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=ChristopherBiscardi) | [**Pablo R. Dinella**](http://pablodinella.com/)[πŸ–‹](#content-PabloDinella) | [**Simon Vrachliotis**](http://simonswiss.com)[πŸ–‹](#content-simonswiss) | [**Michael Wood**](https://github.com/wodin)[πŸ–‹](#content-wodin) | [**Mark Erikson**](http://blog.isquaredsoftware.com)[πŸ–‹](#content-markerikson) | | [**J.C. Hiatt**](https://jchiatt.com)[πŸ–‹](#content-jchiatt) | [**Idan Entin**](https://github.com/idanen)[πŸ–‹](#content-idanen) | [**Chase Adams**](https://chaseonsoftware.com/about)[πŸ–‹](#content-chaseadamsio) | [**Warao**](https://github.com/Wgil)[πŸ–‹](#content-Wgil) | [**Benoit de La Forest**](https://github.com/bdelaforest)[πŸ–‹](#content-bdelaforest) | [**Ben Orozco**](http://www.benoror.com)[πŸ–‹](#content-benoror) | [**Jimmy Somsanith**](https://github.com/jsomsanith)[πŸ–‹](#content-jsomsanith) | | [**Krunal Shah**](https://github.com/imkrunal)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=imkrunal) | [**w5mix**](http://w5mix.dev)[πŸ–‹](#content-w5mix) | [**MichaΓ«l De Boey**](https://michaeldeboey.be)[πŸ–‹](#content-MichaelDeBoey) [πŸ›](https://github.com/kentcdodds/kentcdodds.com/issues?q=author%3AMichaelDeBoey) | [**Sam Horton**](https://twitter.com/SavePointSam)[πŸ–‹](#content-SavePointSam) | [**Mat Dupont**](https://github.com/matldupont)[πŸ“–](https://github.com/kentcdodds/kentcdodds.com/commits?author=matldupont) [πŸ–‹](#content-matldupont) | [**Alejandro Garcia Anglada**](http://aganglada.com)[πŸ›](https://github.com/kentcdodds/kentcdodds.com/issues?q=author%3Aaganglada) | [**Krasimir Nedelchev**](https://github.com/kaykayehnn)[πŸ–‹](#content-kaykayehnn) | | [**mohamed magdy**](https://github.com/mohamedmagdy17593)[πŸ–‹](#content-mohamedmagdy17593) | [**Matthieu Bergel**](https://matthieubergel.org)[πŸ–‹](#content-mlbrgl) | [**mackie**](https://mackie.world)[πŸ–‹](#content-macklinu) | [**aaron**](https://github.com/azza85)[πŸ–‹](#content-azza85) | [**Jed Fox**](https://j-f1.github.io)[πŸ–‹](#content-j-f1) | [**Caleb Eby**](https://calebeby.ml)[πŸ–‹](#content-calebeby) | [**Ideveloper (이승규)**](http://ideveloper2.tistory.com/)[🌍](#translation-zx6658) | | [**Derrick Bol**](https://github.com/derrxb)[πŸ–‹](#content-derrxb) | [**Andy Krings-Stern**](https://github.com/ankri)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=ankri) | [**Jaakko Puntila**](https://github.com/Pumpuli)[πŸ–‹](#content-Pumpuli) | [**Daksh Shah**](https://daksh.me)[πŸ–‹](#content-dakshshah96) | [**Cory House**](http://www.bitnative.com)[πŸ–‹](#content-coryhouse) | [**Stephen Reilly**](https://www.stephenreilly.dev)[πŸ–‹](#content-itsknob) | [**Mutalis**](https://github.com/mutalis)[πŸ–‹](#content-mutalis) | | [**Jaime Mendoza**](https://jaimemendoza.com/)[πŸ–‹](#content-jaimemendozadev) | [**Jesco WΓΌster**](https://www.jescowuester.com)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=jescowuester) | [**Rakibul Hasan**](http:// raikusy.github.io)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=raikusy) | [**Stephan de Vries**](http://stephan281094.github.io)[πŸ–‹](#content-stephan281094) | [**Jonathan Beller**](https://github.com/48lizards)[πŸ–‹](#content-48lizards) | [**Sagiv ben giat**](https://github.com/sag1v)[πŸ–‹](#content-sag1v) | [**Bennett**](https://github.com/bennettdams)[πŸ–‹](#content-bennettdams) | | [**Ashutosh**](https://ashu96.github.io/)[πŸ–‹](#content-Ashu96) | [**dallanlee**](https://github.com/dallanlee)[πŸ–‹](#content-dallanlee) | [**paqe**](https://github.com/paqe)[πŸ–‹](#content-paqe) | [**Eric Jinks**](http://ericjinks.com)[πŸ–‹](#content-Jinksi) | [**Nicolas Dermine**](https://github.com/nicoder)[πŸ–‹](#content-nicoder) | [**kingingcole**](https://github.com/kingingcole)[πŸ–‹](#content-kingingcole) [πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=kingingcole) | [**Jorge Baumann**](https://twitter.com/baumannzone)[πŸ–‹](#content-baumannzone) | | [**ismail simsek**](https://github.com/itsmylife)[🌍](#translation-itsmylife) | [**Jesse Thomson**](https://github.com/jessethomson)[πŸ–‹](#content-jessethomson) | [**Gregor Albrecht**](https://twitter.com/gregoralbrecht)[πŸ–‹](#content-gregoralbrecht) | [**Stefano Magni**](https://twitter.com/NoriSte)[πŸ–‹](#content-NoriSte) | [**Bouwe K. Westerdijk**](https://bouwe.io)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=bouwe77) [πŸ–‹](#content-bouwe77) | [**LukΓ‘Ε‘**](https://github.com/lukasduspiva)[πŸ–‹](#content-lukasduspiva) | [**Nicholas Murray**](https://www.itsmycodeblog.com)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=NicholasMurray) | | [**Timothy Vernon**](https://tvernon.tech)[πŸ–‹](#content-tvthatsme) | [**Dinesh Pandiyan**](https://dineshpandiyan.com)[πŸ›](https://github.com/kentcdodds/kentcdodds.com/issues?q=author%3Aflexdinesh) | [**Andy Hong**](https://github.com/weelillad)[πŸ–‹](#content-weelillad) | [**fxOne**](https://github.com/fxOne)[πŸ–‹](#content-fxOne) | [**Gilles Debunne**](https://github.com/GillesDebunne)[πŸ–‹](#content-GillesDebunne) | [**Zubin Khavarian**](https://twitter.com/ZubinKhavarian)[πŸ–‹](#content-zubinkhavarian) | [**Billy Levin**](https://github.com/BillyLevin)[πŸ–‹](#content-BillyLevin) | | [**Deric Cain**](https://github.com/dericgw)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=dericgw) | [**Abel Lifaefi Mbula**](http://www.abelmbula.com)[πŸ–‹](#content-Bam92) | [**Andrew Luca**](https://iamandrewluca.com/)[πŸ–‹](#content-iamandrewluca) | [**Crushford**](https://github.com/Crushford)[πŸ›](https://github.com/kentcdodds/kentcdodds.com/issues?q=author%3ACrushford) | [**arnau-rius**](http://www.arnaurius.tech)[πŸ–‹](#content-arnau-rius) | [**JavaScript Joe**](https://jsjoe.io)[πŸ–‹](#content-jsjoeio) | [**Dan Abramov**](http://twitter.com/dan_abramov)[πŸ€”](#ideas-gaearon) | | [**Travis Baker**](https://github.com/baker-travis)[πŸ–‹](#content-baker-travis) | [**Ken Gregory**](http://kengregory.com)[πŸ–‹](#content-kgregory) | [**GQSM**](https://medium.com/enjoy-life-enjoy-coding)[🌍](#translation-ms314006) | [**Anastasiya Mashoshyna**](https://github.com/AMashoshyna)[πŸ–‹](#content-AMashoshyna) | [**Arkalyk Akash**](http://arkalyk.org)[πŸ–‹](#content-aarkalyk) | [**Nate Finch**](https://n8finch.com/)[πŸ–‹](#content-n8finch) | [**Jeremy Tice**](http://jeremytice.com)[πŸ–‹](#content-jetpacmonkey) | | [**Evgeniy Nagalskiy**](https://github.com/DrShpongle)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=DrShpongle) | [**Dave Brudner**](https://github.com/dbrudner)[πŸ–‹](#content-dbrudner) | [**Ryan Hinerman**](https://github.com/rchinerman)[πŸ–‹](#content-rchinerman) | [**Antonin Januska**](https://antjanus.com)[πŸ–‹](#content-AntJanus) | [**Ovie Okeh**](http://ovie.dev)[πŸ–‹](#content-ovieokeh) | [**Hitesh Riziya**](https://twitter.com/hitriz)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=hriziya) | [**mjfneto**](https://github.com/mjfneto)[🌍](#translation-mjfneto) | | [**Vedran**](https://github.com/vedran)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=vedran) | [**Hossam Mourad**](https://www.linkedin.com/in/hossammourad/)[πŸ–‹](#content-hos4m) | [**Zak**](http://www.zaklaughton.dev)[πŸ›](https://github.com/kentcdodds/kentcdodds.com/issues?q=author%3AZakLaughton) | [**Ivan Kurnosov**](http://cv.zerkms.com)[πŸ–‹](#content-zerkms) | [**Ian Jones**](https://ianjones.us/)[πŸ–‹](#content-theianjones) | [**Andrew Patton**](http://www.acusti.ca)[πŸ–‹](#content-acusti) | [**Nicholas Whittaker**](https://nchlswhttkr.com)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=nchlswhttkr) | | [**Ernesto GarcΓ­a**](https://twitter.com/gnapse)[πŸ–‹](#content-gnapse) | [**Italo**](https://segredo.dev)[🌍](#translation-iaurg) | [**Ian Wilson**](https://ianwilson.io)[πŸ–‹](#content-iwilsonq) | [**John Yeates**](https://github.com/unikitty37)[πŸ–‹](#content-unikitty37) | [**David Luhr**](https://luhr.co)[πŸ–‹](#content-davidluhr) | [**Adam Laycock**](https://arcath.net)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=Arcath) | [**@berzavlu**](https://berzavlu.com)[πŸ–‹](#content-berzavlu) | | [**Daniel Corner**](https://dcorn068.github.io/dc_gatsby/)[πŸ–‹](#content-dcorn068) | [**Gautier Darchen**](https://github.com/gdarchen)[πŸ–‹](#content-gdarchen) | [**Nerman Deliahmetovic**](https://github.com/nermand)[πŸ–‹](#content-nermand) | [**mattdenkers**](https://github.com/mattdenkers)[πŸ–‹](#content-mattdenkers) | [**Pavel Keyzik**](https://pavelkeyzik.github.io)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=pavelkeyzik) | [**KarelVerschraegen**](https://github.com/KarelVerschraegen)[πŸ–‹](#content-KarelVerschraegen) | [**Pranjal Jately**](https://github.com/pranjaljately)[πŸ–‹](#content-pranjaljately) | | [**Steric**](https://github.com/steric85)[πŸ–‹](#content-steric85) | [**Julian**](https://juliangaramendy.dev)[πŸ–‹](#content-JulianG) | [**Pranesh**](https://github.com/pranesh239)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=pranesh239) | [**Abhishek Jakhar**](http://www.abhishekjakhar.com/)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=abhishekjakhar) | [**BalΓ‘zs OrbΓ‘n**](https://balazsorban.com)[πŸ–‹](#content-balazsorban44) | [**Alejandro Requejo**](https://github.com/arequejo)[πŸ–‹](#content-arequejo) | [**Andrew Aquino**](https://dawneraq.github.io)[πŸ–‹](#content-dawneraq) | | [**todoroff**](https://github.com/todoroff)[πŸ–‹](#content-todoroff) | [**Pedro Filipe**](https://github.com/puzzledbytheweb)[πŸ–‹](#content-puzzledbytheweb) | [**Creeland A. Provinsal **](https://github.com/Creeland)[πŸ–‹](#content-Creeland) | [**Hung Viet Nguyen**](https://hung.dev)[πŸ–‹](#content-nvh95) | [**Drew Hays**](http://www.andrewhays.net)[πŸ–‹](#content-Dru89) | [**Kim RΓΈen**](http://twitter.com/kimroen)[πŸ–‹](#content-kimroen) | [**Javier MartΓ­nez**](https://github.com/JavierMartinz)[πŸ–‹](#content-JavierMartinz) | | [**Jelte Homminga**](https://jelte.tech)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=jeltehomminga) | [**David Stockton**](http://davidstockton.dev/)[πŸ–‹](#content-dstockto) | [**Dani de la Cruz**](https://delacruz.dev)[πŸ–‹](#content-delacruz-dev) | [**Marcus Lyons**](https://www.marcuslyons.com)[πŸ–‹](#content-marcuslyons) | [**Ricardo Busquet**](https://ricardobusquet.com)[πŸ–‹](#content-rbusquet) | [**MinGu Anthony Lee**](http://immigration9.github.io)[🌍](#translation-immigration9) | [**Ahmed Talaat**](http://ahmd.talat95@gmail.com)[πŸ–‹](#content-ahmdtalat) | | [**Sebastian Silbermann**](https://solverfox.dev)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=eps1lon) | [**AndrΓ© Ericson**](https://github.com/aericson)[πŸ–‹](#content-aericson) | [**Timothy Jones**](https://github.com/TimothyJones)[πŸ–‹](#content-TimothyJones) | [**Oliver Schmidt**](http://oliverschmidt.dev)[πŸ–‹](#content-codejet) | [**Maciek Sakrejda**](http://bitrotincarnate.com)[πŸ–‹](#content-uhoh-itsmaciek) | [**Adam Tuttle**](http://adamtuttle.codes)[πŸ–‹](#content-atuttle) | [**Lee Taylor**](https://www.leetaylor.dev)[πŸ–‹](#content-leettaylor) | | [**Brooks Lybrand**](https://github.com/brookslybrand)[πŸ–‹](#content-brookslybrand) | [**Will Worth**](http://willworth.dev/)[πŸ–‹](#content-willworth) | [**Nemanja Glumac**](https://glumac.me)[πŸ–‹](#content-nemanjaglumac) | [**Nick Nisi**](https://nicknisi.com)[πŸ–‹](#content-nicknisi) | [**Victor Osipov**](http://t.me/ipovos)[πŸ–‹](#content-ipovos) | [**Justinas Vebra**](https://github.com/vebradev)[πŸ›](https://github.com/kentcdodds/kentcdodds.com/issues?q=author%3Avebradev) | [**Peter HozΓ‘k**](http://peter.hozak.info/)[πŸ–‹](#content-Aprillion) [πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=Aprillion) [πŸ‘€](https://github.com/kentcdodds/kentcdodds.com/pulls?q=is%3Apr+reviewed-by%3AAprillion) | | [**onemen**](https://github.com/onemen)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=onemen) | [**Marco Moretti**](https://github.com/marcosvega91)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=marcosvega91) | [**Art Telesh**](https://github.com/decisa)[πŸ–‹](#content-decisa) | [**Stefan Huckschlag**](https://www.linkedin.com/in/hucki/)[πŸ–‹](#content-hucki) | [**Atif**](https://github.com/Atif252)[πŸ–‹](#content-Atif252) | [**Dale Seo**](https://www.daleseo.com)[πŸ–‹](#content-DaleSeo) | [**Ivan Ganev**](https://www.ganevdev.com)[🌍](#translation-Ganevru) | | [**Jonathan Rubin**](http://j-rubin.com)[πŸ–‹](#content-rubinj30) | [**devserkan**](https://github.com/devserkan)[πŸ–‹](#content-devserkan) | [**Hercules Gabriel**](https://www.linkedin.com/in/herculesgabriel/)[πŸ–‹](#content-herculesgabriel) | [**Gabriel Santana**](http://linkedin.com/in/gabrielsanttana)[πŸ–‹](#content-gabrielsanttana) | [**Patryk Fryda**](https://github.com/pafry7)[πŸ–‹](#content-pafry7) | [**Carmelo Scandaliato**](https://cascandaliato.com)[πŸ–‹](#content-cascandaliato) | [**Jacob M-G Evans**](https://dev.to/jacobmgevans)[πŸ‘€](https://github.com/kentcdodds/kentcdodds.com/pulls?q=is%3Apr+reviewed-by%3AJacobMGEvans) | | [**Adam Vigneaux**](https://adamvig.com)[πŸ–‹](#content-AdamVig) | [**Julian Betancourt**](https://github.com/julianbetancourt)[🌍](#translation-julianbetancourt) | [**Nikolai Yakuschenko**](https://github.com/nick722)[πŸ–‹](#content-nick722) | [**ravishankar97**](https://github.com/ravishankar97)[πŸ–‹](#content-ravishankar97) | [**Yury Nekhaevskiy**](https://github.com/nekhaevskiy)[πŸ–‹](#content-nekhaevskiy) | [**Konstantin MΓΌnster**](https://github.com/konstantinmuenster)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=konstantinmuenster) | [**Bill Fienberg**](https://github.com/billfienberg)[πŸ–‹](#content-billfienberg) | | [**Juliette Rapala**](https://julietterapala.com)[πŸ–‹](#content-jrapala) | [**Nikolay Stoynov**](http://arvigeus.github.com)[πŸ–‹](#content-arvigeus) | [**Oscar Dominguez**](https://dev.to/oscardom)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=oscard0m) [πŸ–‹](#content-oscard0m) | [**Willian Fernandes**](https://linkedin.com/in/willian/)[πŸ‘€](https://github.com/kentcdodds/kentcdodds.com/pulls?q=is%3Apr+reviewed-by%3Awillian) | [**Justin Hall**](https://github.com/wKovacs64)[πŸ–‹](#content-wKovacs64) [πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=wKovacs64) | [**Nikola Đuza**](https://nikolalsvk.github.io/)[πŸ–‹](#content-nikolalsvk) | [**Chris Milson**](http://shlappas.com)[πŸ–‹](#content-chrismilson) | | [**Giovani Sousa**](https://github.com/giovanisleite)[πŸ–‹](#content-giovanisleite) [🌍](#translation-giovanisleite) | [**Sudhanshu**](http://sudhanshu-ranjan.tech)[πŸ–‹](#content-tsuki42) | [**danielghandahari**](https://github.com/danielghandahari)[πŸ–‹](#content-danielghandahari) | [**Vladislav Gapurov**](https://gapurov.com)[πŸ–‹](#content-gapurov) | [**Erik Rasmussen**](https://keybase.io/erikras)[πŸ–‹](#content-erikras) | [**P. Michael Holland**](http://maikeru.github.io)[πŸ–‹](#content-maikeru) | [**Maciek Sitkowski**](https://macieksitkowski.com)[πŸ–‹](#content-sitek94) | | [**Alexandros Rantos**](https://github.com/alex-rantos)[πŸ–‹](#content-alex-rantos) | [**hiroki osame**](http://instagram.com/private.number_)[πŸ–‹](#content-privatenumber) | [**Arpan Chattopadhyay**](https://github.com/sleepyArpan)[πŸ–‹](#content-sleepyArpan) | [**Aditya Donthy**](https://github.com/AdityaDonthy)[πŸ–‹](#content-AdityaDonthy) | [**Joshua Pinter**](http://about.me/joshuapinter)[πŸ–‹](#content-joshuapinter) | [**Jae Hyun An**](https://goongoguma.github.io/)[🌍](#translation-goongoguma) | [**Koal**](https://seongry.github.io/)[🌍](#translation-seongry) | | [**Dakotah Godfrey**](http://dakotahg.dev)[πŸ–‹](#content-DakotahGodfrey) | [**Itay**](https://github.com/itayperry)[πŸ–‹](#content-itayperry) | [**thomasmarr**](https://github.com/thomasmarr)[πŸ–‹](#content-thomasmarr) | [**Diana GarcΓ­a**](https://github.com/dianaeligg)[πŸ’»](https://github.com/kentcdodds/kentcdodds.com/commits?author=dianaeligg) | [**Richard Mena**](https://github.com/rmena0127)[πŸ–‹](#content-rmena0127) | [**Abhijeet Singh**](https://www.absingh.com/)[πŸ–‹](#content-cseas) | | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! [all-contributors-badge]: https://img.shields.io/github/all-contributors/kentcdodds/kentcdodds.com?color=orange&style=flat-square