diff --git a/.all-contributorsrc b/.all-contributorsrc
index be5b5426d..9bc2e912d 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -94,7 +94,8 @@
       "avatar_url": "https://avatars1.githubusercontent.com/u/28659384?v=4",
       "profile": "http://timdeschryver.dev/",
       "contributions": [
-        "doc"
+        "doc",
+        "code"
       ]
     },
     {
@@ -314,11 +315,2498 @@
       "contributions": [
         "doc"
       ]
+    },
+    {
+      "login": "vernonk",
+      "name": "Vernon Kesner",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/74096?v=4",
+      "profile": "https://github.com/vernonk",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "wdoug",
+      "name": "Will Douglas",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/5432102?v=4",
+      "profile": "https://github.com/wdoug",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "HTMLhead",
+      "name": "Head",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/40166539?v=4",
+      "profile": "https://velog.io/@head",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mynar7",
+      "name": "Lee",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/32332479?v=4",
+      "profile": "https://github.com/mynar7",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Belco90",
+      "name": "Mario Beltrán Alarcón",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/2677072?v=4",
+      "profile": "https://mario.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jameslevine",
+      "name": "jameslevine",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/41184245?v=4",
+      "profile": "https://github.com/jameslevine",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mihar-22",
+      "name": "Rahim Alwer",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/14304599?v=4",
+      "profile": "https://github.com/mihar-22",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ariesjia",
+      "name": "Chenjia",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/1797160?v=4",
+      "profile": "http://www.btorange.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "olethanh",
+      "name": "Olivier Le Thanh Duong",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/82500?v=4",
+      "profile": "http://blog.staz.be/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "KubaJastrz",
+      "name": "Jakub Jastrzębski",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/6443113?v=4",
+      "profile": "https://kubajastrz.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "trurl-master",
+      "name": "Ivan Galiatin",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/640657?v=4",
+      "profile": "http://russianbrandgardeners.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "HendrikRoehm",
+      "name": "Hendrik Röhm",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/26203080?v=4",
+      "profile": "https://github.com/HendrikRoehm",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "samvk",
+      "name": "Sam Kauffman",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/12996081?v=4",
+      "profile": "https://samvk.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "turadg",
+      "name": "Turadg Aleahmad",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/21505?v=4",
+      "profile": "http://turadg.aleahmad.net/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "MarkGeeRomano",
+      "name": "mark g romano",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/13630752?v=4",
+      "profile": "https://github.com/MarkGeeRomano",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "arturoromeroslc",
+      "name": "Arturo Romero",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/7406639?v=4",
+      "profile": "https://github.com/arturoromeroslc",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "dustinsoftware",
+      "name": "Dustin Masters",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/942358?v=4",
+      "profile": "https://www.dustinsoftware.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "darren-lester",
+      "name": "Darren Lester",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/19534488?v=4",
+      "profile": "https://www.darrenlester.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "iswara108",
+      "name": "Iswara Chaitanya",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/9681451?v=4",
+      "profile": "https://github.com/iswara108",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "pylnata",
+      "name": "Nataliia Pylypenko",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/33361478?v=4",
+      "profile": "https://github.com/pylnata",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "huchenme",
+      "name": "Hu Chen",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/2078389?v=4",
+      "profile": "https://huchen.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jkdowdle",
+      "name": "Josh",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/19804196?v=4",
+      "profile": "https://github.com/jkdowdle",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "numb86",
+      "name": "numb86",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/16703337?v=4",
+      "profile": "https://numb86.net/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "NicholasBoll",
+      "name": "Nicholas Boll",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/338257?v=4",
+      "profile": "https://github.com/NicholasBoll",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Billy-",
+      "name": "Billy Matthews",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/4316168?v=4",
+      "profile": "https://github.com/Billy-",
+      "contributions": [
+        "talk",
+        "doc"
+      ]
+    },
+    {
+      "login": "dale-french",
+      "name": "Dale French",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/6544116?v=4",
+      "profile": "https://github.com/dale-french",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "aw-davidson",
+      "name": "aw-davidson",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/32170938?v=4",
+      "profile": "https://github.com/aw-davidson",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "BBlackwo",
+      "name": "Benjamin Blackwood",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/7598058?v=4",
+      "profile": "https://twitter.com/B_Blackwo",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "rockingskier",
+      "name": "Ben",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/681614?v=4",
+      "profile": "https://github.com/rockingskier",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "danieljcafonso",
+      "name": "Daniel Afonso",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/35337607?v=4",
+      "profile": "https://github.com/danieljcafonso",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "NomanGul",
+      "name": "Noman Gul",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/39244918?v=4",
+      "profile": "https://dev.to/nomangul",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "rafaelangical",
+      "name": "Rafael Souza",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/20307803?v=4",
+      "profile": "http://rafatech.tk/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "pustovalov",
+      "name": "Pavel Pustovalov",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/1568885?v=4",
+      "profile": "http://pustovalov.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "dymafr",
+      "name": "Dyma",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/32801166?v=4",
+      "profile": "https://github.com/dymafr",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "MatanBobi",
+      "name": "Matan Borenkraout",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/12711091?v=4",
+      "profile": "https://twitter.com/matan_bobi",
+      "contributions": [
+        "doc",
+        "code"
+      ]
+    },
+    {
+      "login": "timrobinson33",
+      "name": "timrobinson33",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/57178390?v=4",
+      "profile": "https://github.com/timrobinson33",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mdugue",
+      "name": "Manuel Dugué",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/894149?v=4",
+      "profile": "http://manueldugue.de/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "karthik20",
+      "name": "karthik20",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/12153250?v=4",
+      "profile": "https://github.com/karthik20",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "pobch",
+      "name": "Pob Ch",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/19894957?v=4",
+      "profile": "https://github.com/pobch",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mkermani144",
+      "name": "Mohammad Kermani",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/12621708?v=4",
+      "profile": "https://github.com/mkermani144",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "adeelibr",
+      "name": "Adeel Imran",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/16651811?v=4",
+      "profile": "http://twitter.com/adeelibr",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "varundey",
+      "name": "Varun Dey",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/9202135?v=4",
+      "profile": "https://varundey.me/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "PabloDinella",
+      "name": "Pablo R. Dinella",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/2482730?v=4",
+      "profile": "http://pablodinella.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jamsinclair",
+      "name": "Jamie",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/5964236?v=4",
+      "profile": "https://jamie.tokyo/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "coryhouse",
+      "name": "Cory House",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/1688997?v=4",
+      "profile": "http://www.bitnative.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "bugzpodder",
+      "name": "Jack Zhao",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/14841421?v=4",
+      "profile": "http://fb.me/yz",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "rkennel",
+      "name": "Ryan Kennel",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/28492538?v=4",
+      "profile": "https://github.com/rkennel",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "JesuHrz",
+      "name": "Jesus Hernandez",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/28031187?v=4",
+      "profile": "https://github.com/JesuHrz",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "airjp73",
+      "name": "Aaron Pettengill",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/25882770?v=4",
+      "profile": "https://github.com/airjp73",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Izhaki",
+      "name": "Izhaki",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/880132?v=4",
+      "profile": "https://github.com/Izhaki",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "rwieruch",
+      "name": "Robin Wieruch",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/2479967?v=4",
+      "profile": "https://www.robinwieruch.de/",
+      "contributions": [
+        "tutorial"
+      ]
+    },
+    {
+      "login": "Alex-Sokolov",
+      "name": "Alexander Sokolov",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/4497128?v=4",
+      "profile": "https://github.com/Alex-Sokolov",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "sastan",
+      "name": "Sascha Tandel",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/514405?v=4",
+      "profile": "https://github.com/sastan",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "gyuwon",
+      "name": "Gyuwon Yi",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/973743?v=4",
+      "profile": "https://gyuwon.github.io/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "just-boris",
+      "name": "Boris Serdiuk",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/812240?v=4",
+      "profile": "https://twitter.com/boriscoder",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "balavishnuvj",
+      "name": "balavishnuvj",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/13718688?v=4",
+      "profile": "https://github.com/balavishnuvj",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "sharmilajesupaul",
+      "name": "Sharmila Jesupaul",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/7876997?v=4",
+      "profile": "http://jesupaul.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "BatuhanW",
+      "name": "Batuhan Wilhelm",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/16444991?v=4",
+      "profile": "https://github.com/BatuhanW",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "deadkff01",
+      "name": "Dennis Kaffer",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/5138179?v=4",
+      "profile": "https://github.com/deadkff01",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "camjackson",
+      "name": "Cam Jackson",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/1930451?v=4",
+      "profile": "http://camjackson.net/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jluxenberg",
+      "name": "Jared Luxenberg",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/450478?v=4",
+      "profile": "http://www.jaredlux.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "yakirn",
+      "name": "Yakir Narkis",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/6659632?v=4",
+      "profile": "https://github.com/yakirn",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "rahulbhooteshwar",
+      "name": "Rahul Bhooteshwar",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/15920476?v=4",
+      "profile": "https://rahulbhooteshwar.github.io/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "majapw",
+      "name": "Maja Wichrowska",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/1383861?v=4",
+      "profile": "https://github.com/majapw",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "m98",
+      "name": "Kermani",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/7496103?v=4",
+      "profile": "http://medium.com/@kermani",
+      "contributions": [
+        "doc",
+        "review"
+      ]
+    },
+    {
+      "login": "malykhinvi",
+      "name": "Vasily Malykhin",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/5537715?v=4",
+      "profile": "https://malykhinvi.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "brrianalexis",
+      "name": "Brian Alexis",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/51463930?v=4",
+      "profile": "https://github.com/brrianalexis",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "kalpeshsingh",
+      "name": "Kalpesh Singh",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/13119410?v=4",
+      "profile": "http://knowkalpesh.in/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ljosberinn",
+      "name": "Gerrit Alex",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/29307652?v=4",
+      "profile": "http://gerritalex.de/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "winterlamon",
+      "name": "Winter LaMon",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/16295605?v=4",
+      "profile": "https://github.com/winterlamon",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jpenna",
+      "name": "Juliano Penna",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/16005946?v=4",
+      "profile": "https://github.com/jpenna",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "PaulACoroneos",
+      "name": "Paul Coroneos",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/40515238?v=4",
+      "profile": "http://www.pcoroneos.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "eps1lon",
+      "name": "Sebastian Silbermann",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/12292047?v=4",
+      "profile": "https://solverfox.dev/",
+      "contributions": [
+        "doc",
+        "review"
+      ]
+    },
+    {
+      "login": "psalaets",
+      "name": "Paul Salaets",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/123952?v=4",
+      "profile": "https://paulsalaets.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "michaeldeboey",
+      "name": "Michaël De Boey",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/6643991?v=4",
+      "profile": "https://michaeldeboey.be/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "washingtonsoares",
+      "name": "Washington Soares",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/5726140?v=4",
+      "profile": "https://thewashington.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jamisuomalainen",
+      "name": "Jami Suomalainen",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/19325270?v=4",
+      "profile": "https://github.com/jamisuomalainen",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "oriolpuig",
+      "name": "Oriol Puig",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/3933098?v=4",
+      "profile": "http://www.oriolpuig.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "hedgecox",
+      "name": "hedgecox",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/41297418?v=4",
+      "profile": "https://hedgecox.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "shermanhui",
+      "name": "Sherman Hui",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/11592023?v=4",
+      "profile": "https://github.com/shermanhui",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jesujcastillom",
+      "name": "Jesu Castillo",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/7827281?v=4",
+      "profile": "https://github.com/jesujcastillom",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "corehtml5canvas",
+      "name": "Core HTML5 Canvas, the book",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/1553693?v=4",
+      "profile": "http://gearysite.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "johnste",
+      "name": "John Sterling",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/886051?v=4",
+      "profile": "https://github.com/johnste",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "velusgautam",
+      "name": "Velu S Gautam",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/8556085?v=4",
+      "profile": "http://www.velusgautam.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "RichardBray",
+      "name": "Richard Oliver Bray",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/1377253?v=4",
+      "profile": "https://www.youtube.com/c/RichardBray",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "cncolder",
+      "name": "Yanlin Jiang",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/127009?v=4",
+      "profile": "https://github.com/cncolder",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "lidoravitan",
+      "name": "Lidor Avitan",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/35113398?v=4",
+      "profile": "https://github.com/lidoravitan",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ITenthusiasm",
+      "name": "Isaiah Thomason",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/47364027?v=4",
+      "profile": "https://github.com/ITenthusiasm",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "denis",
+      "name": "Denis Barushev",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/805?v=4",
+      "profile": "http://barushev.net/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "domasx2",
+      "name": "Domas",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/847684?v=4",
+      "profile": "https://github.com/domasx2",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "AntonNiklasson",
+      "name": "Anton Niklasson",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/785676?v=4",
+      "profile": "http://www.antn.se/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "nick722",
+      "name": "Nikolai Yakuschenko",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/31370625?v=4",
+      "profile": "https://github.com/nick722",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "vier31",
+      "name": "Jan Schröder",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/34372068?v=4",
+      "profile": "https://github.com/vier31",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "nickmccurdy",
+      "name": "Nick McCurdy",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/927220?v=4",
+      "profile": "https://nickmccurdy.com/",
+      "contributions": [
+        "doc",
+        "review",
+        "code"
+      ]
+    },
+    {
+      "login": "tsuki42",
+      "name": "Sudhanshu",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/22864071?v=4",
+      "profile": "http://sudhanshu-ranjan.tech/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "aleks-rope",
+      "name": "Aleksandr Chernov",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/58922379?v=4",
+      "profile": "http://newrope.biz/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mathiassoeholm",
+      "name": "Mathias",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/1747242?v=4",
+      "profile": "https://github.com/mathiassoeholm",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "davidseow",
+      "name": "davidseow",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/502503?v=4",
+      "profile": "https://github.com/davidseow",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "tonyhallett",
+      "name": "Tony Hallett",
+      "avatar_url": "https://avatars2.githubusercontent.com/u/11292998?v=4",
+      "profile": "https://github.com/tonyhallett",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "prsdta",
+      "name": "prsdta",
+      "avatar_url": "https://avatars3.githubusercontent.com/u/19373361?v=4",
+      "profile": "https://github.com/prsdta",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "tal-joffe",
+      "name": "tal-joffe",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/7221753?v=4",
+      "profile": "https://github.com/tal-joffe",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mayank23",
+      "name": "Mayank Jethva",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1103708?v=4",
+      "profile": "http://mayankjethva.xyz/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "EladIsraeli",
+      "name": "Elad Israeli",
+      "avatar_url": "https://avatars.githubusercontent.com/u/13487086?v=4",
+      "profile": "https://github.com/EladIsraeli",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "chartrandf",
+      "name": "Francis Chartrand",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1503758?v=4",
+      "profile": "https://francischartrand.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "prestoncarman",
+      "name": "Preston Carman",
+      "avatar_url": "https://avatars.githubusercontent.com/u/3517157?v=4",
+      "profile": "https://github.com/prestoncarman",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "olivierwilkinson",
+      "name": "Olivier Wilkinson",
+      "avatar_url": "https://avatars.githubusercontent.com/u/15321261?v=4",
+      "profile": "https://github.com/olivierwilkinson",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "amitmiran137",
+      "name": "Amit Miran",
+      "avatar_url": "https://avatars.githubusercontent.com/u/47772523?v=4",
+      "profile": "https://github.com/amitmiran137",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "gangsthub",
+      "name": "Paul Melero",
+      "avatar_url": "https://avatars.githubusercontent.com/u/6775220?v=4",
+      "profile": "https://graficos.net/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "modosc",
+      "name": "jonathan schatz",
+      "avatar_url": "https://avatars.githubusercontent.com/u/2231664?v=4",
+      "profile": "https://modo.sc/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "rickysullivan",
+      "name": "Ricky Sullivan Himself",
+      "avatar_url": "https://avatars.githubusercontent.com/u/437480?v=4",
+      "profile": "https://github.com/rickysullivan",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "wuarmin",
+      "name": "Armin",
+      "avatar_url": "https://avatars.githubusercontent.com/u/9987680?v=4",
+      "profile": "https://github.com/wuarmin",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "dalebaldwin",
+      "name": "Dale Baldwin",
+      "avatar_url": "https://avatars.githubusercontent.com/u/403546?v=4",
+      "profile": "http://linktr.ee/dalebaldwin",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "AdriSolid",
+      "name": "AdriSolid",
+      "avatar_url": "https://avatars.githubusercontent.com/u/25487037?v=4",
+      "profile": "https://www.linkedin.com/in/adrisolid/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "naruthk",
+      "name": "Naruth Kongurai",
+      "avatar_url": "https://avatars.githubusercontent.com/u/9120451?v=4",
+      "profile": "https://naruth.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ErfanMirzapour",
+      "name": "Erfan Mirzapour",
+      "avatar_url": "https://avatars.githubusercontent.com/u/52346515?v=4",
+      "profile": "https://github.com/ErfanMirzapour",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "shemExelate",
+      "name": "Shem Mahluf",
+      "avatar_url": "https://avatars.githubusercontent.com/u/46557021?v=4",
+      "profile": "https://github.com/shemExelate",
+      "contributions": [
+        "code",
+        "infra",
+        "doc"
+      ]
+    },
+    {
+      "login": "scoobster17",
+      "name": "Phil Gibbins",
+      "avatar_url": "https://avatars.githubusercontent.com/u/12157029?v=4",
+      "profile": "https://github.com/scoobster17",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Liadshiran",
+      "name": "Liad Shiran",
+      "avatar_url": "https://avatars.githubusercontent.com/u/18011106?v=4",
+      "profile": "https://github.com/Liadshiran",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "EduardoSimon",
+      "name": "Eduardo Simón Picón",
+      "avatar_url": "https://avatars.githubusercontent.com/u/19764148?v=4",
+      "profile": "https://github.com/EduardoSimon",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "thesanjeevsharma",
+      "name": "Sanjeev Sharma",
+      "avatar_url": "https://avatars.githubusercontent.com/u/29539278?v=4",
+      "profile": "https://thesanjeevsharma.now.sh/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "drorheller",
+      "name": "dror-heller",
+      "avatar_url": "https://avatars.githubusercontent.com/u/12750737?v=4",
+      "profile": "https://github.com/drorheller",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "yialo",
+      "name": "Aleksei Arro",
+      "avatar_url": "https://avatars.githubusercontent.com/u/38593881?v=4",
+      "profile": "https://github.com/yialo",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "carlobeltrame",
+      "name": "Carlo Beltrame",
+      "avatar_url": "https://avatars.githubusercontent.com/u/7566995?v=4",
+      "profile": "https://github.com/carlobeltrame",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ggorlen",
+      "name": "ggorlen",
+      "avatar_url": "https://avatars.githubusercontent.com/u/17895165?v=4",
+      "profile": "https://github.com/ggorlen",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mattstobbs",
+      "name": "mattstobbs",
+      "avatar_url": "https://avatars.githubusercontent.com/u/15341757?v=4",
+      "profile": "https://blog.scottlogic.com/mstobbs/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "vxxce",
+      "name": "Zach",
+      "avatar_url": "https://avatars.githubusercontent.com/u/38638365?v=4",
+      "profile": "https://vxxce.github.io/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "anpaopao",
+      "name": "Angus J. Pope",
+      "avatar_url": "https://avatars.githubusercontent.com/u/44686792?v=4",
+      "profile": "https://github.com/anpaopao",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "DylanPiercey",
+      "name": "Dylan Piercey",
+      "avatar_url": "https://avatars.githubusercontent.com/u/4985201?v=4",
+      "profile": "https://twitter.com/dylan_piercey",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ruhollahh",
+      "name": "Ruhollah",
+      "avatar_url": "https://avatars.githubusercontent.com/u/53814636?v=4",
+      "profile": "https://github.com/ruhollahh",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "votemike",
+      "name": "Michael Gwynne",
+      "avatar_url": "https://avatars.githubusercontent.com/u/3957065?v=4",
+      "profile": "https://votemike.co.uk/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "thetric",
+      "name": "Dominik Broj",
+      "avatar_url": "https://avatars.githubusercontent.com/u/19861998?v=4",
+      "profile": "https://github.com/thetric",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "stephenwade",
+      "name": "Stephen Wade",
+      "avatar_url": "https://avatars.githubusercontent.com/u/4148577?v=4",
+      "profile": "https://github.com/stephenwade",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "luizbaldi",
+      "name": "Luiz Baldi",
+      "avatar_url": "https://avatars.githubusercontent.com/u/17226904?v=4",
+      "profile": "https://luizbaldi.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ravinggenius",
+      "name": "Thomas Ingram",
+      "avatar_url": "https://avatars.githubusercontent.com/u/21517?v=4",
+      "profile": "http://www.ravinggenius.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "dwjohnston",
+      "name": "David Johnston",
+      "avatar_url": "https://avatars.githubusercontent.com/u/2467377?v=4",
+      "profile": "https://blacksheepcode.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "fildon",
+      "name": "Rupert McKay",
+      "avatar_url": "https://avatars.githubusercontent.com/u/10462288?v=4",
+      "profile": "https://fildon.me/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "SebastianMaciel",
+      "name": "Sebastián Maciel",
+      "avatar_url": "https://avatars.githubusercontent.com/u/4841148?v=4",
+      "profile": "http://www.sebastianmaciel.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "sidharthv96",
+      "name": "Sidharth Vinod",
+      "avatar_url": "https://avatars.githubusercontent.com/u/10703445?v=4",
+      "profile": "http://sidharth.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jankalfus",
+      "name": "Honza Kalfus",
+      "avatar_url": "https://avatars.githubusercontent.com/u/12714276?v=4",
+      "profile": "https://github.com/jankalfus",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "claidler",
+      "name": "Christopher Laidler",
+      "avatar_url": "https://avatars.githubusercontent.com/u/43636691?v=4",
+      "profile": "https://github.com/claidler",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "savcni01",
+      "name": "Nik Savchenko",
+      "avatar_url": "https://avatars.githubusercontent.com/u/18025894?v=4",
+      "profile": "https://github.com/savcni01",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "sfrieson",
+      "name": "Steven Frieson",
+      "avatar_url": "https://avatars.githubusercontent.com/u/15187179?v=4",
+      "profile": "http://stevenfrieson.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "andrewarosario",
+      "name": "Andrew Rosário",
+      "avatar_url": "https://avatars.githubusercontent.com/u/21269337?v=4",
+      "profile": "https://andrewrosario.medium.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "brleinad",
+      "name": "Daniel RB",
+      "avatar_url": "https://avatars.githubusercontent.com/u/12233785?v=4",
+      "profile": "http://danielrb.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "HonkingGoose",
+      "name": "HonkingGoose",
+      "avatar_url": "https://avatars.githubusercontent.com/u/34918129?v=4",
+      "profile": "https://github.com/HonkingGoose",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Daniel-Kolev",
+      "name": "Daniel Kolev",
+      "avatar_url": "https://avatars.githubusercontent.com/u/43587261?v=4",
+      "profile": "https://github.com/Daniel-Kolev",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "arryanggaputra",
+      "name": "Arryangga Aliev Pratamaputra",
+      "avatar_url": "https://avatars.githubusercontent.com/u/4743772?v=4",
+      "profile": "http://www.kopi.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "arahansen",
+      "name": "Andrew Hansen",
+      "avatar_url": "https://avatars.githubusercontent.com/u/8746094?v=4",
+      "profile": "http://arahansen.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jgsneves",
+      "name": "JOAO GABRIEL SANTOS NEVES",
+      "avatar_url": "https://avatars.githubusercontent.com/u/48700146?v=4",
+      "profile": "https://www.linkedin.com/in/jgsneves/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "lukeingalls",
+      "name": "Luke Ingalls",
+      "avatar_url": "https://avatars.githubusercontent.com/u/45518011?v=4",
+      "profile": "http://lukeingalls.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "levenleven",
+      "name": "Aleksey Levenstein",
+      "avatar_url": "https://avatars.githubusercontent.com/u/6463364?v=4",
+      "profile": "https://github.com/levenleven",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "zaicevas",
+      "name": "Tomas Zaicevas",
+      "avatar_url": "https://avatars.githubusercontent.com/u/34719980?v=4",
+      "profile": "https://medium.com/@zaicevas",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "tsriram",
+      "name": "Sriram Thiagarajan",
+      "avatar_url": "https://avatars.githubusercontent.com/u/450559?v=4",
+      "profile": "https://github.com/tsriram",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "EstebanBorai",
+      "name": "Esteban Borai",
+      "avatar_url": "https://avatars.githubusercontent.com/u/34756077?v=4",
+      "profile": "http://estebanborai.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "artivilla",
+      "name": "Arti Villa",
+      "avatar_url": "https://avatars.githubusercontent.com/u/2120159?v=4",
+      "profile": "https://twitter.com/artivilla",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jakeboone02",
+      "name": "Jake Boone",
+      "avatar_url": "https://avatars.githubusercontent.com/u/366438?v=4",
+      "profile": "https://github.com/jakeboone02",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Dennis273",
+      "name": "Dennis273",
+      "avatar_url": "https://avatars.githubusercontent.com/u/19815164?v=4",
+      "profile": "https://github.com/Dennis273",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "moshfeu",
+      "name": "Mosh Feu",
+      "avatar_url": "https://avatars.githubusercontent.com/u/3723951?v=4",
+      "profile": "https://www.linkedin.com/in/moshfeu/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "make-github-pseudonymous-again",
+      "name": "Notas Hellout",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5165674?v=4",
+      "profile": "https://fosstodon.org/@sudonymouse",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "msmolens",
+      "name": "Max Smolens",
+      "avatar_url": "https://avatars.githubusercontent.com/u/7122091?v=4",
+      "profile": "https://maxsmolens.org/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "nimaebra",
+      "name": "Nima Ebrazeh",
+      "avatar_url": "https://avatars.githubusercontent.com/u/78249749?v=4",
+      "profile": "https://github.com/nimaebra",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ph-fritsche",
+      "name": "Philipp Fritsche",
+      "avatar_url": "https://avatars.githubusercontent.com/u/39068198?v=4",
+      "profile": "http://ph-fritsche.github.io/",
+      "contributions": [
+        "review"
+      ]
+    },
+    {
+      "login": "clemp6r",
+      "name": "Clément Plantier",
+      "avatar_url": "https://avatars.githubusercontent.com/u/4757677?v=4",
+      "profile": "https://github.com/clemp6r",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "pppp606",
+      "name": "pppp606",
+      "avatar_url": "https://avatars.githubusercontent.com/u/7203958?v=4",
+      "profile": "https://github.com/pppp606",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "bilouw",
+      "name": "Bilou",
+      "avatar_url": "https://avatars.githubusercontent.com/u/7089641?v=4",
+      "profile": "https://github.com/bilouw",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "dten",
+      "name": "David Hewson",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1019038?v=4",
+      "profile": "https://github.com/dten",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "alex-kim-dev",
+      "name": "Alex Kim",
+      "avatar_url": "https://avatars.githubusercontent.com/u/45559664?v=4",
+      "profile": "https://github.com/alex-kim-dev",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "PaquitoSoft",
+      "name": "PaquitoSoft",
+      "avatar_url": "https://avatars.githubusercontent.com/u/166022?v=4",
+      "profile": "http://paquitosoftware.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "marcioggs",
+      "name": "Márcio Gabriel",
+      "avatar_url": "https://avatars.githubusercontent.com/u/2506127?v=4",
+      "profile": "https://br.linkedin.com/in/marcioggs",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "krychaxp",
+      "name": "Krychaxp",
+      "avatar_url": "https://avatars.githubusercontent.com/u/55843050?v=4",
+      "profile": "http://krychaxp.pl/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mohetti",
+      "name": "momokolo",
+      "avatar_url": "https://avatars.githubusercontent.com/u/73931283?v=4",
+      "profile": "https://github.com/mohetti",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "meatnordrink",
+      "name": "AndyG",
+      "avatar_url": "https://avatars.githubusercontent.com/u/35735666?v=4",
+      "profile": "https://github.com/meatnordrink",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jbutz",
+      "name": "Jason Butz",
+      "avatar_url": "https://avatars.githubusercontent.com/u/736696?v=4",
+      "profile": "http://www.jasonbutz.info/",
+      "contributions": [
+        "infra"
+      ]
+    },
+    {
+      "login": "olejech",
+      "name": "Oleg",
+      "avatar_url": "https://avatars.githubusercontent.com/u/64708593?v=4",
+      "profile": "https://github.com/olejech",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "danywalls",
+      "name": "Dany Paredes",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5494535?v=4",
+      "profile": "http://www.danywalls.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "abelhbeyene",
+      "name": "Abel",
+      "avatar_url": "https://avatars.githubusercontent.com/u/12272815?v=4",
+      "profile": "https://github.com/abelhbeyene",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "patrady",
+      "name": "Patrick Brady",
+      "avatar_url": "https://avatars.githubusercontent.com/u/17067460?v=4",
+      "profile": "https://github.com/patrady",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "GrantIsEaton",
+      "name": "Grant Eaton",
+      "avatar_url": "https://avatars.githubusercontent.com/u/101603396?v=4",
+      "profile": "https://github.com/GrantIsEaton",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "aarondunphy",
+      "name": "Aaron Dunphy",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5583119?v=4",
+      "profile": "https://aarondunphy.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mrazauskas",
+      "name": "Tom Mrazauskas",
+      "avatar_url": "https://avatars.githubusercontent.com/u/72159681?v=4",
+      "profile": "https://github.com/mrazauskas",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "LuckyMona",
+      "name": "Supermaryy",
+      "avatar_url": "https://avatars.githubusercontent.com/u/12708942?v=4",
+      "profile": "http://supermaryy.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "bennewton999",
+      "name": "Ben Newton",
+      "avatar_url": "https://avatars.githubusercontent.com/u/458991?v=4",
+      "profile": "http://benenewton.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "silvenon",
+      "name": "Matija Marohnić",
+      "avatar_url": "https://avatars.githubusercontent.com/u/471278?v=4",
+      "profile": "https://silvenon.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ThaddeusJiang",
+      "name": "Thaddeus Jiang",
+      "avatar_url": "https://avatars.githubusercontent.com/u/17308201?v=4",
+      "profile": "https://thaddeusjiang.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "robin-drexler",
+      "name": "Robin Drexler",
+      "avatar_url": "https://avatars.githubusercontent.com/u/474248?v=4",
+      "profile": "https://www.robin-drexler.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "caffeine-storm",
+      "name": "Thomas McKee",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1609128?v=4",
+      "profile": "https://github.com/caffeine-storm",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "satanTime",
+      "name": "satanTime",
+      "avatar_url": "https://avatars.githubusercontent.com/u/966305?v=4",
+      "profile": "https://sudo.eu/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "polinamochan",
+      "name": "polinamochan",
+      "avatar_url": "https://avatars.githubusercontent.com/u/108654322?v=4",
+      "profile": "https://github.com/polinamochan",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "shaiRose",
+      "name": "Shai Rose",
+      "avatar_url": "https://avatars.githubusercontent.com/u/4546940?v=4",
+      "profile": "https://github.com/shaiRose",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "AldinRekic",
+      "name": "AldinRekic",
+      "avatar_url": "https://avatars.githubusercontent.com/u/65592409?v=4",
+      "profile": "https://github.com/AldinRekic",
+      "contributions": [
+        "design"
+      ]
+    },
+    {
+      "login": "thanhsonng",
+      "name": "Son Nguyen",
+      "avatar_url": "https://avatars.githubusercontent.com/u/28614996?v=4",
+      "profile": "https://sonng.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Lirlev48",
+      "name": "Lirlev48",
+      "avatar_url": "https://avatars.githubusercontent.com/u/58209233?v=4",
+      "profile": "https://github.com/Lirlev48",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "tarjei",
+      "name": "Tarjei Huse",
+      "avatar_url": "https://avatars.githubusercontent.com/u/211263?v=4",
+      "profile": "https://github.com/tarjei",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ObieMunoz",
+      "name": "Obie Munoz",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5696449?v=4",
+      "profile": "https://www.linkedin.com/in/obedmunozjr/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "bertybot",
+      "name": "Bert B",
+      "avatar_url": "https://avatars.githubusercontent.com/u/44912991?v=4",
+      "profile": "https://github.com/bertybot",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "alirezahi",
+      "name": "Alireza Heydari",
+      "avatar_url": "https://avatars.githubusercontent.com/u/16666064?v=4",
+      "profile": "https://github.com/alirezahi",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "glebinsky",
+      "name": "Gleb Radutsky",
+      "avatar_url": "https://avatars.githubusercontent.com/u/898643?v=4",
+      "profile": "https://github.com/glebinsky",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "giovanniPepi",
+      "name": "giovanniPepi",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5255535?v=4",
+      "profile": "https://github.com/giovanniPepi",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mdjastrzebski",
+      "name": "Maciej Jastrzebski",
+      "avatar_url": "https://avatars.githubusercontent.com/u/6368606?v=4",
+      "profile": "https://github.com/mdjastrzebski",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "semoal",
+      "name": "Sergio Moreno",
+      "avatar_url": "https://avatars.githubusercontent.com/u/22656541?v=4",
+      "profile": "https://semoal.github.io/sergiomoreno/",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "davidnixon",
+      "name": "David Nixon",
+      "avatar_url": "https://avatars.githubusercontent.com/u/7536103?v=4",
+      "profile": "https://github.com/davidnixon",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "khitrenovich",
+      "name": "Anton Khitrenovich",
+      "avatar_url": "https://avatars.githubusercontent.com/u/3424762?v=4",
+      "profile": "http://technotes.khitrenovich.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "kostasx",
+      "name": "Kostas Minaidis",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1638325?v=4",
+      "profile": "https://plethorathemes.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "MynockSpit",
+      "name": "Than Hutchins",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5713867?v=4",
+      "profile": "https://github.com/MynockSpit",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "edmundsj",
+      "name": "Jordan Edmunds",
+      "avatar_url": "https://avatars.githubusercontent.com/u/11085127?v=4",
+      "profile": "https://github.com/edmundsj",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mouse484",
+      "name": "mouse",
+      "avatar_url": "https://avatars.githubusercontent.com/u/38714187?v=4",
+      "profile": "https://portfolio.mouse484.vercel.app/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "robertoms99",
+      "name": "Roberto Molina",
+      "avatar_url": "https://avatars.githubusercontent.com/u/54558382?v=4",
+      "profile": "https://roberto-molina.netlify.app/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "louis-young",
+      "name": "Louis Young",
+      "avatar_url": "https://avatars.githubusercontent.com/u/35606709?v=4",
+      "profile": "https://www.louisyoung.co.uk/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "lukaselmer",
+      "name": "Lukas Elmer",
+      "avatar_url": "https://avatars.githubusercontent.com/u/326935?v=4",
+      "profile": "https://www.linkedin.com/in/lukaselmer/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "brentguf",
+      "name": "Brent Guffens",
+      "avatar_url": "https://avatars.githubusercontent.com/u/16427929?v=4",
+      "profile": "https://github.com/brentguf",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "estebanfelipep",
+      "name": "Esteban",
+      "avatar_url": "https://avatars.githubusercontent.com/u/15718690?v=4",
+      "profile": "https://github.com/estebanfelipep",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "tiborbarsi",
+      "name": "Tibor Barsi",
+      "avatar_url": "https://avatars.githubusercontent.com/u/21023594?v=4",
+      "profile": "https://github.com/tiborbarsi",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "tnyo43",
+      "name": "Tomoya Kashifuku",
+      "avatar_url": "https://avatars.githubusercontent.com/u/11014018?v=4",
+      "profile": "https://github.com/tnyo43",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "wtlin1228",
+      "name": "Leo",
+      "avatar_url": "https://avatars.githubusercontent.com/u/16910748?v=4",
+      "profile": "https://leonerd.gatsbyjs.io/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "erik-metz",
+      "name": "Erik Metz",
+      "avatar_url": "https://avatars.githubusercontent.com/u/69653055?v=4",
+      "profile": "http://spray-r.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mrtyagi07",
+      "name": "Vaibhav Tyagi",
+      "avatar_url": "https://avatars.githubusercontent.com/u/83115094?v=4",
+      "profile": "https://github.com/mrtyagi07",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "alleksei37",
+      "name": "Aleksei Drokin",
+      "avatar_url": "https://avatars.githubusercontent.com/u/18336748?v=4",
+      "profile": "https://github.com/alleksei37",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "shaman-apprentice",
+      "name": "Torsten Knauf",
+      "avatar_url": "https://avatars.githubusercontent.com/u/3596742?v=4",
+      "profile": "https://github.com/shaman-apprentice",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "jharlowuk",
+      "name": "John Harlow",
+      "avatar_url": "https://avatars.githubusercontent.com/u/41212861?v=4",
+      "profile": "http://jharlow.uk/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "morgan121",
+      "name": "Morgan Hunter",
+      "avatar_url": "https://avatars.githubusercontent.com/u/62575603?v=4",
+      "profile": "https://github.com/morgan121",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Mozl",
+      "name": "Louis Moselhi",
+      "avatar_url": "https://avatars.githubusercontent.com/u/24245755?v=4",
+      "profile": "https://github.com/Mozl",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "rydash",
+      "name": "Ryan McGill",
+      "avatar_url": "https://avatars.githubusercontent.com/u/9492442?v=4",
+      "profile": "https://github.com/rydash",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "renansoares",
+      "name": "Renan Andrade",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1657840?v=4",
+      "profile": "http://rensoares.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "boldurean",
+      "name": "Vasilii Boldurean",
+      "avatar_url": "https://avatars.githubusercontent.com/u/64642760?v=4",
+      "profile": "https://github.com/boldurean",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "josiasds",
+      "name": "Josias Schneider",
+      "avatar_url": "https://avatars.githubusercontent.com/u/882253?v=4",
+      "profile": "http://theoutsider.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ledenis",
+      "name": "Denis LE",
+      "avatar_url": "https://avatars.githubusercontent.com/u/2855723?v=4",
+      "profile": "https://github.com/ledenis",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Nicoss54",
+      "name": "Nicolas Frizzarin",
+      "avatar_url": "https://avatars.githubusercontent.com/u/24563545?v=4",
+      "profile": "https://github.com/Nicoss54",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "santoshyadavdev",
+      "name": "Santosh Yadav",
+      "avatar_url": "https://avatars.githubusercontent.com/u/11923975?v=4",
+      "profile": "https://github.com/santoshyadavdev",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "caiangums",
+      "name": "Ilê Caian",
+      "avatar_url": "https://avatars.githubusercontent.com/u/7551787?v=4",
+      "profile": "http://caian.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Clarity-89",
+      "name": "Alex Khomenko",
+      "avatar_url": "https://avatars.githubusercontent.com/u/8878045?v=4",
+      "profile": "https://claritydev.net/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "LLCampos",
+      "name": "Luís Campos",
+      "avatar_url": "https://avatars.githubusercontent.com/u/12008784?v=4",
+      "profile": "https://llcampos.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "YozhEzhi",
+      "name": "Alexandr Zhidovlenko",
+      "avatar_url": "https://avatars.githubusercontent.com/u/2706062?v=4",
+      "profile": "https://github.com/YozhEzhi",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "lyannel",
+      "name": "lyannel",
+      "avatar_url": "https://avatars.githubusercontent.com/u/34246811?v=4",
+      "profile": "https://github.com/lyannel",
+      "contributions": [
+        "a11y"
+      ]
+    },
+    {
+      "login": "yanick",
+      "name": "Yanick Champoux",
+      "avatar_url": "https://avatars.githubusercontent.com/u/19954?v=4",
+      "profile": "https://techblog.babyl.ca/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ali-kamalizade",
+      "name": "Ali",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1886605?v=4",
+      "profile": "https://ali-dev.medium.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "macmillen",
+      "name": "Milan Jaritz",
+      "avatar_url": "https://avatars.githubusercontent.com/u/33156526?v=4",
+      "profile": "https://github.com/macmillen",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "dzonatan",
+      "name": "Rokas Brazdžionis",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5166666?v=4",
+      "profile": "https://github.com/dzonatan",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "tomalaforge",
+      "name": "Laforge Thomas",
+      "avatar_url": "https://avatars.githubusercontent.com/u/30832608?v=4",
+      "profile": "https://thomaslaforge.dev/home",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "StephNathai",
+      "name": "Steph Nathai",
+      "avatar_url": "https://avatars.githubusercontent.com/u/11414958?v=4",
+      "profile": "https://github.com/StephNathai",
+      "contributions": [
+        "code",
+        "a11y"
+      ]
+    },
+    {
+      "login": "friederbluemle",
+      "name": "Frieder Bluemle",
+      "avatar_url": "https://avatars.githubusercontent.com/u/743291?v=4",
+      "profile": "https://github.com/friederbluemle",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ssi02014",
+      "name": "Gromit (전민재)",
+      "avatar_url": "https://avatars.githubusercontent.com/u/64779472?v=4",
+      "profile": "https://blog.naver.com/ssi02014",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "csantos1113",
+      "name": "Cesar S",
+      "avatar_url": "https://avatars.githubusercontent.com/u/9648559?v=4",
+      "profile": "https://github.com/csantos1113",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "crutchcorn",
+      "name": "Corbin Crutchley",
+      "avatar_url": "https://avatars.githubusercontent.com/u/9100169?v=4",
+      "profile": "https://crutchcorn.dev/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "rbatsenko",
+      "name": "Roman Batsenko",
+      "avatar_url": "https://avatars.githubusercontent.com/u/6410057?v=4",
+      "profile": "https://github.com/rbatsenko",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "snjro",
+      "name": "snjro",
+      "avatar_url": "https://avatars.githubusercontent.com/u/34432943?v=4",
+      "profile": "https://github.com/snjro",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "taro-28",
+      "name": "taro",
+      "avatar_url": "https://avatars.githubusercontent.com/u/66539019?v=4",
+      "profile": "https://bento.me/taro",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "andnorda",
+      "name": "Andreas Nordahl",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1894119?v=4",
+      "profile": "https://github.com/andnorda",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "neaumusic",
+      "name": "neaumusic",
+      "avatar_url": "https://avatars.githubusercontent.com/u/3423750?v=4",
+      "profile": "https://neaumusic.github.io/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "JoyelJohny",
+      "name": "Joyel Johny",
+      "avatar_url": "https://avatars.githubusercontent.com/u/81413791?v=4",
+      "profile": "https://github.com/JoyelJohny",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "bsheps",
+      "name": "bsheps",
+      "avatar_url": "https://avatars.githubusercontent.com/u/35780702?v=4",
+      "profile": "https://github.com/bsheps",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "kyle-n",
+      "name": "Kyle Nazario",
+      "avatar_url": "https://avatars.githubusercontent.com/u/13384477?v=4",
+      "profile": "http://www.kylenazario.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "thefalked",
+      "name": "Giuliano Crivelli",
+      "avatar_url": "https://avatars.githubusercontent.com/u/28029756?v=4",
+      "profile": "https://github.com/thefalked",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mroforolhc",
+      "name": "mrkv",
+      "avatar_url": "https://avatars.githubusercontent.com/u/26799398?v=4",
+      "profile": "https://t.me/markov_ka",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "smk267",
+      "name": "smk267",
+      "avatar_url": "https://avatars.githubusercontent.com/u/88115182?v=4",
+      "profile": "https://github.com/smk267",
+      "contributions": [
+        "infra"
+      ]
+    },
+    {
+      "login": "agentdylan",
+      "name": "Dylan Gordon",
+      "avatar_url": "https://avatars.githubusercontent.com/u/3656794?v=4",
+      "profile": "https://www.dylangordon.co.nz/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "mcous",
+      "name": "Michael Cousins",
+      "avatar_url": "https://avatars.githubusercontent.com/u/2963448?v=4",
+      "profile": "https://michael.cousins.io/",
+      "contributions": [
+        "doc",
+        "review"
+      ]
+    },
+    {
+      "login": "kettanaito",
+      "name": "Artem Zakharchenko",
+      "avatar_url": "https://avatars.githubusercontent.com/u/14984911?v=4",
+      "profile": "https://kettanaito.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "vadimshvetsov",
+      "name": "Vadim Shvetsov",
+      "avatar_url": "https://avatars.githubusercontent.com/u/16336572?v=4",
+      "profile": "https://github.com/vadimshvetsov",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "domnantas",
+      "name": "Domantas Petrauskas",
+      "avatar_url": "https://avatars.githubusercontent.com/u/51953549?v=4",
+      "profile": "https://domnantas.lt/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "Efim-Kapliy",
+      "name": "Efim",
+      "avatar_url": "https://avatars.githubusercontent.com/u/126895483?v=4",
+      "profile": "https://portfolio.edkt.ru/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "denisx",
+      "name": "denisx",
+      "avatar_url": "https://avatars.githubusercontent.com/u/427776?v=4",
+      "profile": "https://github.com/denisx",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "ggualiato",
+      "name": "Giovanni Gualiato",
+      "avatar_url": "https://avatars.githubusercontent.com/u/26698704?v=4",
+      "profile": "https://github.com/ggualiato",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "saubaig456",
+      "name": "Saud Baig",
+      "avatar_url": "https://avatars.githubusercontent.com/u/143418574?v=4",
+      "profile": "https://github.com/saubaig456",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "moeyashi",
+      "name": "Ren Adachi",
+      "avatar_url": "https://avatars.githubusercontent.com/u/49895682?v=4",
+      "profile": "https://github.com/moeyashi",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "TyMick",
+      "name": "Ty Mick",
+      "avatar_url": "https://avatars.githubusercontent.com/u/5317080?v=4",
+      "profile": "https://tymick.me/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "enmanuelduran",
+      "name": "Enmanuel Durán",
+      "avatar_url": "https://avatars.githubusercontent.com/u/8060530?v=4",
+      "profile": "https://enmascript.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "gbhasha",
+      "name": "Galeel Bhasha Satthar",
+      "avatar_url": "https://avatars.githubusercontent.com/u/501794?v=4",
+      "profile": "https://github.com/gbhasha",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "ianlet",
+      "name": "Ian Létourneau",
+      "avatar_url": "https://avatars.githubusercontent.com/u/6018732?v=4",
+      "profile": "https://noma.to/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "brianlu2610",
+      "name": "brianlu2610",
+      "avatar_url": "https://avatars.githubusercontent.com/u/68666483?v=4",
+      "profile": "https://github.com/brianlu2610",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "ezzatron",
+      "name": "Erin",
+      "avatar_url": "https://avatars.githubusercontent.com/u/100152?v=4",
+      "profile": "https://github.com/ezzatron",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "nchen000",
+      "name": "Nan Chen",
+      "avatar_url": "https://avatars.githubusercontent.com/u/23487984?v=4",
+      "profile": "https://www.linkedin.com/in/nan-chen-000/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "aburdiss",
+      "name": "Alexander Burdiss",
+      "avatar_url": "https://avatars.githubusercontent.com/u/31200600?v=4",
+      "profile": "http://alexanderburdiss.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "peterh-capella",
+      "name": "Peter Hentges",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1122723?v=4",
+      "profile": "https://github.com/peterh-capella",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "neknalb",
+      "name": "neknalb",
+      "avatar_url": "https://avatars.githubusercontent.com/u/23031302?v=4",
+      "profile": "https://github.com/neknalb",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "fetsorn",
+      "name": "fetsorn",
+      "avatar_url": "https://avatars.githubusercontent.com/u/12858105?v=4",
+      "profile": "https://github.com/fetsorn",
+      "contributions": [
+        "doc"
+      ]
     }
   ],
   "contributorsPerLine": 7,
   "projectName": "testing-library-docs",
   "projectOwner": "testing-library",
   "repoType": "github",
-  "repoHost": "https://github.com/"
+  "repoHost": "https://github.com/",
+  "skipCi": true,
+  "commitType": "docs"
 }
diff --git a/.dockerignore b/.dockerignore
deleted file mode 100755
index 27d2dae2b..000000000
--- a/.dockerignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*/node_modules
-*.log
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index 9bf526656..000000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1 +0,0 @@
-open_collective: testing-library
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index dd84ea782..8bc4a7ed8 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -4,35 +4,33 @@ about: Create a report to help us improve
 title: ''
 labels: ''
 assignees: ''
-
 ---
 
-**Describe the bug**
-A clear and concise description of what the bug is.
+**Describe the bug** A clear and concise description of what the bug is.
+
+**To Reproduce** Steps to reproduce the behavior:
 
-**To Reproduce**
-Steps to reproduce the behavior:
 1. Go to '...'
 2. Click on '....'
 3. Scroll down to '....'
 4. See error
 
-**Expected behavior**
-A clear and concise description of what you expected to happen.
+**Expected behavior** A clear and concise description of what you expected to
+happen.
 
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
+**Screenshots** If applicable, add screenshots to help explain your problem.
 
 **Desktop (please complete the following information):**
- - OS: [e.g. iOS]
- - Browser [e.g. chrome, safari]
- - Version [e.g. 22]
+
+- OS: [e.g. iOS]
+- Browser [e.g. chrome, safari]
+- Version [e.g. 22]
 
 **Smartphone (please complete the following information):**
- - Device: [e.g. iPhone6]
- - OS: [e.g. iOS8.1]
- - Browser [e.g. stock browser, safari]
- - Version [e.g. 22]
 
-**Additional context**
-Add any other context about the problem here.
+- Device: [e.g. iPhone6]
+- OS: [e.g. iOS8.1]
+- Browser [e.g. stock browser, safari]
+- Version [e.g. 22]
+
+**Additional context** Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index bbcbbe7d6..2866f790f 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -4,17 +4,16 @@ about: Suggest an idea for this project
 title: ''
 labels: ''
 assignees: ''
-
 ---
 
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+**Is your feature request related to a problem? Please describe.** A clear and
+concise description of what the problem is. Ex. I'm always frustrated when [...]
 
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
+**Describe the solution you'd like** A clear and concise description of what you
+want to happen.
 
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
+**Describe alternatives you've considered** A clear and concise description of
+any alternative solutions or features you've considered.
 
-**Additional context**
-Add any other context or screenshots about the feature request here.
+**Additional context** Add any other context or screenshots about the feature
+request here.
diff --git a/.gitignore b/.gitignore
index ce04b46a7..5c447595b 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.idea
 .DS_Store
 
 node_modules
@@ -5,12 +6,12 @@ node_modules
 lib/core/metadata.js
 lib/core/MetadataBlog.js
 
-website/translated_docs
-website/build/
-website/yarn.lock
-website/node_modules
-website/i18n/*
+translated_docs
+build/
+i18n/*
+.docusaurus
+.cache-loader
 
 *.log
 
-.idea
+yarn.lock
diff --git a/.node-version b/.node-version
new file mode 100644
index 000000000..dcf74e268
--- /dev/null
+++ b/.node-version
@@ -0,0 +1 @@
+16.14
\ No newline at end of file
diff --git a/.prettierrc.js b/.prettierrc.js
index 30f575a92..4679d9bf6 100644
--- a/.prettierrc.js
+++ b/.prettierrc.js
@@ -1,6 +1 @@
-module.exports = {
-  proseWrap: 'always',
-  singleQuote: true,
-  semi: false,
-  trailingComma: 'es5',
-}
\ No newline at end of file
+module.exports = require('kcd-scripts/prettier')
diff --git a/.vscode/markdown.code-snippets b/.vscode/markdown.code-snippets
index 8df3257d7..bed57a2f8 100644
--- a/.vscode/markdown.code-snippets
+++ b/.vscode/markdown.code-snippets
@@ -1,53 +1,47 @@
 {
-	// Place your testing-library-docs workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and 
-	// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope 
-	// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is 
-	// used to trigger the snippet and the body will be expanded and inserted. Possible variables are: 
-	// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. 
-	// Placeholders with the same ids are connected.
-	// Example:
-	// "Print to console": {
-	// 	"scope": "javascript,typescript",
-	// 	"prefix": "log",
-	// 	"body": [
-	// 		"console.log('$1');",
-	// 		"$2"
-	// 	],
-	// 	"description": "Log output to console"
-	// },
-	"Multilanguage Code Block": {
-		"scope": "markdown",
-		"prefix": "docblock",
-		"body": [
-			"```html",
-			"$4",
-			"```",
-			"",
-			"",
-			"",
-			"",
-			"```js",
-			"import { $1 } from '@testing-library/dom'",
-			"",
-			"const container = document.body",
-			"const $3 = $1(container, '$2')",
-			"```",
-			"",
-			"",
-			"```js",
-			"import { render } from '@testing-library/react'",
-			"",
-			"const { $1 } = render(",
+      "  ",
+      "",
+      "  ```js",
+      "  $1",
+      "  ```",
+      "",
+      "   ",
+      "  ",
+      "",
+      "  ```jsx",
+      "  $2",
+      "  ```",
+      "",
+      "   ",
+      "  ",
+      "",
+      "  ```js",
+      "  $3",
+      "  ```",
+      "",
+      "   ",
+      "   ",
+      ""
+    ],
+    "description": "MDX multilingual tabs"
+  }
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 7a17ef2a4..176df8375 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,6 +1,9 @@
 {
   "editor.rulers": [
     60, // try to keep examples this long
-    80, // hard wrap
-  ]
+    80 // hard wrap
+  ],
+  "files.associations": {
+    "*.md": "mdx"
+  }
 }
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 26cd10755..6a568d709 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -5,31 +5,31 @@
 In the interest of fostering an open and welcoming environment, we as
 contributors and maintainers pledge to making participation in our project and
 our community a harassment-free experience for everyone, regardless of age, body
-size, disability, ethnicity, sex characteristics, gender identity and expression,
-level of experience, education, socio-economic status, nationality, personal
-appearance, race, religion, or sexual identity and orientation.
+size, disability, ethnicity, sex characteristics, gender identity and
+expression, level of experience, education, socio-economic status, nationality,
+personal appearance, race, religion, or sexual identity and orientation.
 
 ## Our Standards
 
 Examples of behavior that contributes to creating a positive environment
 include:
 
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy towards other community members
 
 Examples of unacceptable behavior by participants include:
 
-* The use of sexualized language or imagery and unwelcome sexual attention or
- advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
- address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
- professional setting
+- The use of sexualized language or imagery and unwelcome sexual attention or
+  advances
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or electronic
+  address, without explicit permission
+- Other conduct which could reasonably be considered inappropriate in a
+  professional setting
 
 ## Our Responsibilities
 
@@ -37,11 +37,11 @@ Project maintainers are responsible for clarifying the standards of acceptable
 behavior and are expected to take appropriate and fair corrective action in
 response to any instances of unacceptable behavior.
 
-Project maintainers have the right and responsibility to remove, edit, or
-reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct, or to ban temporarily or
-permanently any contributor for other behaviors that they deem inappropriate,
-threatening, offensive, or harmful.
+Project maintainers have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, or to ban temporarily or permanently any
+contributor for other behaviors that they deem inappropriate, threatening,
+offensive, or harmful.
 
 ## Scope
 
@@ -55,11 +55,12 @@ further defined and clarified by project maintainers.
 ## Enforcement
 
 Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at alexander.krolick+testing@gmail.com. All
-complaints will be reviewed and investigated and will result in a response that
-is deemed necessary and appropriate to the circumstances. The project team is
-obligated to maintain confidentiality with regard to the reporter of an incident.
-Further details of specific enforcement policies may be posted separately.
+reported by contacting the project team at alexander.krolick+testing@gmail.com.
+All complaints will be reviewed and investigated and will result in a response
+that is deemed necessary and appropriate to the circumstances. The project team
+is obligated to maintain confidentiality with regard to the reporter of an
+incident. Further details of specific enforcement policies may be posted
+separately.
 
 Project maintainers who do not follow or enforce the Code of Conduct in good
 faith may face temporary or permanent repercussions as determined by other
@@ -67,8 +68,9 @@ members of the project's leadership.
 
 ## Attribution
 
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
-available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 1.4, available at
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
 
 [homepage]: https://www.contributor-covenant.org
 
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100755
index d369844d5..000000000
--- a/Dockerfile
+++ /dev/null
@@ -1,10 +0,0 @@
-FROM node:8.11.4
-
-WORKDIR /app/website
-
-EXPOSE 3000 35729
-COPY ./docs /app/docs
-COPY ./website /app/website
-RUN yarn install
-
-CMD ["yarn", "start"]
diff --git a/README.md b/README.md
index 7fbc2bbaa..4ffd940f5 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,15 @@
-testing-library-docs
---------------------
-
+## testing-library-docs
 
 
-[![Open Collective Sponsors and Backers][opencollective-badge]][opencollective]
 [![All Contributors][allcontributors-badge]](#contributors)
 [![Code of Conduct][coc-badge]][coc]
 
 
-Documentation site for [React Testing Library](https://github.com/testing-library/react-testing-library), [DOM Testing Library](https://github.com/testing-library/dom-testing-library), and [related projects](https://github.com/testing-library)
-
-See [./website/README.md](./website/README.md) for instructions on building the site
+Documentation site for
+[React Testing Library](https://github.com/testing-library/react-testing-library),
+[DOM Testing Library](https://github.com/testing-library/dom-testing-library),
+[Angular Testing Library](https://github.com/testing-library/angular-testing-library),
+and [related projects](https://github.com/testing-library)
 
 **https://testing-library.com**
 
@@ -18,67 +17,532 @@ See [./website/README.md](./website/README.md) for instructions on building the
 
 [![Netlify Status][netlify-badge]][build]
 
-[netlify-badge]: https://api.netlify.com/api/v1/badges/24366204-84ca-41e9-b573-2a64f0845e46/deploy-status
+[netlify-badge]:
+  https://api.netlify.com/api/v1/badges/24366204-84ca-41e9-b573-2a64f0845e46/deploy-status
 [build]: https://app.netlify.com/sites/testing-library/deploys
-[opencollective]: https://opencollective.com/testing-library/
-[opencollective-badge]: https://img.shields.io/opencollective/all/testing-library.svg?label=opencollective%20backers&style=flat-square
-[allcontributors-badge]: https://img.shields.io/badge/all_contributors-2-orange.svg?style=flat-square
-[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
-[coc]: https://github.com/testing-library/react-testing-library/blob/master/CODE_OF_CONDUCT.md
+[allcontributors-badge]:
+  https://img.shields.io/github/all-contributors/testing-library/testing-library-docs?color=ee8449&style=flat-square
+[coc-badge]:
+  https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
+[coc]:
+  https://github.com/testing-library/react-testing-library/blob/main/CODE_OF_CONDUCT.md
+
+This website was created with [Docusaurus](https://v2.docusaurus.io).
+
+# What's In This Document
+
+- [Get Started in 5 Minutes](#get-started-in-5-minutes)
+- [Editing Content](#editing-content)
+- [Adding Content](#adding-content)
+
+# Get Started in 5 Minutes
+
+1. Make sure all the dependencies for the website are installed:
+
+```sh
+# Install dependencies
+$ npm install
+```
+
+2. Run your dev server:
+
+```sh
+# Start the site
+$ npm start
+```
+
+# Editing Content
+
+## Editing an existing docs page
+
+Edit docs by navigating to `docs/` and editing the corresponding document:
+
+`docs/doc-to-be-edited.mdx`
+
+```markdown
+---
+id: page-needs-edit
+title: This Doc Needs To Be Edited
+---
+
+Edit me...
+```
+
+For more information about docs, click [here](https://v2.docusaurus.io/docs)
+
+## Editing an existing blog post
+
+Edit blog posts by navigating to `blog` and editing the corresponding post:
+
+`blog/post-to-be-edited.mdx`
+
+```markdown
+---
+id: post-needs-edit
+title: This Blog Post Needs To Be Edited
+---
+
+Edit me...
+```
+
+For more information about blog posts, click
+[here](https://v2.docusaurus.io/docs/blog)
+
+# Adding Content
+
+## Adding a new docs page to an existing sidebar
+
+1. Create the doc as a new markdown file in `/docs`, example
+   `docs/newly-created-doc.mdx`:
+
+```md
+---
+id: newly-created-doc
+title: This Doc Needs To Be Edited
+---
+
+My new content here..
+```
+
+Note: Ensure the file name and the id value do not include non-url safe
+characters i.e. '\*'.
+
+2. Refer to that doc's ID in an existing sidebar in `sidebar.json`:
+
+```javascript
+// Add newly-created-doc to the Getting Started category of docs
+{
+  "docs": {
+    "Getting Started": [
+      "quick-start",
+      "newly-created-doc" // new doc here
+    ],
+    ...
+  },
+  ...
+}
+```
+
+For more information about adding new docs, click
+[here](https://v2.docusaurus.io/docs/)
 
 ## Contributors
 
-Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
+Thanks goes to these wonderful people
+([emoji key](https://allcontributors.org/docs/en/emoji-key)):
 
 
-
+
+
 
 
+
+
+
 
 
-This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
+This project follows the
+[all-contributors](https://github.com/all-contributors/all-contributors)
+specification. Contributions of any kind welcome!
diff --git a/website/blog/2018-12-29-new-site.md b/blog/2018-12-29-new-site.mdx
similarity index 79%
rename from website/blog/2018-12-29-new-site.md
rename to blog/2018-12-29-new-site.mdx
index cd3652a16..592607164 100755
--- a/website/blog/2018-12-29-new-site.md
+++ b/blog/2018-12-29-new-site.mdx
@@ -1,7 +1,7 @@
 ---
 title: New Site
 author: Alex Krolick
-authorURL: http://github.com/alexkrolick
+authorURL: 'http://github.com/alexkrolick'
 ---
 
 We have a docs site now! It's built with [Docusaurus](https://docusaurus.io).
@@ -20,6 +20,6 @@ beyond!
 
 🎉 Happy new year!
 
-[dtl]: /
-[rtl]: /react
-[ctl]: /cypress
+[dtl]: /docs/dom-testing-library/intro
+[rtl]: /docs/react-testing-library/intro
+[ctl]: /docs/cypress-testing-library/intro
diff --git a/website/blog/2019-03-17-code-blocks.md b/blog/2019-03-17-code-blocks.mdx
similarity index 92%
rename from website/blog/2019-03-17-code-blocks.md
rename to blog/2019-03-17-code-blocks.mdx
index 49b0c45b1..b17d70ea2 100755
--- a/website/blog/2019-03-17-code-blocks.md
+++ b/blog/2019-03-17-code-blocks.mdx
@@ -1,7 +1,7 @@
 ---
 title: Multi-Framework Code Blocks
 author: Alex Krolick
-authorURL: http://github.com/alexkrolick
+authorURL: 'http://github.com/alexkrolick'
 ---
 
 Many of the code samples have been updated to include tabs to switch between
diff --git a/website/blog/2019-04-25-new-org.md b/blog/2019-04-25-new-org.mdx
similarity index 83%
rename from website/blog/2019-04-25-new-org.md
rename to blog/2019-04-25-new-org.mdx
index c835f1a8b..b0e09c200 100644
--- a/website/blog/2019-04-25-new-org.md
+++ b/blog/2019-04-25-new-org.mdx
@@ -1,10 +1,12 @@
 ---
-# prettier doesn't like how long this line is.
-# prettier-ignore
-title: "Testing Library Updates: new release, github org, open collective, and twitter account"
+# prettier doesn't like how long this line is.: ""
+# prettier-ignore: ""
+title:
+  'Testing Library Updates: new release, github org, open collective, and
+  twitter account'
 author: Kent C. Dodds
-authorURL: https://kentcdodds.com
-authorImageURL: https://avatars0.githubusercontent.com/u/1500684?s=120&v=4
+authorURL: 'https://kentcdodds.com/'
+authorImageURL: 'https://avatars0.githubusercontent.com/u/1500684?s=120&v=4'
 ---
 
 Hello friends! I'm pleased to announce the recent updates to the testing-library
@@ -35,8 +37,7 @@ just disable it here -->
 
 
 We hope that this helps you catch bugs better!
@@ -71,7 +72,7 @@ Here are the current (or soon to be) members of the org:
   (Puppeteer)
 - [bs-react-testing-library](https://github.com/wyze/bs-react-testing-library)
   (ReasonReact)
-- [testcafe-testing-library](https://github.com/benmonro/testcafe-testing-library)
+- [testcafe-testing-library](https://github.com/testing-library/testcafe-testing-library)
 - [user-event](https://github.com/Gpx/user-event)
 - [jest-dom](https://github.com/testing-library/jest-dom)
 - [jest-native](https://github.com/testing-library/jest-native)
@@ -122,33 +123,27 @@ there.) Please join us!
 
 > [Join us on Spectrum](https://spectrum.chat/testing-library)
 
-## [Testing Library on React Native](https://www.native-testing-library.com/)
+## [Testing Library on React Native](https://callstack.github.io/react-native-testing-library/)
 
 I'm really happy to announce a super solution to the React Native testing space.
 The DOM is quite different from native, as I mentioned before, it's not the code
 but the concepts that really make the Testing Library great. I'm happy to say
-that [Brandon Carroll](https://twitter.com/bcarroll22) has successfully ported
+that [Brandon Carroll](https://github.com/bcarroll22) has successfully ported
 those concepts to a solution for React Native and I'm really happy with it. Give
 it a look if you're building React Native applications and want confidence that
 they continue to work as you make changes!
 
-(Note, there is already `react-native-testing-library`, but it doesn't quite
-follow the guiding principles of Testing Library, so we recommend you use
-`native-testing-library`.
-[Learn More](https://medium.com/@brandoncarroll/why-native-testing-library-exists-629ffb85cae2)).
+> [Checkout native-testing-library](https://callstack.github.io/react-native-testing-library/)
 
-> [Checkout native-testing-library](https://www.native-testing-library.com/)
-
-## [Learn Testing Library](https://testing-library.com/docs/learning)
+## [Learn Testing Library](/docs/learning)
 
 There's been a LOT of activity around the Testing Library principles and tools
 in the content space. We do have
-[a page that lists learning materials](https://testing-library.com/docs/learning),
-and more gets added to it daily. If you know of blog posts, YouTube videos,
-courses, or anything else about the Testing Library family of tools, please
-contribute to the list!
+[a page that lists learning materials](/docs/learning), and more gets added to
+it daily. If you know of blog posts, YouTube videos, courses, or anything else
+about the Testing Library family of tools, please contribute to the list!
 
-> [Contribute to the learning materials page](https://github.com/testing-library/testing-library-docs/edit/master/docs/learning.md)
+> [Contribute to the learning materials page](https://github.com/testing-library/testing-library-docs/edit/main/docs/learning.mdx)
 
 ## Other Exciting news
 
@@ -157,9 +152,9 @@ As of a few months ago,
 you use react-testing-library to test your react applications. That's kinda neat
 :)
 
-At the React Amsterdam [Open Source awards](https://osawards.com/react/) ceremony,
-react-testing-library won the award for the Most impactful contribution to the
-community!
+At the React Amsterdam [Open Source awards](https://osawards.com/react/)
+ceremony, react-testing-library won the award for the Most impactful
+contribution to the community!
 
 
 
@@ -178,7 +173,7 @@ an especially significant impact on the Testing Library family of tools and
 community.
 
 [Myself 👋](https://kentcdodds.com), [Alex Krolick](https://alexkrolick.com/),
-[Brandon Carroll](https://twitter.com/bcarroll22),
+[Brandon Carroll](https://github.com/bcarroll22),
 [Giorgio](https://twitter.com/Gpx),
 [Ernesto García](https://twitter.com/gnapse), and
 [Daniel Cook](https://github.com/dfcook).
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100755
index 6711192ae..000000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-version: "3"
-
-services:
-  docusaurus:
-    build: .
-    ports:
-      - 3000:3000
-      - 35729:35729
-    volumes:
-      - ./docs:/app/docs
-      - ./website/blog:/app/website/blog
-      - ./website/core:/app/website/core
-      - ./website/i18n:/app/website/i18n
-      - ./website/pages:/app/website/pages
-      - ./website/static:/app/website/static
-      - ./website/sidebars.json:/app/website/sidebars.json
-      - ./website/siteConfig.js:/app/website/siteConfig.js
-    working_dir: /app/website
diff --git a/docs/angular-testing-library/api.md b/docs/angular-testing-library/api.md
deleted file mode 100644
index 976e959c9..000000000
--- a/docs/angular-testing-library/api.md
+++ /dev/null
@@ -1,282 +0,0 @@
----
-id: api
-title: API
-sidebar_label: API
----
-
-`Angular Testing Library` re-exports everything from `DOM Testing Library` as
-well as these methods:
-
-- [`render`](<(#render)>)
-
-## `render`
-
-```typescript
-function render(
-  component: Type,
-  renderOptions?: RenderOptions
-): Promise
-function render(
-  template: string,
-  renderOptions: RenderOptions
-): Promise
-```
-
-## RenderOptions
-
-### `detectChanges`
-
-Will call `detectChanges` when the component is compiled
-
-**default** : `true`
-
-**example**:
-
-```typescript
-const component = await render(AppComponent, { detectChanges: false })
-```
-
-### `declarations`
-
-A collection of providers needed to render the component via Dependency
-Injection, for example, injectable services or tokens.
-
-For more info see the
-[Angular docs](https://angular.io/api/core/NgModule#providers).
-
-**default** : `[]`
-
-**example**:
-
-```typescript
-const component = await render(AppComponent, {
-  providers: [
-    CustomersService,
-    {
-      provide: MAX_CUSTOMERS_TOKEN,
-      useValue: 10,
-    },
-  ],
-})
-```
-
-### `imports`
-
-A collection of imports needed to render the component, for example, shared
-modules. Adds `NoopAnimationsModule` by default if `BrowserAnimationsModule`
-isn't added to the collection
-
-For more info see the
-[Angular docs](https://angular.io/api/core/NgModule#imports).
-
-**default** : `[NoopAnimationsModule]`
-
-**example**:
-
-```typescript
-const component = await render(AppComponent, {
-  imports: [AppSharedModule, MaterialModule],
-})
-```
-
-### `schemas`
-
-A collection of schemas needed to render the component. Allowed values are
-`NO_ERRORS_SCHEMA` and `CUSTOM_ELEMENTS_SCHEMA`.
-
-For more info see the
-[Angular docs](https://angular.io/api/core/NgModule#schemas).
-
-**default** : `[]`
-
-**example**:
-
-```typescript
-const component = await render(AppComponent, {
-  schemas: [NO_ERRORS_SCHEMA],
-})
-```
-
-### `componentProperties`
-
-An object to set `@Input` and `@Output` properties of the component.
-
-**default** : `{}`
-
-**example**:
-
-```typescript
-const component = await render(AppComponent, {
-  componentProperties: {
-    counterValue: 10,
-    send: (value) => { ... }
-  }
-})
-```
-
-### `componentProviders`
-
-A collection of providers to inject dependencies of the component.
-
-For more info see the
-[Angular docs](https://angular.io/api/core/Directive#providers).
-
-**default** : `[]`
-
-**example**:
-
-```typescript
-const component = await render(AppComponent, {
-  componentProviders: [AppComponentService],
-})
-```
-
-### `queries`
-
-Queries to bind. Overrides the default set from DOM Testing Library unless
-merged.
-
-**default** : `undefined`
-
-**example**:
-
-```typescript
-const component = await render(AppComponent, {
-  queries: { ...queries, ...customQueries },
-})
-```
-
-### `wrapper`
-
-An Angular component to wrap the component in.
-
-**default** : `WrapperComponent`, an empty component that strips the
-`ng-version` attribute.
-
-**example**:
-
-```typescript
-const component = await render(AppComponent, {
-  wrapper: CustomWrapperComponent,
-})
-```
-
-### `excludeComponentDeclaration`
-
-Exclude the component to be automatically be added as a declaration. This is
-needed when the component is declared in an imported module.
-
-**default** : `false`
-
-**example**:
-
-```typescript
-const component = await render(AppComponent, {
-  imports: [AppModule], // a module that includes AppComponent
-  excludeComponentDeclaration: true,
-})
-```
-
-## `RenderResult`
-
-### `...queries`
-
-The most important feature of `render` is that the queries from
-[DOM Testing Library](https://testing-library.com/docs/dom-testing-library) are
-automatically returned with their first argument bound to the component under
-test.
-
-See [Queries](https://testing-library.com/docs/dom-testing-library/api-queries)
-for a complete list.
-
-**example**:
-
-```typescript
-const component = await render(AppComponent)
-
-component.getByText('Hello world')
-component.queryByLabelText('First name:')
-```
-
-### `fireEvent.***`
-
-The second most important feature of `render` is that the events from
-[DOM Testing Library](https://testing-library.com/docs/dom-testing-library) are
-automatically bound to the Angular Component. This to ensure that the Angular
-change detection has been run by calling `detectChanges` after an event has been
-fired.
-
-See
-[Firing Events](https://testing-library.com/docs/dom-testing-library/api-events)
-for a complete list.
-
-**example**:
-
-```typescript
-const component = await render(AppComponent)
-
-component.change(component.getByLabelText('Username'), {
-  target: {
-    value: 'Tim',
-  },
-})
-component.click(component.getByText('Login'))
-```
-
-### `type`
-
-Types a value in an input field with the same interactions as the user would do.
-
-```typescript
-const component = await render(AppComponent)
-
-component.type(component.getByLabelText('Username'), 'Tim')
-component.type(component.getByLabelText('Username'), 'Tim', { delay: 250 })
-```
-
-### `selectOptions`
-
-Select an option(s) from a select field with the same interactions as the user
-would do.
-
-```typescript
-const component = await render(AppComponent)
-
-component.selectOptions(component.getByLabelText('Fruit'), 'Blueberry')
-component.selectOptions(component.getByLabelText('Fruit'), ['Blueberry'. 'Grape'])
-```
-
-### `fixture`
-
-The Angular `ComponentFixture` of the component.
-
-For more info see the
-[Angular docs](https://angular.io/api/core/testing/ComponentFixture).
-
-```typescript
-const component = await render(AppComponent)
-
-const componentInstance = component.fixture.componentInstance as AppComponent
-```
-
-> 🚨 If you find yourself using `fixture` to access the component's internal
-> values you should reconsider! This probable means, you're testing
-> implementation details.
-
-### `container`
-
-The containing DOM node of your rendered Angular Component. This is a regular
-DOM node, so you can call `container.querySelector` etc. to inspect the
-children.
-
-### `debug`
-
-Prints out the component's DOM with syntax highlighting. Accepts an optional
-parameter, to print out a specific DOM node.
-
-```typescript
-const component = await render(AppComponent)
-
-component.debug()
-component.debug(component.getByRole('alert'))
-```
diff --git a/docs/angular-testing-library/api.mdx b/docs/angular-testing-library/api.mdx
new file mode 100644
index 000000000..08daa3359
--- /dev/null
+++ b/docs/angular-testing-library/api.mdx
@@ -0,0 +1,597 @@
+---
+id: api
+title: API
+---
+
+`Angular Testing Library` re-exports everything from `DOM Testing Library` as
+well as the `render` method.
+
+The following re-exports are patched to make them easier to use with Angular:
+
+- The events on `fireEvent` automatically invoke a change detection cycle after
+  the event has been fired
+- The `findBy` queries automatically invoke a change detection cycle before the
+  query is invoked function
+- The `waitFor` functions automatically invoke a change detection cycle before
+  invoking the callback function
+
+## `render`
+
+With Angular Testing Library, the component can be rendered in two ways, via the
+component's type or with a template.
+
+> By default, `render` also imports the `NoopAnimationsModule`.
+
+## `Type`
+
+To render a component, you need to pass component's type to the `render` method.
+For components that don't use other parts of your application (for example
+design modules or services), rendering a component can be as simple as the
+following example.
+
+```typescript
+await render(AppComponent)
+```
+
+## `template`
+
+Instead of passing the component's type as first argument, you can also provide
+a template. This practice is required to render directives but can also be
+applied to components, it might even be more useful. The directive's (or
+component's) type must then be added to the `imports` (or `declarations` in case
+of non-standalone components).
+
+**example with directive**:
+
+```typescript
+await render('
', {
+  declarations: [SpoilerDirective],
+})
+```
+
+**example with component**:
+
+```typescript
+await render(
+  '(
+  component: Type,
+  renderOptions?: RenderComponentOptions,
+): Promise>
+export async function render(
+  template: string,
+  renderOptions?: RenderTemplateOptions,
+): Promise>
+```
+
+## Component RenderOptions
+
+
+### `inputs`
+
+An object to set `@Input` or `input()` properties of the component.
+
+**default** : `{}`
+
+```typescript
+await render(AppComponent, {
+  inputs: {
+    counterValue: 10,
+    // explicitly define aliases using `aliasedInput`
+    ...aliasedInput('someAlias', 'someValue'),
+  },
+})
+```
+
+### `on`
+
+An object with callbacks to subscribe to `EventEmitters` and `Observables` of
+the component.
+
+**default** : `{}`
+
+```ts
+// using a manual callback
+const sendValue = (value) => { ... }
+await render(AppComponent, {
+  on: {
+    send: (value) => sendValue(value),
+  }
+})
+
+// using a (jest) spy
+const sendValueSpy = jest.fn()
+
+await render(AppComponent, {
+  on: {
+    send: sendValueSpy
+  }
+})
+```
+
+### `declarations`
+
+A collection of components, directives and pipes needed to render the component.
+For example, nested components of the component.
+
+For more info see the
+[Angular docs](https://angular.dev/guide/ngmodules/overview#declarations).
+
+**default** : `[]`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  declarations: [CustomerDetailComponent, ButtonComponent],
+})
+```
+
+### `deferBlockBehavior`
+
+Set the defer blocks behavior.
+
+For more info see the
+[Angular docs](https://angular.dev/api/core/testing/DeferBlockBehavior)
+
+**default** : `undefined` (uses `DeferBlockBehavior.Manual`, which is different
+from the Angular default of `DeferBlockBehavior.Playthrough`)
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  deferBlockBehavior: DeferBlockBehavior.Playthrough,
+})
+```
+
+### `deferBlockStates`
+
+Set the initial state of a deferrable blocks in a component.
+
+For more info see the
+[Angular docs](https://angular.dev/api/core/testing/DeferBlockState)
+
+**default** : `undefined` (uses the Angular default, which is
+`DeferBlockState.Placeholder`)
+
+**example**:
+
+```typescript
+await render(FixtureComponent, {
+  deferBlockStates: DeferBlockState.Loading,
+})
+```
+
+### `componentProviders`
+
+A collection of providers needed to render the component via Dependency
+Injection.
+
+These will be provided at the component level. To inject dependencies at the
+module level, use [`providers`](#providers).
+
+For more info see the
+[Angular docs](https://angular.dev/guide/di/hierarchical-dependency-injection#example-providing-services-in-component).
+
+**default** : `[]`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  componentProviders: [AppComponentService],
+})
+```
+
+### `componentImports`
+
+A collection of imports to override a standalone component's imports with.
+
+**default** : `undefined`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  componentImports: [MockChildComponent],
+})
+```
+
+### `childComponentOverrides`
+
+Collection of child component specified providers to override with.
+
+**default** : `undefined`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  childComponentOverrides: [
+    {
+      component: ChildOfAppComponent,
+      providers: [{provide: ChildService, useValue: {hello: 'world'}}],
+    },
+  ],
+})
+```
+
+### `detectChangesOnRender`
+
+Invokes `detectChanges` after the component is rendered.
+
+**default** : `true`
+
+**example**:
+
+```typescript
+await render(AppComponent, {detectChangesOnRender: false})
+```
+
+### `autoDetectChanges`
+
+Automatically detect changes as a "real" running component would do. For
+example, runs a change detection cycle when an event has occured.
+
+**default** : `true`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  autoDetectChanges: false,
+})
+```
+
+### `excludeComponentDeclaration`
+
+Exclude the component to be automatically be added as a declaration. This is
+needed when the component is declared in an imported module, for example with
+SCAMs.
+
+**default** : `false`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  imports: [AppModule], // a module that includes AppComponent
+  excludeComponentDeclaration: true,
+})
+```
+
+### `imports`
+
+A collection of imports needed to render the component, for example, shared
+modules. Adds `NoopAnimationsModule` by default if `BrowserAnimationsModule`
+isn't added to the collection
+
+For more info see the
+[Angular docs](https://angular.dev/guide/components#imports-in-the-component-decorator).
+
+**default** : `[NoopAnimationsModule]`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  imports: [AppSharedModule, MaterialModule],
+})
+```
+
+### `providers`
+
+A collection of providers needed to render the component via Dependency
+Injection.
+
+These will be provided at the module level. To inject dependencies at the
+component level, use [`componentProviders`](#componentProviders).
+
+For more info see the
+[Angular docs](https://angular.dev/guide/di/dependency-injection-providers#).
+
+**default** : `[]`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  providers: [
+    CustomersService,
+    {
+      provide: MAX_CUSTOMERS_TOKEN,
+      useValue: 10,
+    },
+  ],
+})
+```
+
+### `queries`
+
+Queries to bind. Overrides the default set from DOM Testing Library unless
+merged.
+
+**default** : `undefined`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  queries: {...queries, ...customQueries},
+})
+```
+
+### `routes`
+
+The route configuration to set up the router service via
+`RouterTestingModule.withRoutes`. For more info see the
+[Angular Routes docs](https://angular.dev/api/router/Routes).
+
+**default** : `[]`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  declarations: [ChildComponent],
+  routes: [
+    {
+      path: '',
+      children: [
+        {
+          path: 'child/:id',
+          component: ChildComponent,
+        },
+      ],
+    },
+  ],
+})
+```
+
+### `schemas`
+
+A collection of schemas needed to render the component. Allowed values are
+`NO_ERRORS_SCHEMA` and `CUSTOM_ELEMENTS_SCHEMA`.
+
+For more info see the
+[Angular docs](https://angular.dev/guide/components/advanced-configuration#custom-element-schemas).
+
+**default** : `[]`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  schemas: [NO_ERRORS_SCHEMA],
+})
+```
+
+### `removeAngularAttributes`
+
+Removes the Angular attributes (ng-version, and root-id) from the fixture.
+
+**default** : `false`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  removeAngularAttributes: true,
+})
+```
+
+
+### ~~`componentInputs`~~ (deprecated)
+
+An object to set `@Input` properties of the component. Uses `setInput` to set
+the input property. Throws if the component property is not annotated with the
+`@Input` attribute.
+
+**default** : `{}`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  componentInputs: {
+    counterValue: 10,
+  },
+})
+```
+
+### ~~`componentOutputs`~~ (deprecated)
+
+An object to set `@Output` properties of the component.
+
+**default** : `{}`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  componentOutputs: {
+    clicked: (value) => { ... }
+  }
+})
+```
+
+### ~~`componentProperties`~~ (deprecated)
+
+An object to set `@Input` and `@Output` properties of the component. Doesn't
+have a fine-grained control as `inputs` and `on`.
+
+**default** : `{}`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+  componentProperties: {
+    // an input
+    counterValue: 10,
+    // an output
+    send: (value) => { ... }
+    // a public property
+    name: 'Tim'
+  }
+})
+```
+
+
+## `RenderResult`
+
+### `container`
+
+The containing DOM node of your rendered Angular Component. This is a regular
+DOM node, so you can call `container.querySelector` etc. to inspect the
+children.
+
+### `debug`
+
+Prints out the component's DOM with syntax highlighting. Accepts an optional
+parameter, to print out a specific DOM node.
+
+```typescript
+const {debug} = await render(AppComponent)
+
+debug()
+```
+
+### `rerender`
+
+Changes the input properties of the existing component instance by following
+Angular component lifecycle events (i.e. `ngOnChanges` is called). Input
+properties that are not defined are cleared.
+
+```typescript
+const {rerender} = await render(Counter, {
+  inputs: {count: 4, name: 'Sarah'},
+})
+
+expect(screen.getByTestId('count-value').textContent).toBe('4')
+expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
+
+await rerender({
+  inputs: {count: 7}
+})
+
+// count is updated to 7
+expect(screen.getByTestId('count-value').textContent).toBe('7')
+// name is undefined because it's not provided in rerender
+expect(screen.getByTestId('name-value').textContent).toBeUndefined()
+```
+
+Using `partialUpdate`, only the newly provided properties will be updated. Other
+input properties that aren't provided won't be cleared.
+
+```typescript
+const {rerender} = await render(Counter, {
+  inputs: {count: 4, name: 'Sarah'},
+})
+
+expect(screen.getByTestId('count-value').textContent).toBe('4')
+expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
+
+await rerender({inputs: {count: 7}, partialUpdate: true})
+
+// count is updated to 7
+expect(screen.getByTestId('count-value').textContent).toBe('7')
+// name is still rendered as "Sarah" because of the partial update
+expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
+```
+
+### `detectChanges`
+
+Trigger a change detection cycle for the component.
+
+For more info see the
+[Angular docs](https://angular.dev/api/core/testing/ComponentFixture#detectChanges).
+
+### `debugElement`
+
+The Angular `DebugElement` of the component.
+
+For more info see the [Angular docs](https://angular.dev/api/core/DebugElement).
+
+### `fixture`
+
+The Angular `ComponentFixture` of the component.
+
+For more info see the
+[Angular docs](https://angular.dev/api/core/testing/ComponentFixture).
+
+```typescript
+const {fixture} = await render(AppComponent)
+
+// componentInstance is typed as AppComponent
+const componentInstance = fixture.componentInstance
+```
+
+> 🚨 If you find yourself using `fixture` to access the component's internal
+> values you should reconsider! This probable means, you're testing
+> implementation details.
+
+### `navigate`
+
+Accepts a DOM element or a path as parameter. If an element is passed,
+`navigate` will navigate to the `href` value of the element. If a path is
+passed, `navigate` will navigate to the path.
+
+```typescript
+const { navigate } = await render(AppComponent, {
+  routes: [...]
+})
+
+await navigate(component.getByLabelText('To details'))
+await navigate('details/3')
+```
+
+### `...queries`
+
+The most important feature of `render` is that the queries from
+[DOM Testing Library](/docs/dom-testing-library/intro) are automatically
+returned with their first argument bound to the component under test.
+
+See [Queries](queries/about.mdx) for a complete list.
+
+**example**:
+
+```typescript
+const {getByText, queryByLabelText} = await render(AppComponent)
+
+screen.getByRole('heading', {
+  name: /api/i,
+})
+queryByLabelText(/First name/i')
+```
+
+### `renderDeferBlock`
+
+To test [Deferrable views](https://angular.dev/guide/defer#defer), you can make
+use of `renderDeferBlock`. `renderDeferBlock` will set the desired defer state
+for a specific deferrable block. The default value of a deferrable view is
+`Placeholder`, but you can also set the initial state while rendering the
+component.
+
+```typescript
+const {renderDeferBlock} = await render(FixtureComponent, {
+  deferBlockStates: DeferBlockState.Loading,
+})
+
+expect(screen.getByText(/loading/i)).toBeInTheDocument()
+
+await renderDeferBlock(DeferBlockState.Complete)
+expect(screen.getByText(/completed/i)).toBeInTheDocument()
+```
diff --git a/docs/angular-testing-library/examples.md b/docs/angular-testing-library/examples.md
deleted file mode 100644
index ad2e2cd35..000000000
--- a/docs/angular-testing-library/examples.md
+++ /dev/null
@@ -1,69 +0,0 @@
----
-id: examples
-title: Examples
-sidebar_label: Examples
----
-
-counter.component.ts
-
-```typescript
-@Component({
-  selector: 'counter',
-  template: `
-    - 
-    Current Count: {{ counter }} 
-    + 
-  `,
-})
-export class CounterComponent {
-  @Input() counter = 0
-
-  increment() {
-    this.counter += 1
-  }
-
-  decrement() {
-    this.counter -= 1
-  }
-}
-```
-
-counter.component.spec.ts
-
-```typescript
-import { render } from '@testing-library/angular'
-import CounterComponent from './counter.component.ts'
-
-describe('Counter', () => {
-  test('should render counter', async () => {
-    const { getByText } = await render(CounterComponent, {
-      componentProperties: { counter: 5 },
-    })
-
-    expect(getByText('Current Count: 5'))
-  })
-
-  test('should increment the counter on click', async () => {
-    const { getByText, click } = await render(CounterComponent, {
-      componentProperties: { counter: 5 },
-    })
-
-    click(getByText('+'))
-
-    expect(getByText('Current Count: 6'))
-  })
-})
-```
-
-More examples can be found in the
-[GitHub project](https://github.com/testing-library/angular-testing-library/tree/master/src/app/examples).
-These examples include:
-
-- `@Input` and `@Output` properties
-- (Reactive) Forms
-- Integration with NgRx (mock) Store
-- And more
-
-If you're looking for an example that isn't on the list, please feel free to
-create a
-[new issue](https://github.com/testing-library/angular-testing-library/issues/new).
diff --git a/docs/angular-testing-library/examples.mdx b/docs/angular-testing-library/examples.mdx
new file mode 100644
index 000000000..2e44b893c
--- /dev/null
+++ b/docs/angular-testing-library/examples.mdx
@@ -0,0 +1,82 @@
+---
+id: examples
+title: Example
+---
+
+> Read about
+> [best practices](https://timdeschryver.dev/blog/good-testing-practices-with-angular-testing-library),
+> or follow the
+> [guided example](https://timdeschryver.dev/blog/getting-the-most-value-out-of-your-angular-component-tests)
+
+Angular Testing Library can be used with standalone components and also with Angular components that uses Modules.
+The example below shows how to test a standalone component, but the same principles apply to Angular components that uses Modules.
+In fact, there should be no difference in how you test both types of components, only the setup might be different.
+
+```ts title="counter.component.ts"
+@Component({
+  selector: 'app-counter',
+  template: `
+    {{ hello() }} 
+    - 
+    Current Count: {{ counter() }} 
+    + 
+  `,
+})
+export class CounterComponent {
+  counter = model(0);
+  hello = input('Hi', { alias: 'greeting' });
+
+  increment() {
+    this.counter.set(this.counter() + 1);
+  }
+
+  decrement() {
+    this.counter.set(this.counter() - 1);
+  }
+}
+```
+
+```typescript title="counter.component.spec.ts"
+import { render, screen, fireEvent, aliasedInput } from '@testing-library/angular';
+import { CounterComponent } from './counter.component';
+
+describe('Counter', () => {
+  it('should render counter', async () => {
+    await render(CounterComponent, {
+      inputs: {
+        counter: 5,
+        // aliases need to be specified using aliasedInput
+        ...aliasedInput('greeting', 'Hello Alias!'),
+      },
+    });
+
+    expect(screen.getByText('Current Count: 5')).toBeVisible();
+    expect(screen.getByText('Hello Alias!')).toBeVisible();
+  });
+
+  it('should increment the counter on click', async () => {
+    await render(CounterComponent, { inputs: { counter: 5 } });
+
+    const incrementButton = screen.getByRole('button', { name: '+' });
+    fireEvent.click(incrementButton);
+
+    expect(screen.getByText('Current Count: 6')).toBeVisible();
+  });
+});
+```
+
+## More examples
+
+More examples can be found in the
+[GitHub project](https://github.com/testing-library/angular-testing-library/tree/master/apps/example-app/src/app/examples).
+These examples include:
+
+- `input` and `output` properties
+- Forms
+- Integration injected services
+- And
+  [more](https://github.com/testing-library/angular-testing-library/tree/master/apps/example-app/src/app/examples)
+
+If you're looking for an example that isn't on the list, please feel free to
+create a
+[new issue](https://github.com/testing-library/angular-testing-library/issues/new).
diff --git a/docs/angular-testing-library/faq.mdx b/docs/angular-testing-library/faq.mdx
new file mode 100644
index 000000000..e333db4b3
--- /dev/null
+++ b/docs/angular-testing-library/faq.mdx
@@ -0,0 +1,109 @@
+---
+id: faq
+title: FAQ
+---
+
+See also the [main FAQ](dom-testing-library/faq.mdx) for questions not specific
+to Angular testing.
+
+
+
+Can I write unit tests with this library? 
+
+Definitely yes! You can write unit and integration tests with this library. See
+below for more on how to mock dependencies (because this library intentionally
+does NOT support shallow rendering) if you want to unit test a high level
+component. The tests in this project show several examples of unit testing with
+this library.
+
+As you write your tests, keep in mind:
+
+> The more your tests resemble the way your software is used, the more
+> confidence they can give you. - [17 Feb 2018][guiding-principle]
+
+ 
+
+
+
+
+  If I can't use shallow rendering, how do I mock out components in tests?
+ 
+
+In general, you should avoid mocking out components (see
+[the Guiding Principles section](guiding-principles.mdx)). However, if you need
+to, then try to use [ng-mocks](https://ng-mocks.sudo.eu/) and its
+[`MockBuilder`](https://ng-mocks.sudo.eu/extra/with-3rd-party#testing-libraryangular-and-mockbuilder).
+
+```typescript
+import {Component, NgModule} from '@angular/core'
+import {render, screen} from '@testing-library/angular'
+import {MockBuilder} from 'ng-mocks'
+
+@Component({
+  selector: 'app-parent-component',
+  template: 'Child component
',
+})
+class ChildComponent {}
+
+@NgModule({
+  declarations: [ParentComponent, ChildComponent],
+})
+export class AppModule {}
+
+describe('ParentComponent', () => {
+  it('should not render ChildComponent when shallow rendering', async () => {
+    // all imports, declarations and exports of AppModule will be mocked.
+    const dependencies = MockBuilder(ParentComponent, AppModule).build()
+
+    await render(ParentComponent, dependencies)
+
+    expect(screen.queryByText('Child component')).toBeNull()
+  })
+})
+```
+
+ 
+
+
+
+
+  What level of a component tree should I test? Children, parents, or both?
+ 
+
+Following the guiding principle of this library, it is useful to break down how
+tests are organized around how the user experiences and interacts with
+application functionality rather than around specific components themselves. In
+some cases, for example for reusable component libraries, it might be useful to
+include developers in the list of users to test for and test each of the
+reusable components individually. Other times, the specific break down of a
+component tree is just an implementation detail and testing every component
+within that tree individually can cause issues (see
+https://kentcdodds.com/blog/avoid-the-test-user).
+
+In practice this means that it is often preferable to test high enough up the
+component tree to simulate realistic user interactions. The question of whether
+it is worth additionally testing at a higher or lower level on top of this comes
+down to a question of tradeoffs and what will provide enough value for the cost
+(see https://kentcdodds.com/blog/unit-vs-integration-vs-e2e-tests on more info
+on different levels of testing).
+
+For a more in-depth discussion of this topic see
+[this video](https://youtu.be/0qmPdcV-rN8).
+
+ 
+
+
+
+
+
+[guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106
+
+
diff --git a/docs/angular-testing-library/intro.md b/docs/angular-testing-library/intro.mdx
similarity index 82%
rename from docs/angular-testing-library/intro.md
rename to docs/angular-testing-library/intro.mdx
index 42d30e6ff..a7820b7f0 100644
--- a/docs/angular-testing-library/intro.md
+++ b/docs/angular-testing-library/intro.mdx
@@ -8,9 +8,17 @@ sidebar_label: Introduction
 builds on top of
 [`DOM Testing Library`](https://github.com/testing-library/dom-testing-library)
 by adding APIs for working with Angular components.
+Starting from ATL version 17, you also need to install `@testing-library/dom`:
+
+```bash npm2yarn
+npm install --save-dev @testing-library/angular @testing-library/dom
+```
+
+Or, you can use the `ng add` command.
+This sets up your project to use Angular Testing Library, which also includes the installation of `@testing-library/dom`.
 
 ```bash
-npm install --save-dev @testing-library/angular
+ng add @testing-library/angular
 ```
 
 - [`@testing-library/angular-testing-library` on GitHub](https://github.com/testing-library/angular-testing-library)
@@ -33,11 +41,11 @@ components. It provides light utility functions on top of
 in a way that encourages better testing practices. Its primary guiding principle
 is:
 
-> [The more your tests resemble the way your software is used, the more confidence they can give you.](guiding-principles.md)
+> [The more your tests resemble the way your software is used, the more confidence they can give you.](guiding-principles.mdx)
 
 So rather than dealing with instances of rendered Angular components, your tests
 will work with actual DOM nodes. The utilities this library provides facilitate
-querying the DOM in the same way the user would. Finding for elements by their
+querying the DOM in the same way the user would. Finding form elements by their
 label text (just like a user would), finding links and buttons from their text
 (like a user would). It also exposes a recommended way to find elements by a
 `data-testid` as an "escape hatch" for elements where the text content and label
diff --git a/docs/angular-testing-library/version-compatibility.mdx b/docs/angular-testing-library/version-compatibility.mdx
new file mode 100644
index 000000000..3b64dd5d2
--- /dev/null
+++ b/docs/angular-testing-library/version-compatibility.mdx
@@ -0,0 +1,18 @@
+---
+id: version-compatibility
+title: Version compatibility
+---
+
+An overview of the compatibility between different versions of Angular Testing
+Library and Angular.
+
+| Angular | Angular Testing Library            |
+| ------- | ---------------------------------- |
+| 20.x    | 18.x                               |
+| 19.x    | 18.x, 17.x, 16.x, 15.x, 14.x, 13.x |
+| 18.x    | 17.x, 16.x, 15.x, 14.x, 13.x       |
+| 17.x    | 17.x, 16.x, 15.x, 14.x, 13.x       |
+| 16.x    | 14.x, 13.x                         |
+| >= 15.1 | 14.x, 13.x                         |
+| < 15.1  | 12.x, 11.x                         |
+| 14.x    | 12.x, 11.x                         |
diff --git a/docs/bs-react-testing-library/examples.md b/docs/bs-react-testing-library/examples.mdx
similarity index 97%
rename from docs/bs-react-testing-library/examples.md
rename to docs/bs-react-testing-library/examples.mdx
index ce8d544a7..08e96a7c9 100644
--- a/docs/bs-react-testing-library/examples.md
+++ b/docs/bs-react-testing-library/examples.mdx
@@ -1,6 +1,6 @@
 ---
 id: examples
-title: Examples
+title: Example
 ---
 
 You can find more bs-dom-testing-library examples at
@@ -11,9 +11,7 @@ You can find more bs-react-testing-library examples at
 
 ## React Testing Library
 
-```reason
-/* Component_test.re */
-
+```reason title="Component_test.re"
 open Jest;
 open Expect;
 open ReactTestingLibrary;
@@ -37,8 +35,7 @@ with typings and creating events.
 
 ### getByText
 
-```reason
-/* __tests__/example_test.re */
+```reason title="__tests__/example_test.re"
 open Jest;
 open DomTestingLibrary;
 open Expect;
diff --git a/docs/bs-react-testing-library/intro.md b/docs/bs-react-testing-library/intro.mdx
similarity index 95%
rename from docs/bs-react-testing-library/intro.md
rename to docs/bs-react-testing-library/intro.mdx
index 8e2545423..316ccc9b2 100644
--- a/docs/bs-react-testing-library/intro.md
+++ b/docs/bs-react-testing-library/intro.mdx
@@ -13,8 +13,11 @@ Bindings for several testing libraries have been ported to [ReasonML][re].
 [`bs-dom-testing-library`][gh-dom] contains [BuckleScript][bs] bindings for
 `DOM Testing Library`.
 
-```
+```bash npm2yarn
 npm install --save-dev bs-dom-testing-library
+```
+
+```bash npm2yarn
 npm install --save-dev bs-react-testing-library
 ```
 
@@ -49,7 +52,7 @@ _or_
 This is what [BuckleScript][bs] uses to compile the [Reason][re] code to JS. If
 it is not in your project you can install it like so:
 
-```
+```bash npm2yarn
 npm install --save-dev bs-platform
 ```
 
@@ -60,7 +63,7 @@ examples here will be using it.
 
 - [bs-jest on GitHub](https://github.com/glennsl/bs-jest)
 
-```
+```bash npm2yarn
 npm install --save-dev @glennsl/bs-jest
 ```
 
diff --git a/docs/contributing.md b/docs/contributing.md
deleted file mode 100644
index d446eacbe..000000000
--- a/docs/contributing.md
+++ /dev/null
@@ -1,81 +0,0 @@
----
-id: contributing
-title: Contributing
-sidebar_label: Contributing
----
-
-## License
-
-`React Testing Library` is distributed under the open-source MIT license
-
-## 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]
-
-### ❓ Questions
-
-For questions related to using the library, please visit a support community
-instead of filing an issue on GitHub.
-
-- [Spectrum][spectrum]
-- [Reactiflux on Discord][reactiflux]
-- [Stack Overflow][stackoverflow]
-
-
-
-
-
-[npm]: https://www.npmjs.com/
-[node]: https://nodejs.org
-[build-badge]: https://img.shields.io/travis/kentcdodds/react-testing-library.svg?style=flat-square
-[build]: https://travis-ci.org/kentcdodds/react-testing-library
-[coverage-badge]: https://img.shields.io/codecov/c/github/kentcdodds/react-testing-library.svg?style=flat-square
-[coverage]: https://codecov.io/github/kentcdodds/react-testing-library
-[version-badge]: https://img.shields.io/npm/v/react-testing-library.svg?style=flat-square
-[package]: https://www.npmjs.com/package/react-testing-library
-[downloads-badge]: https://img.shields.io/npm/dm/react-testing-library.svg?style=flat-square
-[npmtrends]: http://www.npmtrends.com/react-testing-library
-[spectrum-badge]: https://withspectrum.github.io/badge/badge.svg
-[spectrum]: https://spectrum.chat/testing-library
-[license-badge]: https://img.shields.io/npm/l/react-testing-library.svg?style=flat-square
-[license]: https://github.com/testing-library/react-testing-library/blob/master/LICENSE
-[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
-[prs]: http://makeapullrequest.com
-[donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square
-[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
-[coc]: https://github.com/testing-library/react-testing-library/blob/master/CODE_OF_CONDUCT.md
-[github-watch-badge]: https://img.shields.io/github/watchers/kentcdodds/react-testing-library.svg?style=social
-[github-watch]: https://github.com/testing-library/react-testing-library/watchers
-[github-star-badge]: https://img.shields.io/github/stars/kentcdodds/react-testing-library.svg?style=social
-[github-star]: https://github.com/testing-library/react-testing-library/stargazers
-[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20react-testing-library%20by%20%40kentcdodds%20https%3A%2F%2Fgithub.com%2Fkentcdodds%2Freact-testing-library%20%F0%9F%91%8D
-[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/testing-library/react-testing-library.svg?style=social
-[emojis]: https://github.com/kentcdodds/all-contributors#emoji-key
-[all-contributors]: https://github.com/kentcdodds/all-contributors
-[set-immediate]: https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate
-[guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106
-[data-testid-blog-post]: https://blog.kentcdodds.com/making-your-ui-tests-resilient-to-change-d37a6ee37269
-[dom-testing-lib-textmatch]: https://github.com/testing-library/dom-testing-library#textmatch
-[bugs]: https://github.com/testing-library/react-testing-library/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Acreated-desc
-[requests]: https://github.com/testing-library/react-testing-library/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3Aenhancement+is%3Aopen
-[good-first-issue]: https://github.com/testing-library/react-testing-library/issues?utf8=✓&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A"good+first+issue"+
-[reactiflux]: https://www.reactiflux.com/
-[stackoverflow]: https://stackoverflow.com/questions/tagged/react-testing-library
-
-
diff --git a/docs/contributing.mdx b/docs/contributing.mdx
new file mode 100644
index 000000000..167844e54
--- /dev/null
+++ b/docs/contributing.mdx
@@ -0,0 +1,49 @@
+---
+id: contributing
+title: Contributing
+sidebar_label: Contributing
+---
+
+## License
+
+`React Testing Library` is distributed under the open-source MIT license
+
+## 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]
+
+### ❓ Questions
+
+For questions related to using the library, please visit a support community
+instead of filing an issue on GitHub.
+
+- [Discord][discord]
+- [Stack Overflow][stackoverflow]
+
+
+
+
+
+[bugs]: https://github.com/testing-library/react-testing-library/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Acreated-desc
+[requests]: https://github.com/testing-library/react-testing-library/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3Aenhancement+is%3Aopen
+[good-first-issue]: https://github.com/testing-library/react-testing-library/issues?utf8=✓&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A"good+first+issue"+
+[discord]: https://discord.gg/testing-library
+[stackoverflow]: https://stackoverflow.com/questions/tagged/react-testing-library
+
+
diff --git a/docs/cypress-testing-library/intro.md b/docs/cypress-testing-library/intro.md
deleted file mode 100644
index bbc7cefee..000000000
--- a/docs/cypress-testing-library/intro.md
+++ /dev/null
@@ -1,68 +0,0 @@
----
-id: intro
-title: Cypress Testing Library
----
-
-[`Cypress Testing Library`][gh] allows the use of dom-testing queries within
-[Cypress](https://cypress.io) end-to-end browser tests.
-
-```
-npm install --save-dev cypress @testing-library/cypress
-```
-
-- [Cypress Testing Library on GitHub][gh]
-
-## Usage
-
-`Cypress Testing Library` extends Cypress's `cy` commands.
-
-Add this line to your project's `cypress/support/commands.js`:
-
-```
-import '@testing-library/cypress/add-commands';
-```
-
-## With TypeScript
-
-Typings are defined in `@types/testing-library__cypress` at [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/testing-library__cypress),
-and should be added as follows in `tsconfig.json`:
-
-```json
-{
-  "compilerOptions": {
-    "types": ["cypress", "@types/testing-library__cypress"]
-  }
-}
-```
-
-You can now use all of `DOM Testing Library`'s `getBy`, `getAllBy`, `queryBy`
-and `queryAllBy` commands.
-[See `DOM Testing Library` API for reference](dom-testing-library/api-queries.md)
-
-## Examples
-
-You can find [all library definitions here](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/testing-library__cypress/index.d.ts).
-
-To show some simple examples (from
-[https://github.com/testing-library/cypress-testing-library/blob/master/cypress/integration/commands.spec.js](https://github.com/testing-library/cypress-testing-library/blob/master/cypress/integration/commands.spec.js)):
-
-```javascript
-cy.getAllByText('Jackie Chan').click()
-cy.queryByText('Button Text').should('exist')
-cy.queryByText('Non-existing Button Text').should('not.exist')
-cy.queryByLabelText('Label text', { timeout: 7000 }).should('exist')
-cy.get('form').within(() => {
-  cy.getByText('Button Text').should('exist')
-})
-cy.get('form').then(subject => {
-  cy.getByText('Button Text', { container: subject }).should('exist')
-})
-```
-
-`Cypress Testing Library` supports both jQuery elements and DOM nodes. This is
-necessary because Cypress uses jQuery elements, while `DOM Testing Library`
-expects DOM nodes. When you pass a jQuery element as `container`, it will get
-the first DOM node from the collection and use that as the `container` parameter
-for the DOM Testing Library functions.
-
-[gh]: https://github.com/testing-library/cypress-testing-library
diff --git a/docs/cypress-testing-library/intro.mdx b/docs/cypress-testing-library/intro.mdx
new file mode 100644
index 000000000..3c88d4d2b
--- /dev/null
+++ b/docs/cypress-testing-library/intro.mdx
@@ -0,0 +1,75 @@
+---
+id: intro
+title: Cypress Testing Library
+---
+
+[`Cypress Testing Library`][gh] allows the use of dom-testing queries within
+[Cypress](https://cypress.io) end-to-end browser tests.
+
+```bash npm2yarn
+npm install --save-dev cypress @testing-library/cypress
+```
+
+- [Cypress Testing Library on GitHub][gh]
+
+## Usage
+
+`Cypress Testing Library` extends Cypress's `cy` commands.
+
+Add this line to your project's `cypress/support/commands.js`:
+
+```js
+import '@testing-library/cypress/add-commands'
+```
+
+You can now use some of `DOM Testing Library`'s `findBy`, and `findAllBy` commands off the global `cy` object.
+[See the `About queries` docs for reference](/docs/queries/about).
+
+> Note: the `get*` queries are not supported because for reasonable Cypress
+> tests you need retryability and `find*` queries already support that. `query*`
+> queries are no longer necessary since v5 and will be removed in v6. `find*`
+> fully support built-in Cypress assertions (removes the only use-case for
+> `query*`).
+
+## With TypeScript
+
+Typings should be added as follows in `tsconfig.json`:
+
+```json
+{
+  "compilerOptions": {
+    "types": ["cypress", "@testing-library/cypress"]
+  }
+}
+```
+
+You can find
+[all Library definitions here](https://github.com/testing-library/cypress-testing-library/blob/master/types/index.d.ts).
+
+## Examples
+
+To show some simple examples (from
+[cypress/integration/find.spec.js](https://github.com/testing-library/cypress-testing-library/blob/97939da7d4707a71049884c0324c0eda56e26fc2/cypress/integration/find.spec.js)):
+
+```javascript
+cy.findByRole('button', {name: /Jackie Chan/i}).click()
+cy.findByRole('button', {name: /Button Text/i}).should('exist')
+cy.findByRole('button', {name: /Non-existing Button Text/i}).should('not.exist')
+cy.findByLabelText(/Label text/i, {timeout: 7000}).should('exist')
+
+// findByRole _inside_ a form element
+cy.get('form')
+  .findByRole('button', {name: /Button Text/i})
+  .should('exist')
+cy.findByRole('dialog').within(() => {
+  cy.findByRole('button', {name: /confirm/i})
+})
+```
+
+`Cypress Testing Library` supports both jQuery elements and DOM nodes. This is
+necessary because Cypress uses jQuery elements, while `DOM Testing Library`
+expects DOM nodes. When you pass a jQuery element as `container`, it will get
+the first DOM node from the collection and use that as the `container` parameter
+for the `DOM Testing Library` functions.
+
+[gh]: https://github.com/testing-library/cypress-testing-library
diff --git a/docs/dom-testing-library/api-accessibility.mdx b/docs/dom-testing-library/api-accessibility.mdx
new file mode 100644
index 000000000..9b5e4e761
--- /dev/null
+++ b/docs/dom-testing-library/api-accessibility.mdx
@@ -0,0 +1,92 @@
+---
+id: api-accessibility
+title: Accessibility
+---
+
+## Testing for Accessibility
+
+One of the guiding principles of the Testing Library APIs is that they should
+enable you to test your app the way your users use it, including through
+accessibility interfaces like screen readers.
+
+See the page on [queries](queries/about.mdx#priority) for details on how using a
+semantic HTML query can make sure your app works with browser accessibility
+APIs.
+
+## `getRoles`
+
+This function allows iteration over the implicit ARIA roles represented in a
+given tree of DOM nodes.
+
+It returns an object, indexed by role name, with each value being an array of
+elements which have that implicit ARIA role.
+
+See
+[ARIA in HTML](https://www.w3.org/TR/html-aria/#document-conformance-requirements-for-use-of-aria-attributes-in-html)
+for more information about implicit ARIA roles.
+
+```javascript
+import {getRoles} from '@testing-library/dom'
+
+const nav = document.createElement('nav')
+nav.innerHTML = `
+`
+console.log(getRoles(nav))
+
+// Object {
+//   navigation: [
-```
-
-When in need to wait for non-deterministic periods of time you can use `wait`,
-to wait for your expectations to pass. The `wait` function is a small wrapper
-around the
-[`wait-for-expect`](https://github.com/TheBrainFamily/wait-for-expect) module.
-Here's a simple example:
-
-```javascript
-// ...
-// Wait until the callback does not throw an error. In this case, that means
-// it'll wait until we can get a form control with a label that matches "username".
-await wait(() => getByLabelText(container, 'username'))
-getByLabelText(container, 'username').value = 'chucknorris'
-// ...
-```
-
-This can be useful if you have a unit test that mocks API calls and you need to
-wait for your mock promises to all resolve.
-
-The default `callback` is a no-op function (used like `await wait()`). This can
-be helpful if you only need to wait for one tick of the event loop (in the case
-of mocked API calls with promises that resolve immediately).
-
-The default `timeout` is `4500ms` which will keep you under
-[Jest's default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout).
-
-The default `interval` is `50ms`. However it will run your callback immediately
-on the next tick of the event loop (in a `setTimeout`) before starting the
-intervals.
-
-## `waitForElement`
-
-```typescript
-function waitForElement(
-  callback: () => T,
-  options?: {
-    container?: HTMLElement
-    timeout?: number
-    mutationObserverOptions?: MutationObserverInit
-  }
-): Promise
-```
-
-When in need to wait for DOM elements to appear, disappear, or change you can
-use `waitForElement`. The `waitForElement` function is a small wrapper around
-the
-[`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
-
-Here's a simple example:
-
-```javascript
-// ...
-// Wait until the callback does not throw an error and returns a truthy value. In this case, that means
-// it'll wait until we can get a form control with a label that matches "username".
-// The difference from `wait` is that rather than running your callback on
-// an interval, it's run as soon as there are DOM changes in the container
-// and returns the value returned by the callback.
-const usernameElement = await waitForElement(
-  () => getByLabelText(container, 'username'),
-  { container }
-)
-usernameElement.value = 'chucknorris'
-// ...
-```
-
-You can also wait for multiple elements at once:
-
-```javascript
-const [usernameElement, passwordElement] = await waitForElement(
-  () => [
-    getByLabelText(container, 'username'),
-    getByLabelText(container, 'password'),
-  ],
-  { container }
-)
-```
-
-Using
-[`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
-is more efficient than polling the DOM at regular intervals with `wait`. This
-library sets up a
-[`'mutationobserver-shim'`](https://github.com/megawac/MutationObserver.js) on
-the global `window` object for cross-platform compatibility with older browsers
-and the [`jsdom`](https://github.com/jsdom/jsdom/issues/639) that is usually
-used in Node-based tests.
-
-The default `container` is the global `document`. Make sure the elements you
-wait for will be attached to it, or set a different `container`.
-
-The default `timeout` is `4500ms` which will keep you under
-[Jest's default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout).
-
-(options?: {
-  container?: HTMLElement
-  timeout?: number
-  mutationObserverOptions?: MutationObserverInit
-}): Promise
-```
-
-When in need to wait for the DOM to change you can use `waitForDomChange`. The
-`waitForDomChange` function is a small wrapper around the
-[`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
-
-Here is an example where the promise will be resolved because the container is
-changed:
-
-```javascript
-const container = document.createElement('div')
-waitForDomChange({ container })
-  .then(() => console.log('DOM changed!'))
-  .catch(err => console.log(`Error you need to deal with: ${err}`))
-container.append(document.createElement('p'))
-// if 👆 was the only code affecting the container and it was not run,
-// waitForDomChange would throw an error
-```
-
-The promise will resolve with a
-[`mutationsList`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/MutationObserver)
-which you can use to determine what kind of a change (or changes) affected the
-container
-
-```javascript
-const container = document.createElement('div')
-container.setAttribute('data-cool', 'true')
-waitForDomChange({ container }).then(mutationsList => {
-  const mutation = mutationsList[0]
-  console.log(
-    `was cool: ${mutation.oldValue}\ncurrently cool: ${
-      mutation.target.dataset.cool
-    }`
-  )
-})
-container.setAttribute('data-cool', 'false')
-/*
-  logs:
-    was cool: true
-    currently cool: false
-*/
-```
-
-Using
-[`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
-is more efficient than polling the DOM at regular intervals with `wait`. This
-library sets up a
-[`'mutationobserver-shim'`](https://github.com/megawac/MutationObserver.js) on
-the global `window` object for cross-platform compatibility with older browsers
-and the [`jsdom`](https://github.com/jsdom/jsdom/issues/639) that is usually
-used in Node-based tests.
-
-The default `container` is the global `document`. Make sure the elements you
-wait for will be attached to it, or set a different `container`.
-
-The default `timeout` is `4500ms` which will keep you under
-[Jest's default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout).
-
-(
-  callback: () => T,
-  options?: {
-    container?: HTMLElement
-    timeout?: number
-    mutationObserverOptions?: MutationObserverInit
-  }
-): Promise
-```
-
-To wait for the removal of element(s) from the DOM you can use
-`waitForElementToBeRemoved`. The `waitForElementToBeRemoved` function is a small
-wrapper around the
-[`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
-
-The callback must return the pre-existing element or array of elements that are
-expected to be removed.
-
-Here is an example where the promise resolves with `true` because the element is
-removed:
-
-```javascript
-const el = document.querySelector('div.getOuttaHere')
-
-waitForElementToBeRemoved(() =>
-  document.querySelector('div.getOuttaHere')
-).then(() => console.log('Element no longer in DOM'))
-
-el.setAttribute('data-neat', true)
-// other mutations are ignored...
-
-el.parentElement.removeChild(el)
-// logs 'Element no longer in DOM'
-```
-
-`waitForElementToBeRemoved` will throw an error when the provided callback does
-not return an element.
-
-```javascript
-waitForElementToBeRemoved(() => null).catch(err => console.log(err))
-
-// 'The callback function which was passed did not return an element
-// or non-empty array of elements.
-// waitForElementToBeRemoved requires that the element(s) exist
-// before waiting for removal.'
-```
-
-Using
-[`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
-is more efficient than polling the DOM at regular intervals with `wait`. This
-library sets up a
-[`'mutationobserver-shim'`](https://github.com/megawac/MutationObserver.js) on
-the global `window` object for cross-platform compatibility with older browsers
-and the [`jsdom`](https://github.com/jsdom/jsdom/issues/639) that is usually
-used in Node-based tests.
-
-The default `container` is the global `document`. Make sure the elements you
-wait for are descendants of `container`.
-
-The default `timeout` is `4500ms` which will keep you under
-[Jest's default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout).
-
-(
+  callback: () => T | Promise,
+  options?: {
+    container?: HTMLElement
+    timeout?: number
+    interval?: number
+    onTimeout?: (error: Error) => Error
+    mutationObserverOptions?: MutationObserverInit
+  },
+): Promise
+```
+
+When in need to wait for any period of time you can use `waitFor`, to wait for
+your expectations to pass. Returning _a falsy condition is not sufficient_ to
+trigger a retry, the callback must throw an error in order to retry the
+condition. Here's a simple example:
+
+```javascript
+// ...
+// Wait until the callback does not throw an error. In this case, that means
+// it'll wait until the mock function has been called once.
+await waitFor(() => expect(mockAPI).toHaveBeenCalledTimes(1))
+// ...
+```
+
+`waitFor` may run the callback a number of times until the timeout is reached.
+Note that the number of calls is constrained by the `timeout` and `interval`
+options.
+
+This can be useful if you have a unit test that mocks API calls and you need to
+wait for your mock promises to all resolve.
+
+If you return a promise in the `waitFor` callback (either explicitly or
+implicitly with the `async` syntax), then the `waitFor` utility does not call
+your callback again until that promise rejects. This allows you to `waitFor`
+things that must be checked asynchronously.
+
+The default `container` is the global `document`. Make sure the elements you
+wait for are descendants of `container`.
+
+The default `interval` is `50ms`. However it runs your callback immediately
+before starting the intervals.
+
+The default `timeout` is `1000ms`.
+
+The default `onTimeout` takes the error and appends the `container`'s printed
+state to the error message which should hopefully make it easier to track down
+what caused the timeout.
+
+The default `mutationObserverOptions` is
+`{subtree: true, childList: true, attributes: true, characterData: true}` which
+detects additions and removals of child elements (including text nodes) in the
+`container` and any of its descendants. It also detects attribute changes. When
+any of those changes occur, it re-runs the callback.
+
+## `waitForElementToBeRemoved`
+
+```typescript
+function waitForElementToBeRemoved(
+  callback: (() => T) | T,
+  options?: {
+    container?: HTMLElement
+    timeout?: number
+    interval?: number
+    onTimeout?: (error: Error) => Error
+    mutationObserverOptions?: MutationObserverInit
+  },
+): Promise
+```
+
+To wait for the removal of element(s) from the DOM you can use
+`waitForElementToBeRemoved`. The `waitForElementToBeRemoved` function is a small
+wrapper around the `waitFor` utility.
+
+The first argument must be an element, array of elements, or a callback which
+returns an element or array of elements.
+
+Here is an example where the promise resolves because the element is removed:
+
+```javascript
+const el = document.querySelector('div.getOuttaHere')
+
+waitForElementToBeRemoved(document.querySelector('div.getOuttaHere')).then(() =>
+  console.log('Element no longer in DOM'),
+)
+
+el.setAttribute('data-neat', true)
+// other mutations are ignored...
+
+el.parentElement.removeChild(el)
+// logs 'Element no longer in DOM'
+```
+
+`waitForElementToBeRemoved` throws an error if the first argument is `null` or
+an empty array:
+
+```javascript
+waitForElementToBeRemoved(null).catch(err => console.log(err))
+waitForElementToBeRemoved(queryByText(/not here/i)).catch(err =>
+  console.log(err),
+)
+waitForElementToBeRemoved(queryAllByText(/not here/i)).catch(err =>
+  console.log(err),
+)
+waitForElementToBeRemoved(() => getByText(/not here/i)).catch(err =>
+  console.log(err),
+)
+
+// Error: The element(s) given to waitForElementToBeRemoved are already removed. waitForElementToBeRemoved requires that the element(s) exist(s) before waiting for removal.
+```
+
+The options object is forwarded to `waitFor`.
diff --git a/docs/dom-testing-library/api-configuration.md b/docs/dom-testing-library/api-configuration.md
deleted file mode 100644
index 660495d02..000000000
--- a/docs/dom-testing-library/api-configuration.md
+++ /dev/null
@@ -1,47 +0,0 @@
----
-id: api-configuration
-title: Configuration
----
-
-## Configuration
-
-The library can be configured via the `configure` function, which accepts:
-
-- a plain JS object; this will be merged into the existing configuration. e.g.
-  `configure({testIdAttribute: 'not-data-testid'})`
-- a function; the function will be given the existing configuration, and should
-  return a plain JS object which will be merged as above, e.g.
-  `configure(existingConfig => ({something: [...existingConfig.something, 'extra value for the something array']}))`
-
-Configuration options:
-
-`testIdAttribute`: The attribute used by `getByTestId` and related queries.
-Defaults to `data-testid`. See [`getByTestId`](#getbytestid).
-
-
-
-
-
-```js
-// setup-tests.js
-import { configure } from '@testing-library/dom'
-
-configure({testIdAttribute: 'my-data-test-id'})`
-```
-
-
-
-```js
-// setup-tests.js
-import { configure } from '@testing-library/react'
-
-configure({testIdAttribute: 'my-data-test-id'})`
-```
-
-
-
-```
-The configuration object is not currently exposed to in Cypress Testing Library
-```
-
-
diff --git a/docs/dom-testing-library/api-configuration.mdx b/docs/dom-testing-library/api-configuration.mdx
new file mode 100644
index 000000000..72dd2e196
--- /dev/null
+++ b/docs/dom-testing-library/api-configuration.mdx
@@ -0,0 +1,177 @@
+---
+id: api-configuration
+title: Configuration Options
+---
+
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+## Introduction
+
+The library can be configured via the `configure` function, which accepts:
+
+- a plain JS object; this will be merged into the existing configuration. e.g.
+  `configure({testIdAttribute: 'not-data-testid'})`
+- a function; the function will be given the existing configuration, and should
+  return a plain JS object which will be merged as above, e.g.
+  `configure(existingConfig => ({something: [...existingConfig.something, 'extra value for the something array']}))`
+
+> **Note**
+>
+> Framework-specific wrappers like React Testing Library may add more options to
+> the ones shown below.
+
+
+
+
+```js title="setup-tests.js"
+import {configure} from '@testing-library/dom'
+import serialize from 'my-custom-dom-serializer'
+
+configure({
+  testIdAttribute: 'data-my-test-id',
+  getElementError: (message, container) => {
+    const customMessage = [message, serialize(container.firstChild)].join(
+      '\n\n',
+    )
+    return new Error(customMessage)
+  },
+})
+```
+
+   
+  
+
+```js title="setup-tests.js"
+import {configure} from '@testing-library/react'
+
+configure({testIdAttribute: 'data-my-test-id'})
+```
+
+   
+  
+
+```ts title="setup-tests.ts"
+import {configure} from '@testing-library/angular'
+
+configure({
+  dom: {
+    testIdAttribute: 'data-my-test-id',
+  },
+})
+```
+
+   
+  
+
+```js title="setup-tests.js"
+import {configure} from '@testing-library/cypress'
+
+configure({testIdAttribute: 'data-my-test-id'})
+```
+
+   
+   
+
+## Options
+
+### `computedStyleSupportsPseudoElements`
+
+Set to `true` if `window.getComputedStyle` supports pseudo-elements i.e. a
+second argument. If you're using testing-library in a browser you almost always
+want to set this to `true`. Only very old browser don't support this property
+(such as IE 8 and earlier). However, `jsdom` does not support the second
+argument currently. This includes versions of `jsdom` prior to `16.4.0` and any
+version that logs a `not implemented` warning when calling
+[`getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)
+with a second argument e.g.
+`window.getComputedStyle(document.createElement('div'), '::after')`. Defaults to
+`false`
+
+### `defaultHidden`
+
+The default value for the [`hidden` option](queries/byrole#hidden) used by
+[`getByRole`](queries/byrole.mdx). Defaults to `false`.
+
+### `defaultIgnore`
+
+The default value for the [`ignore` option](queries/bytext.mdx#ignore) used by
+[`getByText`](queries/bytext.mdx). Also determines the nodes that are being
+ignored when errors are printed.
+
+Defaults to `script, style`.
+
+### `showOriginalStackTrace`
+
+By default, [`waitFor`](api-async#waitfor) will ensure that the stack trace for
+errors thrown by Testing Library is cleaned up and shortened so it's easier for
+you to identify the part of your code that resulted in the error (async stack
+traces are hard to debug). If you want to disable this, then
+set`showOriginalStackTrace` to `false`. You can also disable this for a specific
+call in the options you pass to `waitFor`.
+
+### `throwSuggestions` (experimental)
+
+When enabled, if [better queries](queries/about.mdx#priority) are available, the
+test will fail and provide a suggested query to use instead. Defaults to
+`false`.
+
+To disable a suggestion for a single query just add `{suggest:false}` as an
+option.
+
+```js
+screen.getByTestId('foo', {suggest: false}) // will not throw a suggestion
+```
+
+:::note
+
+When this option is enabled, it may provide suggestions that lack an intuitive
+implementation. Typically this happens for
+[roles which cannot be named](https://w3c.github.io/aria/#namefromprohibited),
+most notably paragraphs. For instance, if you attempt to use
+[`getByText`](queries/bytext.mdx), you may encounter the following error:
+
+```
+TestingLibraryElementError: A better query is available, try this:
+    getByRole('paragraph')
+```
+
+However, there is no direct way to query paragraphs using the config object
+parameter, such as in `getByRole('paragraph', { name: 'Hello World' })`.
+
+To address this issue, you can leverage a custom function to validate the
+element's structure, as shown in the example below. More information can be
+found in the
+[GitHub issue](https://github.com/testing-library/dom-testing-library/issues/1306)
+
+```js
+getByRole('paragraph', {
+  name: (_, element) => element.textContent === 'Hello world',
+})
+```
+
+:::
+
+### `testIdAttribute`
+
+The attribute used by [`getByTestId`](queries/bytestid.mdx) and related queries.
+Defaults to `data-testid`.
+
+### `getElementError`
+
+A function that returns the error used when
+[get or find queries](queries/about.mdx#types-of-queries) fail. Takes the error
+message and container object as arguments.
+
+### `asyncUtilTimeout`
+
+The global timeout value in milliseconds used by [`waitFor`](api-async#waitfor)
+utilities. Defaults to 1000ms.
diff --git a/docs/dom-testing-library/api-custom-queries.mdx b/docs/dom-testing-library/api-custom-queries.mdx
new file mode 100644
index 000000000..8147ead50
--- /dev/null
+++ b/docs/dom-testing-library/api-custom-queries.mdx
@@ -0,0 +1,119 @@
+---
+id: api-custom-queries
+title: Custom Queries
+---
+
+`DOM Testing Library` exposes many of the helper functions that are used to
+implement the default queries. You can use the helpers to build custom queries.
+For example, the code below shows a way to override the default `testId` queries
+to use a different data-attribute. (Note: test files would import
+`test-utils.js` instead of using `DOM Testing Library` directly).
+
+> **Note**
+>
+> Custom queries can be added to `React Testing Library`'s `render` method by
+> adding `queries` to the options config object. See the render
+> [options](react-testing-library/api.mdx#render-options).
+
+> Custom queries are different than
+> [custom render](react-testing-library/setup.mdx#custom-render) methods.
+
+```js title="test-utils.js"
+const domTestingLib = require('@testing-library/dom')
+const {queryHelpers} = domTestingLib
+
+export const queryByTestId = queryHelpers.queryByAttribute.bind(
+  null,
+  'data-test-id',
+)
+export const queryAllByTestId = queryHelpers.queryAllByAttribute.bind(
+  null,
+  'data-test-id',
+)
+
+export function getAllByTestId(container, id, ...rest) {
+  const els = queryAllByTestId(container, id, ...rest)
+  if (!els.length) {
+    throw queryHelpers.getElementError(
+      `Unable to find an element by: [data-test-id="${id}"]`,
+      container,
+    )
+  }
+  return els
+}
+
+export function getByTestId(container, id, ...rest) {
+  // result >= 1
+  const result = getAllByTestId(container, id, ...rest)
+  if (result.length > 1) {
+    throw queryHelpers.getElementError(
+      `Found multiple elements with the [data-test-id="${id}"]`,
+      container,
+    )
+  }
+  return result[0]
+}
+
+// re-export with overrides
+module.exports = {
+  ...domTestingLib,
+  getByTestId,
+  getAllByTestId,
+  queryByTestId,
+  queryAllByTestId,
+}
+```
+
+## `buildQueries`
+
+The `buildQueries` helper allows you to create custom queries with all the
+[standard queries](queries/about.mdx) in testing-library.
+
+See the [Add custom queries](react-testing-library/setup.mdx#add-custom-queries)
+section of the custom render guide for example usage.
+
+### Using other assertion libraries
+
+If you're not using jest, you may be able to find a similar set of custom
+assertions for your library of choice. Here's a list of alternatives to jest-dom
+for other popular assertion libraries:
+
+- [chai-dom](https://github.com/nathanboktae/chai-dom)
+
+If you're aware of some other alternatives, please
+[make a pull request](https://github.com/testing-library/testing-library-docs/pulls)
+and add it here!
+
+## `getNodeText`
+
+```typescript
+getNodeText(node: HTMLElement)
+```
+
+Returns the complete text content of an HTML element, removing any extra
+whitespace. The intention is to treat text in nodes exactly as how it is
+perceived by users in a browser, where any extra whitespace within words in the
+html code is not meaningful when the text is rendered.
+
+```javascript
+// 
+//   Hello
+//     World  !
+// 
+const text = getNodeText(container.querySelector('div')) // "Hello World !"
+```
+
+This function is also used internally when querying nodes by their text content.
+This enables functions like `getByText` and `queryByText` to work as expected,
+finding elements in the DOM similarly to how users would do.
+
+The function has a special behavior for some input elements:
+
+```javascript
+// Hello world
+getByText(container, 'Goodbye world') // will fail by throwing error
+```
+
+The above test case will fail, however it prints the state of your DOM under
+test, so you will get to see:
+
+```
+Unable to find an element with the text: Goodbye world. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
+Here is the state of your container:
+
+```
+
+**Note**: Since the DOM size can get really large, you can set the limit of DOM
+content to be printed via environment variable `DEBUG_PRINT_LIMIT`. The default
+value is `7000`. You will see `...` in the console, when the DOM content is
+stripped off, because of the length you have set or due to default size limit.
+Here's how you might increase this limit when running tests:
+
+```bash npm2yarn
+DEBUG_PRINT_LIMIT=10000 npm test
+```
+
+This works on macOS/Linux, you'll need to do something else for Windows. If
+you'd like a solution that works for both, see
+[`cross-env`](https://www.npmjs.com/package/cross-env).
+
+**Note**: The output of the DOM is colorized by default if your tests are
+running in a node environment. However, you may sometimes want to turn off
+colors, such as in cases where the output is written to a log file for debugging
+purposes. You can use the environment variable `COLORS` to explicitly force the
+colorization off or on. For example:
+
+```bash npm2yarn
+COLORS=false npm test
+```
+
+This works on macOS/Linux, you'll need to do something else for Windows. If
+you'd like a solution that works for both, see
+[`cross-env`](https://www.npmjs.com/package/cross-env).
+
+## `prettyDOM`
+
+Built on top of
+[`pretty-format`](https://github.com/jestjs/jest/tree/main/packages/pretty-format),
+this helper function can be used to print out readable representation of the DOM
+tree of a node. This can be helpful for instance when debugging tests.
+
+It is defined as:
+
+```typescript
+interface Options extends prettyFormat.OptionsReceived {
+  filterNode?: (node: Node) => boolean
+}
+
+function prettyDOM(
+  node: HTMLElement,
+  maxLength?: number,
+  options?: Options,
+): string
+```
+
+It receives the root node to print out, an optional extra parameter to limit the
+size of the resulting string, for cases when it becomes too large. It has a last
+parameter which allows you to configure your formatting. In addition to the
+options listed you can also pass the
+[options](https://github.com/jestjs/jest/tree/main/packages/pretty-format#usage-with-options)
+of `pretty-format`.
+
+By default, ``, `` and comment nodes are ignored. You can
+configure this behavior by passing a custom `filterNode` function that should
+return `true` for every node that you wish to include in the output.
+
+This function is usually used alongside `console.log` to temporarily print out
+DOM trees during tests for debugging purposes:
+
+```javascript
+import {prettyDOM} from '@testing-library/dom'
+
+const div = document.createElement('div')
+div.innerHTML = '
Hello World '
+console.log(prettyDOM(div))
+// 
+//   
Hello World 
+// 
+```
+
+This function is what also powers
+[the automatic debugging output described above](#automatic-logging).
+
+## `screen.debug()`
+
+For convenience `screen` also exposes a `debug` method. This method is
+essentially a shortcut for `console.log(prettyDOM())`. It supports debugging the
+document, a single element, or an array of elements.
+
+```javascript
+import {screen} from '@testing-library/dom'
+
+document.body.innerHTML = `
+  test 
+  multi-test 
+  multi-test
+`
+
+// debug document
+screen.debug()
+// debug single element
+screen.debug(screen.getByText('test'))
+// debug multiple elements
+screen.debug(screen.getAllByText('multi-test'))
+```
+
+## `screen.logTestingPlaygroundURL()`
+
+For debugging using [testing-playground](https://testing-playground.com), screen
+exposes this convenient method which logs and returns a URL that can be opened
+in a browser.
+
+```javascript
+import {screen} from '@testing-library/dom'
+
+document.body.innerHTML = `
+  test 
+  multi-test 
+  multi-test
+`
+
+// log entire document to testing-playground
+screen.logTestingPlaygroundURL()
+// log a single element
+screen.logTestingPlaygroundURL(screen.getByText('test'))
+```
+
+## `logRoles`
+
+This helper function can be used to print out a list of all the implicit ARIA
+roles within a tree of DOM nodes, each role containing a list of all of the
+nodes which match that role. This can be helpful for finding ways to query the
+DOM under test with [getByRole](queries/byrole.mdx).
+
+```javascript
+import {logRoles} from '@testing-library/dom'
+
+const nav = document.createElement('nav')
+nav.innerHTML = `
+`
+
+logRoles(nav)
+```
+
+Result:
+
+```
+navigation:
+Submit 
-fireEvent(
-  getByText(container, 'Submit'),
-  new MouseEvent('click', {
-    bubbles: true,
-    cancelable: true,
-  })
-)
-```
-
-## `fireEvent[eventName]`
-
-```typescript
-fireEvent[eventName](node: HTMLElement, eventProperties: Object)
-```
-
-Convenience methods for firing DOM events. Check out
-[src/events.js](https://github.com/testing-library/dom-testing-library/blob/master/src/events.js)
-for a full list as well as default `eventProperties`.
-
-```javascript
-// Submit 
-const rightClick = { button: 2 }
-fireEvent.click(getByText('Submit'), rightClick)
-// default `button` property for click events is set to `0` which is a left click.
-```
-
-**target**: When an event is dispatched on an element, the event has the
-subjected element on a property called `target`. As a convenience, if you
-provide a `target` property in the `eventProperties` (second argument), then
-those properties will be assigned to the node which is receiving the event.
-
-This is particularly useful for a change event:
-
-```javascript
-fireEvent.change(getByLabelText(/username/i), { target: { value: 'a' } })
-
-// note: attempting to manually set the files property of an HTMLInputElement
-// results in an error as the files property is read-only.
-// this feature works around that by using Object.defineProperty.
-fireEvent.change(getByLabelText(/picture/i), {
-  target: {
-    files: [new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' })],
-  },
-})
-```
-
-**Keyboard events**: There are three event types related to keyboard input -
-`keyPress`, `keyDown`, and `keyUp`. When firing these you need to reference an
-element in the DOM and the key you want to fire.
-
-```javascript
-fireEvent.keyDown(domNode, { key: 'Enter', code: 13 })
-
-// note: you should set the charCode or it will be fallback to 0
-// will Fire an KeyboardEvent with charCode = 0
-fireEvent.keyDown(domNode, { key: 'Enter', code: 13 })
-
-// will Fire an KeyboardEvent with charCode = 65
-fireEvent.keyDown(domNode, { key: 'A', code: 65, charCode: 65 })
-```
-
-You can find out which key code to use at
-[https://keycode.info/](https://keycode.info/).
-
-## `createEvent[eventName]`
-
-```typescript
-createEvent[eventName](node: HTMLElement, eventProperties: Object)
-```
-
-Convenience methods for creating DOM events that can then be fired by
-`fireEvent`, allowing you to have a reference to the event created: this might
-be useful if you need to access event properties that cannot be initiated
-programmatically (such as `timeStamp`).
-
-```javascript
-const myEvent = createEvent.click(node, { button: 2 })
-fireEvent(node, myEvent)
-// myEvent.timeStamp can be accessed just like any other properties from myEvent
-```
diff --git a/docs/dom-testing-library/api-events.mdx b/docs/dom-testing-library/api-events.mdx
new file mode 100644
index 000000000..614ff1689
--- /dev/null
+++ b/docs/dom-testing-library/api-events.mdx
@@ -0,0 +1,191 @@
+---
+id: api-events
+title: Firing Events
+---
+
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+> **Note**
+>
+> Most projects have a few use cases for `fireEvent`, but the majority of the
+> time you should probably use
+> [`@testing-library/user-event`](user-event/intro.mdx).
+
+## `fireEvent`
+
+```typescript
+fireEvent(node: HTMLElement, event: Event)
+```
+
+Fire DOM events.
+
+```javascript
+// Submit 
+fireEvent(
+  getByText(container, 'Submit'),
+  new MouseEvent('click', {
+    bubbles: true,
+    cancelable: true,
+  }),
+)
+```
+
+## `fireEvent[eventName]`
+
+```typescript
+fireEvent[eventName](node: HTMLElement, eventProperties: Object)
+```
+
+Convenience methods for firing DOM events. Check out
+[src/event-map.js](https://github.com/testing-library/dom-testing-library/blob/master/src/event-map.js)
+for a full list as well as default `eventProperties`.
+
+**target**: When an event is dispatched on an element, the event has the
+subjected element on a property called `target`. As a convenience, if you
+provide a `target` property in the `eventProperties` (second argument), then
+those properties will be assigned to the node which is receiving the event.
+
+This is particularly useful for a change event:
+
+```javascript
+fireEvent.change(getByLabelText(/username/i), {target: {value: 'a'}})
+
+// note: attempting to manually set the files property of an HTMLInputElement
+// results in an error as the files property is read-only.
+// this feature works around that by using Object.defineProperty.
+fireEvent.change(getByLabelText(/picture/i), {
+  target: {
+    files: [new File(['(⌐□_□)'], 'chucknorris.png', {type: 'image/png'})],
+  },
+})
+
+// Note: The 'value' attribute must use ISO 8601 format when firing a
+// change event on an input of type "date". Otherwise the element will not
+// reflect the changed value.
+
+// Invalid:
+fireEvent.change(input, {target: {value: '24/05/2020'}})
+
+// Valid:
+fireEvent.change(input, {target: {value: '2020-05-24'}})
+```
+
+**dataTransfer**: Drag events have a `dataTransfer` property that contains data
+transferred during the operation. As a convenience, if you provide a
+`dataTransfer` property in the `eventProperties` (second argument), then those
+properties will be added to the event.
+
+This should predominantly be used for testing drag and drop interactions.
+
+```javascript
+fireEvent.drop(getByLabelText(/drop files here/i), {
+  dataTransfer: {
+    files: [new File(['(⌐□_□)'], 'chucknorris.png', {type: 'image/png'})],
+  },
+})
+```
+
+**Keyboard events**: There are three event types related to keyboard input -
+`keyPress`, `keyDown`, and `keyUp`. When firing these you need to reference an
+element in the DOM and the key you want to fire.
+
+```javascript
+fireEvent.keyDown(domNode, {key: 'Enter', code: 'Enter', charCode: 13})
+
+fireEvent.keyDown(domNode, {key: 'A', code: 'KeyA'})
+```
+
+You can find out which key code to use at
+[https://www.toptal.com/developers/keycode](https://www.toptal.com/developers/keycode).
+
+## `createEvent[eventName]`
+
+```typescript
+createEvent[eventName](node: HTMLElement, eventProperties: Object)
+```
+
+Convenience methods for creating DOM events that can then be fired by
+`fireEvent`, allowing you to have a reference to the event created: this might
+be useful if you need to access event properties that cannot be initiated
+programmatically (such as `timeStamp`).
+
+```javascript
+const myEvent = createEvent.click(node, {button: 2})
+fireEvent(node, myEvent)
+// myEvent.timeStamp can be accessed just like any other properties from myEvent
+// note: The access to the events created by `createEvent` is based on the native event API,
+// Therefore, native properties of HTMLEvent object (e.g. `timeStamp`, `cancelable`, `type`) should be set using Object.defineProperty
+// For more info see: https://developer.mozilla.org/en-US/docs/Web/API/Event
+```
+
+You can also create generic events:
+
+```javascript
+// simulate the 'input' event on a file input
+fireEvent(
+  input,
+  createEvent('input', input, {
+    target: {files: inputFiles},
+    ...init,
+  }),
+)
+```
+
+## Using Jest Function Mocks
+
+[Jest's Mock functions](https://jestjs.io/docs/en/mock-functions) can be used to
+test that a component will call its bound callback in response to a particular
+event.
+
+  
+  
+
+```jsx
+import {render, screen, fireEvent} from '@testing-library/react'
+
+const Button = ({onClick, children}) => (
+  {children} 
+)
+
+test('calls onClick prop when clicked', () => {
+  const handleClick = jest.fn()
+  render(Click Me )
+  fireEvent.click(screen.getByText(/click me/i))
+  expect(handleClick).toHaveBeenCalledTimes(1)
+})
+```
+
+   
+  
+
+```ts
+import {render, screen, fireEvent} from '@testing-library/angular'
+
+@Component({
+  template: `Click Me `,
+})
+class ButtonComponent {
+  @Output() handleClick = new EventEmitter()
+}
+
+test('calls onClick prop when clicked', async () => {
+  const handleClick = jest.fn()
+  await render(ButtonComponent, {
+    componentOutputs: {
+      handleClick: {emit: handleClick} as any,
+    },
+  })
+  await fireEvent.click(screen.getByText(/click me/i))
+  expect(handleClick).toHaveBeenCalledTimes(1)
+})
+```
+
+    
+   
diff --git a/docs/dom-testing-library/api-helpers.md b/docs/dom-testing-library/api-helpers.md
deleted file mode 100644
index 6c8934c20..000000000
--- a/docs/dom-testing-library/api-helpers.md
+++ /dev/null
@@ -1,302 +0,0 @@
----
-id: api-helpers
-title: Helpers
----
-
-## Custom Queries
-
-`DOM Testing Library` exposes many of the helper functions that are used to
-implement the default queries. You can use the helpers to build custom queries.
-For example, the code below shows a way to override the default `testId` queries
-to use a different data-attribute. (Note: test files would import
-`test-utils.js` instead of using `DOM Testing Library` directly).
-
-```js
-// test-utils.js
-const domTestingLib = require('@testing-library/dom')
-const { queryHelpers } = domTestingLib
-
-export const queryByTestId = queryHelpers.queryByAttribute.bind(
-  null,
-  'data-test-id'
-)
-export const queryAllByTestId = queryHelpers.queryAllByAttribute.bind(
-  null,
-  'data-test-id'
-)
-
-export function getAllByTestId(container, id, ...rest) {
-  const els = queryAllByTestId(container, id, ...rest)
-  if (!els.length) {
-    throw queryHelpers.getElementError(
-      `Unable to find an element by: [data-test-id="${id}"]`,
-      container
-    )
-  }
-  return els
-}
-
-export function getByTestId(...args) {
-  const result = getAllByTestId(...args)
-  if (result.length > 0) {
-    return result[0]
-  }
-  return null
-}
-
-// re-export with overrides
-module.exports = {
-  ...domTestingLib,
-  getByTestId,
-  getAllByTestId,
-  queryByTestId,
-  queryAllByTestId,
-}
-```
-
-> **Note**
->
-> Custom queries can be added to `React Testing Library`'s `render` method by
-> adding `queries` to the options config object. See the render
-> [options](/docs/react-testing-library/api#render-options).
-
-## `buildQueries`
-
-The `buildQueries` helper allows you to create custom queries with all standard
-[variants](api-queries.md) of queries in testing-library.
-
-See the
-[Add custom queries](/docs/react-testing-library/setup#add-custom-queries)
-section of the custom render guide for example usage.
-
-### Using other assertion libraries
-
-If you're not using jest, you may be able to find a similar set of custom
-assertions for your library of choice. Here's a list of alternatives to jest-dom
-for other popular assertion libraries:
-
-- [chai-dom](https://github.com/nathanboktae/chai-dom)
-
-If you're aware of some other alternatives, please [make a pull request](https://github.com/testing-library/testing-library-docs/pulls)
-and add it here!
-
-## `getNodeText`
-
-```typescript
-getNodeText(node: HTMLElement)
-```
-
-Returns the complete text content of a html element, removing any extra
-whitespace. The intention is to treat text in nodes exactly as how it is
-perceived by users in a browser, where any extra whitespace within words in the
-html code is not meaningful when the text is rendered.
-
-```javascript
-// 
-//   Hello
-//     World  !
-// 
-const text = getNodeText(container.querySelector('div')) // "Hello World !"
-```
-
-This function is also used internally when querying nodes by their text content.
-This enables functions like `getByText` and `queryByText` to work as expected,
-finding elements in the DOM similarly to how users would do.
-
-The function has a special behavior for some input elements:
-
-```javascript
-// Hello world
-getByText(container, 'Goodbye world') // will fail by throwing error
-```
-
-The above test case will fail, however it prints the state of your DOM under
-test, so you will get to see:
-
-```
-Unable to find an element with the text: Goodbye world. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
-Here is the state of your container:
-
-```
-
-Note: Since the DOM size can get really large, you can set the limit of DOM
-content to be printed via environment variable `DEBUG_PRINT_LIMIT`. The default
-value is `7000`. You will see `...` in the console, when the DOM content is
-stripped off, because of the length you have set or due to default size limit.
-Here's how you might increase this limit when running tests:
-
-```
-DEBUG_PRINT_LIMIT=10000 npm test
-```
-
-This works on macOS/linux, you'll need to do something else for windows. If
-you'd like a solution that works for both, see
-[`cross-env`](https://www.npmjs.com/package/cross-env)
-
-### `prettyDOM`
-
-Built on top of
-[`pretty-format`](https://github.com/facebook/jest/tree/master/packages/pretty-format),
-this helper function can be used to print out readable representation of the DOM
-tree of a node. This can be helpful for instance when debugging tests.
-
-It is defined as:
-
-```typescript
-function prettyDOM(
-  node: HTMLElement,
-  maxLength?: number,
-  options?: Options
-): string
-```
-
-It receives the root node to print out, an optional extra parameter to limit the
-size of the resulting string, for cases when it becomes too large. It has a last
-parameter which allows you to configure your formatting as defined in the
-[options](https://github.com/facebook/jest/tree/master/packages/pretty-format#usage-with-options)
-of `pretty-format`.
-
-This function is usually used alongside `console.log` to temporarily print out
-DOM trees during tests for debugging purposes:
-
-```javascript
-const div = document.createElement('div')
-div.innerHTML = '
Hello World '
-console.log(prettyDOM(div))
-// 
-//   
Hello World 
-// 
-```
-
-This function is what also powers
-[the automatic debugging output described above](#debugging).
-
-### `logRoles`
-
-This helper function can be used to print out a list of all the implicit ARIA
-roles within a tree of DOM nodes, each role containing a list of all of the
-nodes which match that role. This can be helpful for finding ways to query the
-DOM under test with [getByRole](api-queries.md#byrole)
-
-```javascript
-import { logRoles } from '@testing-library/dom'
-
-const nav = document.createElement('nav')
-nav.innerHTML = `
-`
-
-console.log(logRoles(nav))
-
-// navigation:
-//
-// Username 
-Username 
-Username  
-
-// aria-label attributes
-// Take care because this is not a label that users can see on the page,
-// so the purpose of your input must be obvious to visual users.
- Username   
-```
-
-```js
-const container = document.body
-const inputNode = getByLabelText(container, 'Username', {
-  selector: 'input',
-})
-```
-
-### `ByPlaceholderText`
-
-> getByPlaceholderText, queryByPlaceholderText, getAllByPlaceholderText,
-> queryAllByPlaceholderText, findByPlaceholderText, findAllByPlaceholderText
-
-```typescript
-getByPlaceholderText(
-  container: HTMLElement,
-  text: TextMatch,
-  options?: {
-    exact?: boolean = true,
-    normalizer?: NormalizerFn,
-  }): HTMLElement
-```
-
-This will search for all elements with a placeholder attribute and find one that
-matches the given [`TextMatch`](#textmatch).
-
-```html
-About ℹ️ 
-```
-
-
-
-
-
-```js
-import { getByText } from '@testing-library/dom'
-
-const container = document.body
-const aboutAnchorNode = getByText(container, /about/i)
-```
-
-
-
-```js
-import { render } from '@testing-library/react'
-
-const { getByText } = render(`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/applet)
-as it's deprecated).
-
-```html
-
-  Close 
-   
-```
-
-
-
-
-
-```js
-import { getByTitle } from '@testing-library/dom'
-
-const container = document.body
-const deleteElement = getByTitle(container, 'Delete')
-const closeElement = getByTitle(container, 'Close')
-```
-
-
-
-```js
-import { render } from '@testing-library/react'
-
-const { getByTitle } = render(` whose selected ``
-matches the given [`TextMatch`](#textmatch).
-
-```html
-
-  State 
-  Alabama 
-  Alaska 
-  Arizona 
- 
-```
-
-
-
-
-
-```js
-import { getByDisplayValue } from '@testing-library/dom'
-
-const container = document.body
-const selectElement = getByDisplayValue(container, 'Alaska')
-```
-
-
-
-```js
-import { render } from '@testing-library/react'
-
-const { getByDisplayValue } = render(...
-```
-
-
-
-
-
-```js
-import { getByRole } from '@testing-library/dom'
-
-const container = document.body
-const dialogContainer = getByRole(container, 'dialog')
-```
-
-
-
-```js
-import { render } from '@testing-library/react'
-
-const { getByRole } = render(Hello World
-```
-
-**_Will_ find the div:**
-
-```javascript
-// Matching a string:
-getByText(container, 'Hello World') // full string match
-getByText(container, 'llo Worl', { exact: false }) // substring match
-getByText(container, 'hello world', { exact: false }) // ignore case
-
-// Matching a regex:
-getByText(container, /World/) // substring match
-getByText(container, /world/i) // substring match, ignore case
-getByText(container, /^hello world$/i) // full string match, ignore case
-getByText(container, /Hello W?oRlD/i) // advanced regex
-
-// Matching with a custom function:
-getByText(container, (content, element) => content.startsWith('Hello'))
-```
-
-**_Will not_ find the div:**
-
-```javascript
-// full string does not match
-getByText(container, 'Goodbye World')
-
-// case-sensitive regex with different case
-getByText(container, /hello world/)
-
-// function looking for a span when it's actually a div:
-getByText(container, (content, element) => {
-  return element.tagName.toLowerCase() === 'span' && content.startsWith('Hello')
-})
-```
diff --git a/docs/dom-testing-library/api-within.mdx b/docs/dom-testing-library/api-within.mdx
new file mode 100644
index 000000000..eda32b9a4
--- /dev/null
+++ b/docs/dom-testing-library/api-within.mdx
@@ -0,0 +1,67 @@
+---
+id: api-within
+title: Querying Within Elements
+---
+
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+`within` (an alias to `getQueriesForElement`) takes a DOM element and binds it
+to the raw query functions, allowing them to be used without specifying a
+container. It is the recommended approach for libraries built on this API and is
+used under the hood in React Testing Library and Vue Testing Library.
+
+Example: To get the text 'hello' only within a section called 'messages', you
+could do:
+
+  
+  
+
+```js
+import {within} from '@testing-library/dom'
+
+const messages = document.getElementById('messages')
+const helloMessage = within(messages).getByText('hello')
+```
+
+   
+  
+
+```jsx
+import {render, within} from '@testing-library/react'
+
+const {getByText} = render( 
+  
+
+```ts
+import {render, within} from '@testing-library/angular'
+
+const {getByText} = await render(MyComponent)
+const messages = getByText('messages')
+const helloMessage = within(messages).getByText('hello')
+```
+
+   
+  
+
+```js
+cy.findByText('messages').within(() => {
+  cy.findByText('hello')
+})
+```
+
+   
+   
diff --git a/docs/dom-testing-library/api.mdx b/docs/dom-testing-library/api.mdx
new file mode 100644
index 000000000..bbaeaa6bc
--- /dev/null
+++ b/docs/dom-testing-library/api.mdx
@@ -0,0 +1,16 @@
+---
+id: api
+title: API
+---
+
+DOM Testing Library is the "core API" of the Testing Library family, so please
+refer to the Core API section for details. The other libraries (with a few
+exceptions) re-export the full DOM Testing Library API, with additional methods
+built on top.
+
+
+
+- [Queries](queries/about.mdx)
+- [Events](api-events.mdx)
+- [Advanced](api-accessibility.mdx)
+- [Configuration](api-configuration.mdx)
diff --git a/docs/dom-testing-library/cheatsheet.md b/docs/dom-testing-library/cheatsheet.mdx
similarity index 74%
rename from docs/dom-testing-library/cheatsheet.md
rename to docs/dom-testing-library/cheatsheet.mdx
index 72b3391ea..d5625d104 100644
--- a/docs/dom-testing-library/cheatsheet.md
+++ b/docs/dom-testing-library/cheatsheet.mdx
@@ -7,7 +7,7 @@ A short guide to all the exported functions in `DOM Testing Library`
 
 ## Queries
 
-See [Which query should I use?](guide-which-query.md)
+See [Which query should I use?](queries/about.mdx#priority)
 
 |                | No Match | 1 Match | 1+ Match | Await? |
 | -------------- | -------- | ------- | -------- | ------ |
@@ -77,32 +77,39 @@ See [Which query should I use?](guide-which-query.md)
 
 ## Async
 
-See [Async API](dom-testing-library/api-async.md)
+See [Async API](dom-testing-library/api-async.mdx). Remember to `await` or
+`.then()` the result of async functions in your tests!
 
-- **wait** (Promise) retry the function within until it stops throwing or times
-  out
-- **waitForElement** (Promise) retry the function until it returns an element or
-  an array of elements
-  - `findBy` and `findAllBy` queries are async and retry until either a timeout
-    or if the query returns successfully; they wrap `waitForElement`
-- **waitForDomChange** (Promise) retry the function each time the DOM is changed
+- **waitFor** (Promise) retry the function within until it stops throwing or
+  times out
 - **waitForElementToBeRemoved** (Promise) retry the function until it no longer
   returns a DOM node
 
-> Remember to `await` or `.then()` the result of async functions in your tests!
+> **Deprecated since v7.0.0:**
+>
+> - **wait** (Promise) retry the function within until it stops throwing or
+>   times
+> - **waitForElement** (Promise) retry the function until it returns an element
+>   or an array of elements. The `findBy` and `findAllBy` queries are async and
+>   retry until the query returns successfully, or when the query times out;
+>   they wrap `waitForElement`
+> - **waitForDomChange** (Promise) retry the function each time the DOM is
+>   changed
 
 ## Events
 
-See [Considerations for fireEvent](guide-events.md), [Events API](api-events.md)
+See [Considerations for fireEvent](guide-events.mdx),
+[Events API](api-events.mdx)
 
 - **fireEvent** trigger DOM event: `fireEvent(node, event)`
 - **fireEvent.\*** helpers for default event types
   - **click** `fireEvent.click(node)`
-  - [See all supported events](https://github.com/testing-library/dom-testing-library/blob/master/src/events.js)
+  - [See all supported events](https://github.com/testing-library/dom-testing-library/blob/master/src/event-map.js)
 
 ## Other
 
-See [Helpers API](api-helpers.md), [Config API](api-configuration.md)
+See [Querying Within Elements](api-within.mdx),
+[Config API](api-configuration.mdx)
 
 - **within** take a node and return an object with all the queries bound to the
   node (used to return the queries from `React Testing Library`'s render
@@ -123,8 +130,8 @@ Given the following HTML:
 ```javascript
 // Matching a string:
 getByText(container, 'Hello World') // full string match
-getByText(container, 'llo Worl', { exact: false }) // substring match
-getByText(container, 'hello world', { exact: false }) // ignore case
+getByText(container, 'llo Worl', {exact: false}) // substring match
+getByText(container, 'hello world', {exact: false}) // ignore case
 
 // Matching a regex:
 getByText(container, /World/) // substring match
@@ -144,7 +151,7 @@ test('loads items eventually', async () => {
   fireEvent.click(getByText(node, 'Load'))
 
   // Wait for page to update with query text
-  const items = await findByText(node, /Item #[0-9]: /)
+  const items = await findAllByText(node, /Item #[0-9]: /)
   expect(items).toHaveLength(10)
 })
 ```
diff --git a/docs/dom-testing-library/example-intro.md b/docs/dom-testing-library/example-intro.mdx
similarity index 89%
rename from docs/dom-testing-library/example-intro.md
rename to docs/dom-testing-library/example-intro.mdx
index 1ec820d90..d169dc915 100644
--- a/docs/dom-testing-library/example-intro.md
+++ b/docs/dom-testing-library/example-intro.mdx
@@ -4,8 +4,7 @@ title: Example
 sidebar_label: Example
 ---
 
-```javascript
-// src/__tests__/example.js
+```js title="src/__tests__/example.js"
 // query utilities:
 import {
   getByLabelText,
@@ -14,10 +13,10 @@ import {
   queryByTestId,
   // Tip: all queries are also exposed on an object
   // called "queries" which you could import here as well
-  wait,
+  waitFor,
 } from '@testing-library/dom'
 // adds special assertions like toHaveTextContent
-import '@testing-library/jest-dom/extend-expect'
+import '@testing-library/jest-dom'
 
 function getExampleDOM() {
   // This is just a raw example of setting up some DOM
@@ -46,25 +45,25 @@ function getExampleDOM() {
 }
 
 test('examples of some things', async () => {
-  const famousWomanInHistory = 'Ada Lovelace'
+  const famousProgrammerInHistory = 'Ada Lovelace'
   const container = getExampleDOM()
 
   // Get form elements by their label text.
   // An error will be thrown if one cannot be found (accessibility FTW!)
   const input = getByLabelText(container, 'Username')
-  input.value = famousWomanInHistory
+  input.value = famousProgrammerInHistory
 
   // Get elements by their text, just like a real user does.
   getByText(container, 'Print Username').click()
 
-  await wait(() =>
-    expect(queryByTestId(container, 'printed-username')).toBeTruthy()
+  await waitFor(() =>
+    expect(queryByTestId(container, 'printed-username')).toBeTruthy(),
   )
 
   // getByTestId and queryByTestId are an escape hatch to get elements
   // by a test id (could also attempt to get this element by its text)
   expect(getByTestId(container, 'printed-username')).toHaveTextContent(
-    famousWomanInHistory
+    famousProgrammerInHistory,
   )
   // jest snapshots work great with regular DOM nodes!
   expect(container).toMatchSnapshot()
diff --git a/docs/dom-testing-library/faq.md b/docs/dom-testing-library/faq.mdx
similarity index 65%
rename from docs/dom-testing-library/faq.md
rename to docs/dom-testing-library/faq.mdx
index ae3c094bb..39e8de991 100644
--- a/docs/dom-testing-library/faq.md
+++ b/docs/dom-testing-library/faq.mdx
@@ -7,7 +7,7 @@ title: FAQ
 
 Which get method should I use? 
 
-See [Which Query Should I Use](guide-which-query.md)
+See [Which Query Should I Use](queries/about.mdx#priority)
 
 
 
@@ -27,7 +27,9 @@ As you write your tests, keep in mind:
 
 
 
-What if my app is localized and I don't have access to the text in test? 
+
+  What if my app is localized and I don't have access to the text in test?
+ 
 
 This is fairly common. Our first bit of advice is to try to get the default text
 used in your tests. That will make everything much easier (more than just using
@@ -38,7 +40,10 @@ with `data-testid`s (which is not bad anyway).
 
 
 
-I really don't like data-testids, but none of the other queries make sense. Do I have to use a data-testid? 
+
+  I really don't like data-testids, but none of the other queries make sense. Do
+  I have to use a data-testid?
+ 
 
 Definitely not. That said, a common reason people don't like the `data-testid`
 attribute is they're concerned about shipping that to production. I'd suggest
@@ -67,7 +72,10 @@ const rootElement = container.firstChild
 
 
 
-What if I’m iterating over a list of items that I want to put the data-testid="item" attribute on. How do I distinguish them from each other? 
+
+  What if I’m iterating over a list of items that I want to put the
+  data-testid="item" attribute on. How do I distinguish them from each other?
+ 
 
 You can make your selector just choose the one you want by including :nth-child
 in the selector.
@@ -76,27 +84,38 @@ in the selector.
 const thirdLiInUl = container.querySelector('ul > li:nth-child(3)')
 ```
 
-Or you could include the index or an ID in your attribute:
-
-```javascript
-;`{item.text} `
-```
-
-And then you could use the `getByTestId` utility:
+Or you could use `getAllByRole` to query the `listitem` role and access the
+index in question:
 
 ```javascript
 const items = [
   /* your items */
 ]
-const container = render(/* however you render this stuff */)
-const thirdItem = getByTestId(container, `item-${items[2].id}`)
+const {container} = render(/* however you render this stuff */)
+const thirdItem = getAllByRole(container, 'listitem')[2]
 ```
 
  
 
-
+
+
+  Help! I can't access component methods or the component instance!
+ 
+
+This is **intentional**.
+
+We want you to focus on testing the output and functionality of the component as
+it is observed by the user and to **avoid worrying about the implementation
+details** of the component.
+
+We believe this leads to less brittle and more meaningful test code.
+
+Please refer to the [Guiding Principles](guiding-principles.mdx) of this testing
+library for more info.
+
+ 
+
+
 
 
 
diff --git a/docs/dom-testing-library/install.md b/docs/dom-testing-library/install.md
deleted file mode 100644
index 7a5308c2d..000000000
--- a/docs/dom-testing-library/install.md
+++ /dev/null
@@ -1,58 +0,0 @@
----
-id: install
-title: Install
-sidebar_label: Install
----
-
-This module is distributed via [npm][npm] which is bundled with [node][node] and
-should be installed as one of your project's `devDependencies`:
-
-```
-npm install --save-dev @testing-library/dom
-```
-
-## Wrappers
-
-If you are using a framework or library such as React, you will likely want to
-install the wrapper:
-
-- [React Testing Library](react-testing-library/intro.md)
-- [Cypress Testing Library](cypress-testing-library/intro.md)
-
-## Ecosystem
-
-`DOM Testing Library` works well with these companion libraries:
-
-- [user-event](ecosystem-user-event.md) browser event simulation
-- [jest-dom](ecosystem-jest-dom.md) custom Jest matchers
-
-## Main Exports
-
-You can
-[review the `DOM Testing Library` package.json here](https://unpkg.com/@testing-library/dom/package.json).
-
-In particular, the `main`, `module`, and `umd:main` fields are useful. Each of
-these points to a file that's useful in certain situations. Typically, your
-testing framework will resolve to the correct one for your situation, but if it
-does not, then you can either configure your testing framework to resolve to the
-right file when you require/import `@testing-library/dom` or you can import the
-file you need more explicitly. For example:
-
-```js
-import { within } from '@testing-library/dom/dist/@testing-library/dom.umd.js'
-```
-
-You can
-[review the published `dist` files here](https://unpkg.com/@testing-library/dom/dist/).
-
-The `main` file is configured to compile down to support the version of node
-that is referenced in the `package.json` `engines.node` field. But the `module`
-and `umd:main` files are configured to compile down to support browsers as old
-as IE 10.
-
-
-
-[npm]: https://www.npmjs.com/
-[node]: https://nodejs.org
diff --git a/docs/dom-testing-library/install.mdx b/docs/dom-testing-library/install.mdx
new file mode 100644
index 000000000..903a0325f
--- /dev/null
+++ b/docs/dom-testing-library/install.mdx
@@ -0,0 +1,81 @@
+---
+id: install
+title: Install
+sidebar_label: Install
+---
+
+This module is distributed via [npm][npm] which is bundled with [node][node] and
+should be installed as one of your project's `devDependencies`:
+
+```bash npm2yarn
+npm install --save-dev @testing-library/dom
+```
+
+## Wrappers
+
+If you are using a framework or library such as React, you will likely want to
+install the wrapper:
+
+- [React Testing Library](react-testing-library/intro.mdx)
+- [Reason Testing Library](bs-react-testing-library/intro.mdx)
+- [React Native Testing Library](react-native-testing-library/intro.mdx)
+- [Vue Testing Library](vue-testing-library/intro.mdx)
+- [Marko Testing Library](marko-testing-library/intro.mdx)
+- [Angular Testing Library](angular-testing-library/intro.mdx)
+- [Preact Testing Library](preact-testing-library/intro.mdx)
+- [Svelte Testing Library](svelte-testing-library/intro.mdx)
+- [Cypress Testing Library](cypress-testing-library/intro.mdx)
+- [Puppeteer Testing Library](pptr-testing-library/intro.mdx)
+- [Testcafe Testing Library](testcafe-testing-library/intro.mdx)
+- [Nightwatch Testing Library](nightwatch-testing-library/intro.mdx)
+- [Solid Testing Library](solid-testing-library/intro.mdx)
+
+## Ecosystem
+
+`DOM Testing Library` works well with these companion libraries:
+
+- [user-event](user-event/intro.mdx) browser event simulation
+- [jest-dom](ecosystem-jest-dom.mdx) custom Jest matchers
+- [bs-jest-dom](ecosystem-bs-jest-dom.mdx) companion library for
+  `bs-react-testing-library`
+- [jest-native](ecosystem-jest-native.mdx) companion library for
+  `React Native Testing Library`
+- [react-select-event](ecosystem-react-select-event.mdx) companion library for
+  `React Testing Library`
+- [eslint-plugin-testing-library](ecosystem-eslint-plugin-testing-library.mdx)
+  ESLint plugin for Testing Library
+- [eslint-plugin-jest-dom](ecosystem-eslint-plugin-jest-dom.mdx) ESLint plugin
+  for Jest DOM
+- [riot-testing-library](ecosystem-riot-testing-library.mdx) adds APIs for
+  working with Riot.js components
+
+## Main Exports
+
+You can
+[review the `DOM Testing Library` package.json here](https://unpkg.com/@testing-library/dom/package.json).
+
+In particular, the `main`, `module`, and `umd:main` fields are useful. Each of
+these points to a file that's useful in certain situations. Typically, your
+testing framework will resolve to the correct one for your situation, but if it
+does not, then you can either configure your testing framework to resolve to the
+right file when you require/import `@testing-library/dom` or you can import the
+file you need more explicitly. For example:
+
+```js
+import {within} from '@testing-library/dom/dist/@testing-library/dom.umd.js'
+```
+
+You can
+[review the published `dist` files here](https://unpkg.com/@testing-library/dom/dist/).
+
+The `main` file is configured to compile down to support the version of node
+that is referenced in the `package.json` `engines.node` field. But the `module`
+and `umd:main` files are configured to compile down to support browsers as old
+as IE 10.
+
+
+
+[npm]: https://www.npmjs.com/
+[node]: https://nodejs.org
diff --git a/docs/dom-testing-library/intro.md b/docs/dom-testing-library/intro.mdx
similarity index 83%
rename from docs/dom-testing-library/intro.md
rename to docs/dom-testing-library/intro.mdx
index 1cbd1b66a..7b323265c 100644
--- a/docs/dom-testing-library/intro.md
+++ b/docs/dom-testing-library/intro.mdx
@@ -22,12 +22,12 @@ elements on the page. In this way, the library helps ensure your tests give you
 confidence in your UI code. The `DOM Testing Library`'s primary guiding
 principle is:
 
-> [The more your tests resemble the way your software is used, the more confidence they can give you.](guiding-principles.md)
+> [The more your tests resemble the way your software is used, the more confidence they can give you.](guiding-principles.mdx)
 
 As part of this goal, the utilities this library provides facilitate querying
-the DOM in the same way the user would. Finding for elements by their label text
-(just like a user would), finding links and buttons from their text (like a user
-would), and more. It also exposes a recommended way to find elements by a
+the DOM in the same way the user would. Finding form elements by their label
+text (just like a user would), finding links and buttons from their text (like a
+user would), and more. It also exposes a recommended way to find elements by a
 `data-testid` as an "escape hatch" for elements where the text content and label
 do not make sense or is not practical.
 
@@ -41,6 +41,6 @@ when a real user uses it.
 1.  A test runner or framework
 2.  Specific to a testing framework (though we recommend Jest as our preference,
     the library works with any framework. See
-    [Using Without Jest](setup.md#using-without-jest))
+    [Using Without Jest](setup.mdx#using-without-jest))
 
 [jest]: https://jestjs.io
diff --git a/docs/dom-testing-library/setup.md b/docs/dom-testing-library/setup.mdx
similarity index 62%
rename from docs/dom-testing-library/setup.md
rename to docs/dom-testing-library/setup.mdx
index fa4263359..b3be51807 100644
--- a/docs/dom-testing-library/setup.md
+++ b/docs/dom-testing-library/setup.mdx
@@ -10,7 +10,6 @@ people using `DOM Testing Library` are using it with
 [the Jest testing framework](https://jestjs.io/) with the `testEnvironment` set
 to
 [`jest-environment-jsdom`](https://www.npmjs.com/package/jest-environment-jsdom)
-(which is the default configuration with Jest).
 
 ## Using Without Jest
 
@@ -18,21 +17,20 @@ to
 the DOM and browser APIs that runs in node. If you're not using Jest and you
 would like to run your tests in Node, then you must install jsdom yourself.
 There's also a package called
-[jsdom-global](https://github.com/rstacruz/jsdom-global) which can be used to
-setup the global environment to simulate the browser APIs.
+[global-jsdom](https://github.com/modosc/global-jsdom) which can be used to
+setup the global environment to simulate the browser APIs. Note that if you're
+using Vitest you only need to configure
+[`environment`](https://vitest.dev/config/#environment) to `jsdom` to achieve
+the same effect, you don't need global-jsdom.
 
-First, install jsdom and jsdom-global.
+First, install jsdom and global-jsdom.
 
-```
-npm install --save-dev jsdom jsdom-global
+```bash npm2yarn
+npm install --save-dev jsdom global-jsdom
 ```
 
 With mocha, the test command would look something like this:
 
 ```
-mocha --require jsdom-global/register
+mocha --require global-jsdom/register
 ```
-
-> Note, depending on the version of Node you're running, you may also need to
-> install `@babel/polyfill` (if you're using babel 7) or `babel-polyfill` (for
-> babel 6).
diff --git a/docs/ecosystem-bs-jest-dom.md b/docs/ecosystem-bs-jest-dom.mdx
similarity index 90%
rename from docs/ecosystem-bs-jest-dom.md
rename to docs/ecosystem-bs-jest-dom.mdx
index ae30bbd3a..0f75bb463 100644
--- a/docs/ecosystem-bs-jest-dom.md
+++ b/docs/ecosystem-bs-jest-dom.mdx
@@ -4,11 +4,11 @@ title: bs-jest-dom
 ---
 
 [`bs-jest-dom`][gh] is a companion library for
-[`bs-react-testing-library`](/docs/bs-react-testing-library/intro) that provides
+[`bs-react-testing-library`](bs-react-testing-library/intro.mdx) that provides
 custom DOM element matchers for Jest in [ReasonML][re] via
 [BuckleScript][bucklescript].
 
-```
+```bash npm2yarn
 npm install --save-dev bs-jest-dom
 ```
 
@@ -30,9 +30,7 @@ full list of available matchers.
 
 ## Example
 
-```reason
-/* A_test.re */
-
+```reason title="A_test.re"
 open Jest;
 open JestDom;
 open ReactTestingLibrary;
diff --git a/docs/ecosystem-cli-testing-library.mdx b/docs/ecosystem-cli-testing-library.mdx
new file mode 100644
index 000000000..8b5a4074d
--- /dev/null
+++ b/docs/ecosystem-cli-testing-library.mdx
@@ -0,0 +1,48 @@
+---
+id: ecosystem-cli-testing-library
+title: cli-testing-library
+---
+
+[`CLI Testing Library`](https://github.com/crutchcorn/cli-testing-library) is a
+companion library to `Testing Library` that aims to mimic the API of
+`Testing Library` for testing CLI applications.
+
+```bash npm2yarn
+npm install --save-dev cli-testing-library
+```
+
+```js
+import {resolve} from 'path'
+import {render} from 'cli-testing-library'
+
+test('Is able to make terminal input and view in-progress stdout', async () => {
+  const {clear, findByText, queryByText, userEvent} = await render('node', [
+    resolve(__dirname, './execute-scripts/stdio-inquirer.js'),
+  ])
+
+  const instance = await findByText('First option')
+
+  expect(instance).toBeInTheConsole()
+
+  expect(await findByText('❯ One')).toBeInTheConsole()
+
+  clear()
+
+  userEvent('[ArrowDown]')
+
+  expect(await findByText('❯ Two')).toBeInTheConsole()
+
+  clear()
+
+  userEvent.keyboard('[Enter]')
+
+  expect(await findByText('First option: Two')).toBeInTheConsole()
+  expect(await queryByText('First option: Three')).not.toBeInTheConsole()
+})
+```
+
+Check out
+[CLI Testing Library's documentation](https://github.com/crutchcorn/cli-testing-library)
+for a full list of its API.
+
+- [CLI Testing Library on GitHub](https://github.com/crutchcorn/cli-testing-library)
diff --git a/docs/ecosystem-eslint-plugin-jest-dom.mdx b/docs/ecosystem-eslint-plugin-jest-dom.mdx
new file mode 100644
index 000000000..62953480c
--- /dev/null
+++ b/docs/ecosystem-eslint-plugin-jest-dom.mdx
@@ -0,0 +1,19 @@
+---
+id: ecosystem-eslint-plugin-jest-dom
+title: eslint-plugin-jest-dom
+---
+
+[`eslint-plugin-jest-dom`][gh] is an ESLint plugin for Jest DOM that helps users
+to follow best practices and anticipate common mistakes when writing tests.
+
+This plugin includes:
+
+- Several rules for linting Jest DOM specific code.
+- Shareable config for recommended rules.
+- Some autofixable rules.
+
+Find more info about available rules and configs on GitHub.
+
+- [eslint-plugin-jest-dom on GitHub][gh]
+
+[gh]: https://github.com/testing-library/eslint-plugin-jest-dom
diff --git a/docs/ecosystem-eslint-plugin-testing-library.mdx b/docs/ecosystem-eslint-plugin-testing-library.mdx
new file mode 100644
index 000000000..0b69bd33b
--- /dev/null
+++ b/docs/ecosystem-eslint-plugin-testing-library.mdx
@@ -0,0 +1,23 @@
+---
+id: ecosystem-eslint-plugin-testing-library
+title: eslint-plugin-testing-library
+---
+
+[`eslint-plugin-testing-library`][gh] is an ESLint plugin for Testing Library
+that helps users to follow best practices and anticipate common mistakes when
+writing tests.
+
+
+
+This plugin includes:
+
+- Several rules for linting Testing Library specific code.
+- Shareable config for recommended rules.
+- Shareable configs for specific rules by framework: Angular, React, Vue.
+- Some autofixable rules.
+
+Find more info about available rules and configs on GitHub.
+
+- [eslint-plugin-testing-library on GitHub][gh]
+
+[gh]: https://github.com/testing-library/eslint-plugin-testing-library
diff --git a/docs/ecosystem-jasmine-dom.mdx b/docs/ecosystem-jasmine-dom.mdx
new file mode 100644
index 000000000..853baff10
--- /dev/null
+++ b/docs/ecosystem-jasmine-dom.mdx
@@ -0,0 +1,35 @@
+---
+id: ecosystem-jasmine-dom
+title: jasmine-dom
+---
+
+[`jasmine-dom`][gh] is a companion library for Testing Library that provides
+custom DOM element matchers for Jasmine
+
+```bash npm2yarn
+npm install --save-dev @testing-library/jasmine-dom
+```
+
+Then follow [usage section][gh-usage] from jasmine-dom's documentation to add
+the matchers to Jasmine.
+
+```jsx
+Visible Example
+
+expect(screen.queryByTestId('not-empty')).not.toBeEmptyDOMElement()
+expect(screen.getByText('Visible Example')).toBeVisible()
+```
+
+> Note: when using some of these matchers, you may need to make sure you use a
+> query function (like `queryByTestId`) rather than a get function (like
+> `getByTestId`). Otherwise the `get*` function could throw an error before your
+> assertion.
+
+Check out [jasmine-dom's documentation][gh] for a full list of available
+matchers.
+
+- [jasmine-dom on GitHub][gh]
+
+[gh]: https://github.com/testing-library/jasmine-dom
+[gh-usage]: https://github.com/testing-library/jasmine-dom#usage
diff --git a/docs/ecosystem-jest-dom.md b/docs/ecosystem-jest-dom.md
deleted file mode 100644
index 0582dd172..000000000
--- a/docs/ecosystem-jest-dom.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-id: ecosystem-jest-dom
-title: jest-dom
----
-
-[`jest-dom`][gh] is a companion library for `React Testing Library` that
-provides custom DOM element matchers for Jest
-
-```
-npm install --save-dev @testing-library/jest-dom
-```
-
-```jsx
-Visible Example
-
-expect(queryByTestId(container, 'not-empty')).not.toBeEmpty()
-expect(getByText(container, 'Visible Example')).toBeVisible()
-```
-
-> Note: when using some of these matchers, you may need to make sure you use a
-> query function (like `queryByTestId`) rather than a get function (like
-> `getByTestId`). Otherwise the `get*` function could throw an error before your
-> assertion.
-
-Check out [jest-dom's documentation][gh] for a full list of available matchers.
-
-- [jest-dom on GitHub][gh]
-
-[gh]: https://github.com/testing-library/jest-dom
diff --git a/docs/ecosystem-jest-dom.mdx b/docs/ecosystem-jest-dom.mdx
new file mode 100644
index 000000000..33d473fe6
--- /dev/null
+++ b/docs/ecosystem-jest-dom.mdx
@@ -0,0 +1,40 @@
+---
+id: ecosystem-jest-dom
+title: jest-dom
+---
+
+[`jest-dom`][gh] is a companion library for Testing Library that provides custom
+DOM element matchers for Jest
+
+```bash npm2yarn
+npm install --save-dev @testing-library/jest-dom
+```
+
+Then follow [usage section][gh-usage] from jest-dom's documentation to add the
+matchers to Jest.
+
+```jsx
+import {screen} from '@testing-library/dom'
+
+test('uses jest-dom', () => {
+  document.body.innerHTML = `
+    Visible Example
+  `
+
+  expect(screen.queryByTestId('not-empty')).not.toBeEmptyDOMElement()
+  expect(screen.getByText('Visible Example')).toBeVisible()
+})
+```
+
+> Note: when using some of these matchers, you may need to make sure you use a
+> query function (like `queryByTestId`) rather than a get function (like
+> `getByTestId`). Otherwise the `get*` function could throw an error before your
+> assertion.
+
+Check out [jest-dom's documentation][gh] for a full list of available matchers.
+
+- [jest-dom on GitHub][gh]
+
+[gh]: https://github.com/testing-library/jest-dom
+[gh-usage]: https://github.com/testing-library/jest-dom#usage
diff --git a/docs/ecosystem-jest-native.md b/docs/ecosystem-jest-native.md
deleted file mode 100644
index a21c8d48c..000000000
--- a/docs/ecosystem-jest-native.md
+++ /dev/null
@@ -1,36 +0,0 @@
----
-id: ecosystem-jest-native
-title: jest-native
-sidebar_label: jest-native
----
-
-[`Jest Native`](https://github.com/testing-library/jest-native) is a companion
-library for `Native Testing Library` that provides custom element matchers for
-Jest.
-
-```
-npm install --save-dev @testing-library/jest-native
-```
-
-```javascript
-;
-  
-     
-  Visible Example 
- 
-
-expect(queryByTestId(baseElement, 'not-empty')).not.toBeEmpty()
-expect(getByText(baseElement, 'Visible Example')).toBeVisible()
-```
-
-> Note: when using some of these matchers, you may need to make sure you use a
-> query function (like `queryByTestId`) rather than a get function (like
-> `getByTestId`). Otherwise the `get*` function could throw an error before your
-> assertion.
-
-Check out
-[Jest Native's documentation](https://github.com/testing-library/jest-native)
-for a full list of available matchers.
-
-- [Jest Native on GitHub](https://github.com/testing-library/jest-native)
diff --git a/docs/ecosystem-jest-native.mdx b/docs/ecosystem-jest-native.mdx
new file mode 100644
index 000000000..b201e8a9f
--- /dev/null
+++ b/docs/ecosystem-jest-native.mdx
@@ -0,0 +1,51 @@
+---
+id: ecosystem-jest-native
+title: jest-native
+sidebar_label: jest-native
+---
+
+:::warning
+
+**This package is deprecated and is no longer actively maintained.**
+
+We encourage you to migrate to React Native Testing Library, v12.4 or later,
+which includes modern
+[built-in Jest matchers](https://callstack.github.io/react-native-testing-library/docs/api/jest-matchers)
+based on the matchers for this repository. The migration process should be
+relatively straightforward, we have a
+[migration guide](https://callstack.github.io/react-native-testing-library/docs/migration/jest-matchers)
+available.
+
+:::
+
+[`Jest Native`](https://github.com/testing-library/jest-native) is a companion
+library for `React Native Testing Library` that provides custom element matchers
+for Jest.
+
+```bash npm2yarn
+npm install --save-dev @testing-library/jest-native
+```
+
+```jsx
+const {queryByTestId} = render(
+  
+    
+       
+    Visible Example 
+   ,
+)
+
+expect(queryByTestId('not-empty')).not.toBeEmpty()
+```
+
+> Note: when using some of these matchers, you may need to make sure you use a
+> query function (like `queryByTestId`) rather than a get function (like
+> `getByTestId`). Otherwise the `get*` function could throw an error before your
+> assertion.
+
+Check out
+[Jest Native's documentation](https://github.com/testing-library/jest-native)
+for a full list of available matchers.
+
+- [Jest Native on GitHub](https://github.com/testing-library/jest-native)
diff --git a/docs/ecosystem-native-testing-library.md b/docs/ecosystem-native-testing-library.md
deleted file mode 100644
index 9f888ffbf..000000000
--- a/docs/ecosystem-native-testing-library.md
+++ /dev/null
@@ -1,76 +0,0 @@
----
-id: ecosystem-native-testing-library
-title: Native Testing Library
-sidebar_label: native-testing-library
----
-
-Native Testing Library is a testing library for **React Native** inspired by
-`DOM Testing Library`. Because React Native does not run in a browser
-environment, the core queries are implemented independently, unlike other
-wrappers that use `DOM Testing Library` as the base. You'll find much more
-information about the library, including examples, on the project website:
-
-- [Docs](https://native-testing-library.com)
-- [Docs repo](https://github.com/bcarroll22/native-testing-library-docs)
-- [Project repo](https://github.com/bcarroll22/native-testing-library)
-
-## Installation
-
-This module should be installed in your project's `devDependencies`:
-
-```
-npm install --save-dev @testing-library/react-native
-```
-
-You will also need `react` and `react-native` installed as `dependencies` in
-order to use this project.
-
-## Example
-
-```javascript
-import React from 'react'
-import { Button, Text, TextInput, View } from 'react-native'
-import { fireEvent, render, wait } from '@testing-library/react-native'
-
-function Example() {
-  const [name, setUser] = React.useState('')
-  const [show, setShow] = React.useState(false)
-
-  return (
-    
-       {
-          // let's pretend this is making a server request, so it's async
-          // (you'd want to mock this imaginary request in your unit tests)...
-          setTimeout(() => {
-            setShow(!show)
-          }, Math.floor(Math.random() * 200))
-        }}
-      />
-      {show && {name} }
-      
-  )
-}
-
-test('examples of some things', async () => {
-  const { getByTestId, getByText, queryByTestId, rootInstance } = render(
-    ('Password:'),
+}
+
+// reuse them in the same test or across multiple tests by calling
+// .get(), .getAll(), .find(), .findAll(), .query(), .queryAll()
+it('example test', async () => {
+  // by default elements will be queried against screen
+  await ui.submitButton.find()
+  expect(ui.submitButton.query()).not.toBeInDocument()
+  expect(ui.submitButton.get()).toBeInDocument()
+
+  const containers = ui.container.getAll()
+  expect(containers).toHaveLength(3)
+
+  // provide a container as first param to query element inside that container
+  const username = ui.usernameInput.get(containers[0])
+})
+```
+
+- [testing-library-selector on GitHub][gh]
+
+[gh]: https://github.com/domasx2/testing-library-selector
diff --git a/docs/ecosystem-user-event.md b/docs/ecosystem-user-event.md
deleted file mode 100644
index 312f4273a..000000000
--- a/docs/ecosystem-user-event.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-id: ecosystem-user-event
-title: user-event
----
-
-[`user-event`][gh] is a companion library for `React Testing Library` that
-provides more advanced simulation of browser interactions than the built-in
-`fireEvent` method.
-
-```
-npm install --save-dev @testing-library/user-event
-```
-
-```jsx
-import React from 'react'
-import { render } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
-
-const { getByText } = test('click', () => {
-  render()
-})
-
-userEvent.type(getByTestId('email'), 'Hello, World!')
-expect(getByTestId('email')).toHaveAttribute('value', 'Hello, World!')
-```
-
-- [user-event on GitHub][gh]
-
-[gh]: https://github.com/testing-library/user-event
diff --git a/docs/example-codesandbox.md b/docs/example-codesandbox.md
deleted file mode 100644
index e028f2099..000000000
--- a/docs/example-codesandbox.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-id: example-codesandbox
-title: Codesandbox Examples
-sidebar_label: Codesandbox Examples
----
-
-You can find runnable examples for many common use cases on Codesandbox.
-
-[](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/)
-
-
diff --git a/docs/example-codesandbox.mdx b/docs/example-codesandbox.mdx
new file mode 100644
index 000000000..fda0b475c
--- /dev/null
+++ b/docs/example-codesandbox.mdx
@@ -0,0 +1,26 @@
+---
+id: example-codesandbox
+title: Codesandbox Examples
+sidebar_label: Codesandbox Examples
+---
+
+You can find runnable examples for many common use cases on Codesandbox.
+
+[](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/main/)
+
+
+
+## Playground
+
+Are you looking for a quick way to run queries against your own html instead?
+Try [testing-playground.com](https://testing-playground.com)
diff --git a/docs/example-drag.mdx b/docs/example-drag.mdx
new file mode 100644
index 000000000..7203e6336
--- /dev/null
+++ b/docs/example-drag.mdx
@@ -0,0 +1,102 @@
+---
+id: example-drag
+title: Drag
+sidebar_label: Drag
+---
+
+> **Note**
+>
+> This example only works with a real browser (not with jsdom, as it does not
+> support `getBoundingClientRect`).
+
+# Usage
+
+```js
+await drag(slider, {
+  delta: {x: -100, y: 0},
+})
+```
+
+# Capture
+
+
+
+# Code
+
+```js
+import {fireEvent} from '@testing-library/dom'
+
+// https://stackoverflow.com/a/53946549/1179377
+function isElement(obj) {
+  if (typeof obj !== 'object') {
+    return false
+  }
+  let prototypeStr, prototype
+  do {
+    prototype = Object.getPrototypeOf(obj)
+    // to work in iframe
+    prototypeStr = Object.prototype.toString.call(prototype)
+    // '[object Document]' is used to detect document
+    if (
+      prototypeStr === '[object Element]' ||
+      prototypeStr === '[object Document]'
+    ) {
+      return true
+    }
+    obj = prototype
+    // null is the terminal of object
+  } while (prototype !== null)
+  return false
+}
+
+function getElementClientCenter(element) {
+  const {left, top, width, height} = element.getBoundingClientRect()
+  return {
+    x: left + width / 2,
+    y: top + height / 2,
+  }
+}
+
+const getCoords = charlie =>
+  isElement(charlie) ? getElementClientCenter(charlie) : charlie
+
+const sleep = ms =>
+  new Promise(resolve => {
+    setTimeout(resolve, ms)
+  })
+
+export default async function drag(
+  element,
+  {to: inTo, delta, steps = 20, duration = 500},
+) {
+  const from = getElementClientCenter(element)
+  const to = delta
+    ? {
+        x: from.x + delta.x,
+        y: from.y + delta.y,
+      }
+    : getCoords(inTo)
+
+  const step = {
+    x: (to.x - from.x) / steps,
+    y: (to.y - from.y) / steps,
+  }
+
+  const current = {
+    clientX: from.x,
+    clientY: from.y,
+  }
+
+  fireEvent.mouseEnter(element, current)
+  fireEvent.mouseOver(element, current)
+  fireEvent.mouseMove(element, current)
+  fireEvent.mouseDown(element, current)
+  for (let i = 0; i < steps; i++) {
+    current.clientX += step.x
+    current.clientY += step.y
+    await sleep(duration / steps)
+    fireEvent.mouseMove(element, current)
+  }
+  fireEvent.mouseUp(element, current)
+}
+```
diff --git a/docs/example-external.md b/docs/example-external.md
deleted file mode 100644
index fa4b369d8..000000000
--- a/docs/example-external.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-id: example-external
-title: External Examples
-sidebar_label: External Examples
----
-
-## Code Samples
-
-- You can find more React Testing Library examples at
-  [react-testing-examples.com](https://react-testing-examples.com/jest-rtl/).
-
-## Videos
-
-- [What is React Testing Library?](https://youtu.be/JKOwJUM4_RM) by Scott
-  Tolinski
-
-
-   
diff --git a/docs/example-external.mdx b/docs/example-external.mdx
new file mode 100644
index 000000000..430e6b38f
--- /dev/null
+++ b/docs/example-external.mdx
@@ -0,0 +1,24 @@
+---
+id: example-external
+title: External Examples
+sidebar_label: External Examples
+---
+
+## Playground
+
+- An interactive sandbox with visual feedback on different queries
+  [testing-playground.com](https://testing-playground.com).
+
+## Videos
+
+- [What is React Testing Library?](https://youtu.be/JKOwJUM4_RM) by Scott
+  Tolinski
+
+
+   
diff --git a/docs/example-findByText.md b/docs/example-findByText.md
new file mode 100644
index 000000000..f2b02b2d6
--- /dev/null
+++ b/docs/example-findByText.md
@@ -0,0 +1,135 @@
+---
+id: example-findByText
+title: Using findByText
+---
+
+```javascript
+// src/__tests__/example.test.js
+// This is an example of how to use findByText to query for text that
+// is not visible right away
+
+import {screen} from '@testing-library/dom'
+import userEvent from '@testing-library/user-event'
+// provides a set of custom jest matchers that you can use to extend jest
+// i.e. `.toBeVisible`
+import '@testing-library/jest-dom'
+
+function renderApp() {
+  const el = document.body.appendChild(document.createElement('div'))
+  el.innerHTML = `
+    
+  `
+
+  const submitButton = el.querySelector('#submit')
+  const formEl = el.querySelector('#login_form')
+
+  submitButton.addEventListener('click', () => {
+    const userInput = el.querySelector('#username_input')
+    const passwordInput = el.querySelector('#password_input')
+
+    const userName = userInput.value
+    const password = passwordInput.value
+    if (!userName) {
+      el.querySelector('#username_required_error').style.display = 'inline'
+    }
+
+    if (!password) {
+      el.querySelector('#password_required_error').style.display = 'inline'
+    }
+
+    if (userName && userName !== 'Bob') {
+      el.querySelector('#invalid_username_error').style.display = 'inline'
+    }
+
+    if (password && password !== 'theBuilder') {
+      el.querySelector('#invalid_password_error').style.display = 'inline'
+    }
+  })
+
+  formEl.addEventListener('submit', function (evt) {
+    evt.preventDefault()
+    window.history.back()
+  })
+
+  return {user: userEvent.setup()}
+}
+
+afterEach(() => (document.body.innerHTML = ``))
+
+describe('findByText Examples', () => {
+  it('should show a required field warning for each empty input field', async () => {
+    const {user} = renderApp()
+    await user.click(
+      screen.getByRole('button', {
+        name: 'Login',
+      }),
+    )
+
+    expect(await screen.findByText('User Name Required')).toBeVisible()
+
+    expect(await screen.findByText('Password Required')).toBeVisible()
+  })
+
+  it('should show invalid field errors for each invalid input field', async () => {
+    const {user} = renderApp()
+    const userNameField = screen.getByPlaceholderText('Enter user name')
+    const passwordField = screen.getByPlaceholderText('Enter password')
+
+    expect(await screen.findByText('Invalid Password')).not.toBeVisible()
+    expect(await screen.findByText('Invalid User Name')).not.toBeVisible()
+
+    await user.type(userNameField, 'Philchard')
+    await user.type(passwordField, 'theCat')
+
+    expect(userNameField).toHaveValue('Philchard')
+    expect(passwordField).toHaveValue('theCat')
+
+    await user.click(
+      screen.getByRole('button', {
+        name: 'Login',
+      }),
+    )
+
+    expect(await screen.findByText('Invalid User Name')).toBeVisible()
+    expect(await screen.findByText('Invalid Password')).toBeVisible()
+  })
+})
+```
diff --git a/docs/example-formik.md b/docs/example-formik.md
new file mode 100644
index 000000000..4d2525b04
--- /dev/null
+++ b/docs/example-formik.md
@@ -0,0 +1,85 @@
+---
+id: example-react-formik
+title: Formik
+---
+
+Example based in this
+[Async Submission Formik example](https://formik.org/docs/examples/async-submission)
+
+```jsx
+// myForm.js
+import React from 'react'
+import {Formik, Field, Form} from 'formik'
+
+const sleep = ms => new Promise(r => setTimeout(r, ms))
+
+export const MyForm = ({onSubmit}) => {
+  const handleSubmit = async values => {
+    await sleep(500)
+    onSubmit(values)
+  }
+
+  return (
+    
+      
Sign Up 
+      
+        
+       
+    
+  )
+}
+```
+
+```jsx
+// myForm.test.js
+import React from 'react'
+import {render, screen, waitFor} from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+
+import {MyForm} from './myForm.js'
+
+test('rendering and submitting a basic Formik form', async () => {
+  const handleSubmit = jest.fn()
+  render(You are on the about page
 const Home = () => You are home
@@ -39,7 +39,7 @@ function App() {
 // that relies on the router being in context
 function renderWithRouter(
   ui,
-  { route = '/', history = createHistory(createMemorySource(route)) } = {}
+  {route = '/', history = createHistory(createMemorySource(route))} = {},
 ) {
   return {
     ...render({ui} ),
@@ -53,7 +53,7 @@ function renderWithRouter(
 test('full app rendering/navigating', async () => {
   const {
     container,
-    history: { navigate },
+    history: {navigate},
   } = renderWithRouter(
+     
+)
+
+// render function with Router wrapper from @reach/router
+function renderWithRouterWrapper(
+  ui,
+  {route = '/', history = createHistory(createMemorySource(route))} = {},
+) {
+  return {
+    ...render(
+      
+        {ui} 
+       ,
+    ),
+    history,
+  }
+}
+
+test('renders the component with params', () => {
+  // you'll have to declare the path prop in the component, exactly like the route
+  renderWithRouterWrapper(
-       
-  )
-  const { getByText } = render(tree)
-  expect(getByText(/^My Name Is:/)).toHaveTextContent('My Name Is: C3P0')
-})
-
-/**
- * To test a component that provides a context value, render a matching
- * consumer as the child
- */
-test('NameProvider composes full name from first, last', () => {
-  const tree = (
-    
-      
-        {value => Received: {value} }
-       
-     
-  )
-  const { getByText } = render(tree)
-  expect(getByText(/^Received:/).textContent).toBe('Received: Boba Fett')
-})
-
-/**
- * A tree containing both a providers and consumer can be rendered normally
- */
-test('NameProvider/Consumer shows name of character', () => {
-  const tree = (
-    
-       
-  )
-  const { getByText } = render(tree)
-  expect(getByText(/^My Name Is:/).textContent).toBe('My Name Is: Leia Organa')
-})
-```
diff --git a/docs/example-react-context.mdx b/docs/example-react-context.mdx
new file mode 100644
index 000000000..212365e3c
--- /dev/null
+++ b/docs/example-react-context.mdx
@@ -0,0 +1,78 @@
+---
+id: example-react-context
+title: React Context
+---
+
+```jsx
+import React from 'react'
+import {render, screen} from '@testing-library/react'
+import '@testing-library/jest-dom'
+import {NameContext, NameProvider, NameConsumer} from '../react-context'
+
+/**
+ * Test default values by rendering a context consumer without a
+ * matching provider
+ */
+test('NameConsumer shows default value', () => {
+  render({ui} ,
+    renderOptions,
+  )
+}
+
+test('NameConsumer shows value from provider', () => {
+  const providerProps = {
+    value: 'C3PO',
+  }
+  customRender(
+      {value => Received: {value} }
+     ,
+    {providerProps},
+  )
+  expect(screen.getByText(/^Received:/).textContent).toBe('Received: Boba Fett')
+})
+
+/**
+ * A tree containing both a providers and consumer can be rendered normally
+ */
+test('NameProvider/Consumer shows name of character', () => {
+  const wrapper = ({children}) => (
+    
+      {children}
+     
+  )
+
+  render(Waiting for confirmation...
         )}
       
-      Confirm 
+       dispatch({type: 'SUCCESS'})}>Confirm 
     
   )
 }
@@ -50,23 +51,23 @@ const Example = () => {
 export default Example
 ```
 
-We are testing to see if we get the correct output in our JSX
-based on the reducer state.
+We are testing to see if we get the correct output in our JSX based on the
+reducer state.
 
 ```jsx
 // example.test.js
 
 import React from 'react'
-import { render, fireEvent } from '@testing-library/react'
+import {render, fireEvent} from '@testing-library/react'
 import Example from './example.js'
 
 it('shows success message after confirm button is clicked', () => {
-  const { getByText } = render(
-      
-  )
-}
-
-const renderWithReactIntl = component => {
-  return render({component} )
-}
-
-setupTests()
-
-test('it should render FormattedDate and have a formated pt date', () => {
-  const { container } = renderWithReactIntl({children} 
+  }
+  return rtlRender(ui, {wrapper: Wrapper, ...renderOptions})
+}
+
+// re-export everything
+export * from '@testing-library/react'
+
+// override render method
+export {render}
+```
+
+## A complete example
+
+```jsx
+import React from 'react'
+import '@testing-library/jest-dom'
+// We're importing from our own created test-utils and not RTL's
+import {render, screen, setupTests} from '../test-utils.js'
+import {FormattedDate} from 'react-intl'
+
+const FormatDateView = () => {
+  return (
+    
+      
+  )
+}
+
+setupTests()
+
+test('it should render FormattedDate and have a formatted pt date', () => {
+  render(
-        
 e.stopPropagation()}
-        >
-          {this.props.children}
-          
Close 
-        
-      
-      test
-     
-  )
-  // Assert
-  expect(getByText('test')).toBeTruthy()
-
-  // Act
-  fireEvent.click(getByText(/close/i))
-
-  // Assert
-  expect(handleClose).toHaveBeenCalledTimes(1)
-})
-```
diff --git a/docs/example-react-modal.mdx b/docs/example-react-modal.mdx
new file mode 100644
index 000000000..9bccf105a
--- /dev/null
+++ b/docs/example-react-modal.mdx
@@ -0,0 +1,55 @@
+---
+id: example-react-modal
+title: Modals
+---
+
+```jsx
+import React, {useEffect} from 'react'
+import ReactDOM from 'react-dom'
+import {render, fireEvent} from '@testing-library/react'
+
+const modalRoot = document.createElement('div')
+modalRoot.setAttribute('id', 'modal-root')
+document.body.appendChild(modalRoot)
+
+const Modal = ({onClose, children}) => {
+  const el = document.createElement('div')
+
+  useEffect(() => {
+    modalRoot.appendChild(el)
+
+    return () => modalRoot.removeChild(el)
+  })
+
+  return ReactDOM.createPortal(
+    
+      
 e.stopPropagation()}>
+        {children}
+        
Close 
+      
+    
+      test
+     ,
+  )
+  // Assert
+  expect(getByText('test')).toBeTruthy()
+
+  // Act
+  fireEvent.click(getByText(/close/i))
+
+  // Assert
+  expect(handleClose).toHaveBeenCalledTimes(1)
+})
+```
diff --git a/docs/example-react-redux.md b/docs/example-react-redux.md
deleted file mode 100644
index e4bcb90ae..000000000
--- a/docs/example-react-redux.md
+++ /dev/null
@@ -1,114 +0,0 @@
----
-id: example-react-redux
-title: React Redux
----
-
-```jsx
-// counter.js
-import React from 'react'
-import { connect } from 'react-redux'
-
-class Counter extends React.Component {
-  increment = () => {
-    this.props.dispatch({ type: 'INCREMENT' })
-  }
-
-  decrement = () => {
-    this.props.dispatch({ type: 'DECREMENT' })
-  }
-
-  render() {
-    return (
-      
-        
Counter 
-        
-          - 
-          {this.props.count} 
-          + 
-        
-      
{ui} ),
-    // adding `store` to the returned utilities to allow us
-    // to reference it in our tests (just try to avoid using
-    // this to test implementation details).
-    store,
-  }
-}
-
-test('can render with redux with defaults', () => {
-  const { getByTestId, getByText } = renderWithRedux(You are on the about page
-const Home = () => You are home
-const NoMatch = () => No match
-
-const LocationDisplay = withRouter(({ location }) => (
-  {location.pathname}
-))
-
-function App() {
-  return (
-    
-      
-         
-      
-  )
-}
-
-// Ok, so here's what your tests might look like
-
-// this is a handy function that I would utilize for any component
-// that relies on the router being in context
-function renderWithRouter(
-  ui,
-  {
-    route = '/',
-    history = createMemoryHistory({ initialEntries: [route] }),
-  } = {}
-) {
-  return {
-    ...render({ui} ),
-    // adding `history` to the returned utilities to allow us
-    // to reference it in our tests (just try to avoid using
-    // this to test implementation details).
-    history,
-  }
-}
-
-test('full app rendering/navigating', () => {
-  const { container, getByText } = renderWithRouter(You are on the about page
+const Home = () => You are home
+const NoMatch = () => No match
+
+export const LocationDisplay = () => {
+  const location = useLocation()
+
+  return {location.pathname}
+}
+
+export const App = () => (
+  
+    
+       
+
+    
+)
+```
+
+```jsx
+// app.test.js
+import {render, screen} from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import React from 'react'
+import '@testing-library/jest-dom'
+import {App, LocationDisplay} from './app'
+import {BrowserRouter, MemoryRouter} from 'react-router-dom'
+
+test('full app rendering/navigating', async () => {
+  render( when you want to manually control the history
+  render(
+    
+       ,
+  )
+
+  // verify navigation to "no match" route
+  expect(screen.getByText(/no match/i)).toBeInTheDocument()
+})
+
+test('rendering a component that uses useLocation', () => {
+  const route = '/some-route'
+
+  // use  when you want to manually control the history
+  render(
+    
+       ,
+  )
+
+  // verify location display is rendered
+  expect(screen.getByTestId('location-display')).toHaveTextContent(route)
+})
+```
+
+## Reducing boilerplate
+
+1. If you find yourself adding Router components to your tests a lot, you may
+   want to create a helper function that wraps around `render`.
+
+```jsx
+// test utils file
+const renderWithRouter = (ui, {route = '/'} = {}) => {
+  window.history.pushState({}, 'Test page', route)
+
+  return {
+    user: userEvent.setup(),
+    ...render(ui, {wrapper: BrowserRouter}),
+  }
+}
+```
+
+```jsx
+// app.test.js
+test('full app rendering/navigating', async () => {
+  const {user} = renderWithRouter(You are on the about page
+const Home = () => You are home
+const NoMatch = () => No match
+
+export const LocationDisplay = () => {
+  const location = useLocation()
+
+  return {location.pathname}
+}
+
+export const App = () => (
+  
+    
+       
+
+    
+)
+```
+
+In your tests, pass the history object as a whole to the Router component.
+**Note:** React Router v5
+[only works with History v4](https://github.com/remix-run/history#documentation),
+so make sure you have the correct version of `history` installed.
+
+```jsx
+// app.test.js
+import {render, screen} from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import {createMemoryHistory} from 'history'
+import React from 'react'
+import {Router} from 'react-router-dom'
+import '@testing-library/jest-dom'
+import {App} from './app'
+
+// React Router v5
+
+test('full app rendering/navigating', async () => {
+  const history = createMemoryHistory()
+  render(
+    
+       ,
+  )
+  const user = userEvent.setup()
+  // verify page content for expected route
+  // often you'd use a data-testid or role query, but this is also possible
+  expect(screen.getByText(/you are home/i)).toBeInTheDocument()
+
+  await user.click(screen.getByText(/about/i))
+
+  // check that the content changed to the new page
+  expect(screen.getByText(/you are on the about page/i)).toBeInTheDocument()
+})
+
+test('landing on a bad page', () => {
+  const history = createMemoryHistory()
+  history.push('/some/bad/route')
+  render(
+    
+       ,
+  )
+
+  expect(screen.getByText(/no match/i)).toBeInTheDocument()
+})
+```
diff --git a/docs/example-react-transition-group.md b/docs/example-react-transition-group.md
deleted file mode 100644
index 2ea5f82f7..000000000
--- a/docs/example-react-transition-group.md
+++ /dev/null
@@ -1,112 +0,0 @@
----
-id: example-react-transition-group
-title: React Transition Group
----
-
-## Mock
-
-```jsx
-import React from 'react'
-import { CSSTransition } from 'react-transition-group'
-import { render, fireEvent } from '@testing-library/react'
-
-function Fade({ children, ...props }) {
-  return (
-    
-      {children}
-     
-  )
-}
-
-class HiddenMessage extends React.Component {
-  state = { show: this.props.initialShow || false }
-  toggle = () => {
-    this.setState(({ show }) => ({ show: !show }))
-  }
-  render() {
-    return (
-      
-        
Toggle 
-        
-          Hello world
-         
-      
{props.children}  : null
-  )
-  return { CSSTransition: FakeCSSTransition, Transition: FakeTransition }
-})
-
-test('you can mock things with jest.mock', () => {
-  const { getByText, queryByText } = render(
-    
-      {children}
-     
-  )
-}
-
-class HiddenMessage extends React.Component {
-  state = { show: this.props.initialShow || false }
-  toggle = () => {
-    this.setState(({ show }) => ({ show: !show }))
-  }
-  render() {
-    return (
-      
-        
Toggle 
-        
-          Hello world
-         
-      
+      {children}
+     
+  )
+}
+
+function HiddenMessage({initialShow}) {
+  const [show, setShow] = useState(initialShow || false)
+  const toggle = () => setShow(prevState => !prevState)
+  return (
+    
+      
Toggle 
+      
+        Hello world
+       
+    
{props.children}  : null,
+  )
+  return {CSSTransition: FakeCSSTransition, Transition: FakeTransition}
+})
+
+test('you can mock things with jest.mock', () => {
+  const {getByText, queryByText} = render(
+      {children}
+     
+  )
+}
+
+function HiddenMessage({initialShow}) {
+  const [show, setShow] = useState(initialShow || false)
+  const toggle = () => setShow(prevState => !prevState)
+  return (
+    
+      
Toggle 
+      
+        Hello world
+       
+    
-        {this.props.number} 
-        {this.id} 
-      
-    )
-  }
-}
-
-test('calling render with the same component on the same container does not remount', () => {
-  const { getByTestId, rerender } = render(
+      {number} 
+      {id.current} 
+    
+  )
+}
+
+test('calling render with the same component on the same container does not remount', () => {
+  const {rerender} = render(Hello, Marko! 
   `)
 })
 ```
 
-> Note
->
-> The [cleanup](#cleanup) function should be called between tests to remove the
-> created DOM nodes and keep the tests isolated.
-
 ### `render` Options
 
 You won't often need to specify options, but if you ever do, here are the
-available options which you could provide as the third argument to `render`.
+available options which you can provide as the third argument to `render`.
 
 #### `container`
 
-By default for client side tests, `Marko Testing Library` will create a `div`
+By default for client-side tests, `Marko Testing Library` will create a `div`
 and append that `div` to the `document.body` and this is where your component
 will be rendered. If you provide your own HTMLElement `container` via this
 option, it will not be appended to the `document.body` automatically.
@@ -69,7 +70,7 @@ of a `div`. In this case, you can specify a `table` as the render `container`.
 ```javascript
 const table = document.createElement('table')
 
-const { container } = await render(MyTableBody, null, {
+const {container} = await render(MyTableBody, null, {
   container: document.body.appendChild(table),
 })
 ```
@@ -82,16 +83,26 @@ few properties:
 ### `...queries`
 
 The most important feature of `render` is that the queries from
-[DOM Testing Library](dom-testing-library/api-queries.md) are automatically
-returned with their first argument bound to the results of rendering your
-component.
+[the Core API](queries/about.mdx) are automatically returned with their first
+argument bound to the results of rendering your component.
 
-See [Queries](dom-testing-library/api-queries.md) for a complete list.
+See [Queries](queries/about.mdx#types-of-queries) for a complete list.
 
 **Example**
 
 ```javascript
-const { getByLabelText, queryAllByTestId } = await render(MyTemplate)
+const {getByLabelText, queryAllByTestId} = await render(MyTemplate)
+```
+
+Alternatively, you can use the
+[top-level `screen` method](queries/about.mdx#screen) to query into all
+currently rendered components in the `document.body`, eg:
+
+```javascript
+import { render, screen } from "@marko/testing-library"
+
+await render(MyTemplate)
+const el = screen.getByText(...)
 ```
 
 ### `debug`
@@ -100,10 +111,10 @@ This method is a shortcut for logging the `prettyDOM` for all children inside of
 the `container`.
 
 ```javascript
-import { render } from '@marko/testing-library'
+import {render} from '@marko/testing-library'
 import Greeting from './greeting.marko'
 
-const { debug } = await render(Greeting, { name: 'World' })
+const {debug} = await render(Greeting, {name: 'World'})
 debug()
 
 // Hello World 
@@ -111,24 +122,24 @@ debug()
 ```
 
 This is a simple wrapper around `prettyDOM` which is also exposed and comes from
-[`DOM Testing Library`](https://github.com/testing-library/dom-testing-library/blob/master/README.md#prettydom).
+[`DOM Testing Library`](dom-testing-library/api-debugging.mdx#prettydom).
 
 ### `rerender`
 
 A Marko components `input` can change at any time from a parent component.
 Although often this input is passed through your component declaratively,
-sometimes it is necessary to ensure that your components reacts appropriately to
+sometimes it is necessary to ensure that your components react appropriately to
 new data. You can simulate your component receiving new `input` by passing new
 data to the `rerender` helper.
 
 ```javascript
-import { render } from '@marko/testing-library'
+import {render} from '@marko/testing-library'
 import Greeting from './greeting.marko'
 
-const { rerender, debug } = await render(Greeting, { name: 'World' })
+const {rerender, debug} = await render(Greeting, {name: 'World'})
 
 // re-render the same component with different props
-await rerender({ name: 'Marko' })
+await rerender({name: 'Marko'})
 
 debug()
 // Hello Marko 
@@ -145,20 +156,20 @@ events since the last call to the helper. You can also pass in an event type to
 filter the results.
 
 ```javascript
-import { render, fireEvent } from '@marko/testing-library'
+import {render, fireEvent} from '@marko/testing-library'
 import Counter from './counter.marko'
 
-const { getByText, emitted } = await render(Counter)
+const {getByText, emitted} = await render(Counter)
 
 const button = getByText('Increment')
 
-fireEvent.click(button)
-fireEvent.click(button)
+await fireEvent.click(button)
+await fireEvent.click(button)
 
 // Assuming the `Counter` component forwards these button clicks as `increment` events
 expect(emitted('increment')).toHaveProperty('length', 2)
 
-fireEvent.click(button)
+await fireEvent.click(button)
 
 // Note: the tracked events are cleared every time you read them.
 // Below we are snapshoting the events after our last assertion,
@@ -204,11 +215,38 @@ expect(emitted()).toMatchInlineSnapshot(`
   `)
 ```
 
+### `cleanup`
+
+Like the [top-level cleanup method](#cleanup-1), this allows you to remove and
+destroy the currently rendered component before the test has been completed.
+
+This can be useful to validate that a component properly cleans up any DOM
+mutations once it has been destroyed.
+
+```javascript
+import {render, screen, getRoles} from '@marko/testing-library'
+import Main from './main.marko'
+import Dialog from './dialog.marko'
+
+await render(Main)
+
+const main = screen.getByRole('main')
+expect(main).not.toHaveAttribute('aria-hidden')
+
+const {cleanup} = await render(Dialog)
+expect(main).toHaveAttribute('aria-hidden') // assert added attribute
+
+cleanup() // destroy the dialog
+
+expect(main).not.toHaveAttribute('aria-hidden') // assert attribute removed
+```
+
 ### `container`
 
-The containing DOM node of your rendered Marko Component. For server side tests
-this is a [JSDOM.fragment](), and for client side tests this will be whatever is
-passed as the `container` render option.
+The containing DOM node of your rendered Marko Component. For server-side tests
+this is a [JSDOM.fragment](https://github.com/jsdom/jsdom#fragment), and for
+client-side tests this will be whatever is passed as the `container` render
+option.
 
 > Tip: To get the root element of your rendered element, use
 > `container.firstChild`.
@@ -218,30 +256,47 @@ passed as the `container` render option.
 > changes that will be made to the component you're testing. Avoid using
 > `container` to query for elements!
 
+## `fireEvent`
+
+Because Marko batches DOM updates to avoid unnecessary re-renders, the
+[fireEvent](dom-testing-library/api-events.mdx) helpers are re-exported as
+`async` functions. Awaiting this ensures that the DOM has properly updated in
+response to the event triggered in the test.
+
+```js
+await fireEvent.click(getByText('Click me'))
+```
+
 ## `cleanup`
 
-With client side tests your components are rendered into a placeholder
+With client-side tests your components are rendered into a placeholder
 HTMLElement. To ensure that your components are properly removed, and destroyed,
-you can call `cleanup` at any time which will remove any attached components.
+after each test the `cleanup` method is called for you automatically by hooking
+into `afterEach` in supported test frameworks. You can also manually call
+`cleanup` at any time which will remove all attached components.
 
 ```javascript
-import { cleanup } from '@marko/testing-library'
-// automatically unmount and cleanup DOM after the test is finished.
-afterEach(cleanup)
-```
+import {render, cleanup, screen} from '@marko/testing-library'
+import Greeting from './greeting.marko'
 
-To save some typing, you could also import a file with the above.
+await render(Greeting, {name: 'Marko'})
 
-```javascript
-import '@marko/testing-library/cleanup-after-each'
+expect(screen.getByText(/Marko/)).toBeInTheDocument()
+
+// manually cleanup the component before the test is finished
+cleanup()
+expect(screen.queryByText(/Marko/)).toBeNull()
 ```
 
-If you are using Jest, you can simply include the following to your Jest config
-to avoid doing this in each file.
+You can turn off the automatic test cleanup by importing the following module:
 
 ```javascript
-module.exports = {
-  ...,
-  setupFilesAfterEnv: ['@marko/testing-library/cleanup-after-each']
-}
+import '@marko/testing-library/dont-cleanup-after-each'
 ```
+
+With mocha you can use
+`mocha --require @marko/testing-library/dont-cleanup-after-each` as a shorthand.
+
+If you are using Jest, you can include
+`setupFilesAfterEnv: ["@marko/testing-library/dont-cleanup-after-each"]` in your
+Jest config to avoid doing this in each file.
diff --git a/docs/marko-testing-library/intro.md b/docs/marko-testing-library/intro.mdx
similarity index 65%
rename from docs/marko-testing-library/intro.md
rename to docs/marko-testing-library/intro.mdx
index c714d2e7b..6ab36a3eb 100644
--- a/docs/marko-testing-library/intro.md
+++ b/docs/marko-testing-library/intro.mdx
@@ -4,25 +4,20 @@ title: Marko Testing Library
 sidebar_label: Introduction
 ---
 
-The [`Marko Testing Library`](gh) is a very lightweight solution for testing
-Marko components. It provides light utility functions on top of
-[`@testing-library/dom`](https://github.com/testing-library/dom-testing-library)
-in a way that encourages better testing practices.
+[`Marko Testing Library`](https://github.com/marko-js/testing-library) builds on
+top of [`DOM Testing Library`](dom-testing-library/intro.mdx) by adding APIs for
+working with Marko components.
 
-```
+```bash npm2yarn
 npm install --save-dev @marko/testing-library
 ```
 
-- [Marko Testing Library on GitHub][gh]
-
-[gh]: https://github.com/marko-js/testing-library
-
 ## The problem
 
 You want to write maintainable tests for your Marko components. As a part of
 this goal, you want your tests to avoid including implementation details of your
 components and rather focus on making your tests give you the confidence for
-which they are intended. As part of this, you want your testbase to be
+which they are intended. As part of this, you want your test suite to be
 maintainable in the long run so refactors of your components (changes to
 implementation but not functionality) don't break your tests and slow you and
 your team down.
@@ -31,18 +26,17 @@ your team down.
 
 The `@marko/testing-library` is a very lightweight solution for testing Marko
 components. It provides light utility functions on top of
-[`@testing-library/dom`](https://github.com/testing-library/dom-testing-library)
-in a way that encourages better testing practices. Its primary guiding principle
-is:
+[`@testing-library/dom`](dom-testing-library/intro.mdx) in a way that encourages
+better testing practices. Its primary guiding principle is:
 
-> [The more your tests resemble the way your software is used, the more confidence they can give you.](guiding-principles.md)
+> [The more your tests resemble the way your software is used, the more confidence they can give you.](guiding-principles.mdx)
 
 So rather than dealing with instances of rendered Marko components, your tests
 will work with actual DOM nodes. The utilities this library provides facilitate
 querying the DOM in the same way the user would. Finding for elements by their
 label text (just like a user would), finding links and buttons from their text
 (like a user would). It contains a small targeted API and can get out of your
-way if absolutely needed with some built in escape hatches.
+way if needed with some built-in escape hatches.
 
 This library encourages your applications to be more accessible and allows you
 to get your tests closer to using your components the way a user will, which
@@ -52,9 +46,9 @@ when a real user uses it.
 **What this library is not**:
 
 1.  A test runner or framework
-2.  Specific to a testing framework, you can [use it with Jest](./setup#jest),
-    [mocha](./setup#mocha), or other test runners.
+2.  Specific to a testing framework, you can [use it with Jest](setup.mdx#jest),
+    [mocha](setup.mdx#mocha), or other test runners.
 
 > NOTE: This library is built on top of
-> [`DOM Testing Library`](dom-testing-library/intro.md) which is where most of
+> [`DOM Testing Library`](dom-testing-library/intro.mdx) which is where most of
 > the logic behind the queries is.
diff --git a/docs/marko-testing-library/setup.md b/docs/marko-testing-library/setup.mdx
similarity index 60%
rename from docs/marko-testing-library/setup.md
rename to docs/marko-testing-library/setup.mdx
index 9dbff69ee..37b74e8dc 100644
--- a/docs/marko-testing-library/setup.md
+++ b/docs/marko-testing-library/setup.mdx
@@ -4,10 +4,10 @@ title: Setup
 sidebar_label: Setup
 ---
 
-`Marko Testing Library` is not dependent on any test runner, however it is
+`Marko Testing Library` is not dependent on any test runner. However, it is
 dependent on the test environment. This package works for testing both server
-side, and client side Marko templates and provide a slightly different
-implementation for each. This is done using a
+side, and client-side Marko templates and provides a slightly different
+implementation optimized for each. This is done using a
 [browser shim](https://github.com/defunctzombie/package-browser-field-spec),
 just like in Marko.
 
@@ -29,52 +29,40 @@ will tell Jest to resolve the
 [browser shim](https://github.com/defunctzombie/package-browser-field-spec)
 version of all modules as mentioned above.
 
-To test components rendered in the client side, be sure to enable both the
+To test components rendered on the client-side, be sure to enable both the
 `browser` option and the preset and you are good to go!
 
-**jest.config.js**
-
-```javascript
+```js title="jest.config.js"
 module.exports = {
-  preset: '@marko/jest',
-  browser: true, // Tells Jest to resolve browser shims.
+  preset: '@marko/jest/preset/browser',
 }
 ```
 
-For testing components rendered server side we can omit the `browser` option,
-however ideally you should also set the
-[`testEnvironment option`](https://jestjs.io/docs/en/configuration#testenvironment-string)
-to `node` which will disable loading JSDOM globally.
-
-**jest.config.js**
+For testing components rendered on the server-side we can instead use
+`@marko/jest/preset/node` as our jest preset.
 
-```javascript
+```js title="jest.config.js"
 module.exports = {
-  preset: '@marko/jest',
-  testEnvironment: 'node', // Tells Jest not to load a global JSDOM for server side.
+  preset: '@marko/jest/preset/node',
 }
 ```
 
 A Jest configuration can also have multiple
 [projects](https://jestjs.io/docs/en/configuration#projects-array-string-projectconfig)
-which we can use to create a combined configuration for server side tests, and
-browser side tests, like so:
-
-**jest.config.js**
+which we can use to create a combined configuration for server-side tests, and
+client-side tests, like so:
 
-```javascript
+```js title="jest.config.js"
 module.exports = {
   projects: [
     {
       displayName: 'server',
-      testEnvironment: 'node',
-      preset: '@marko/jest',
+      preset: '@marko/jest/preset/node',
       testRegex: '/__tests__/[^.]+\\.server\\.js$',
     },
     {
       displayName: 'browser',
-      preset: '@marko/jest',
-      browser: true,
+      preset: '@marko/jest/preset/browser',
       testRegex: '/__tests__/[^.]+\\.browser\\.js$',
     },
   ],
@@ -86,20 +74,20 @@ module.exports = {
 Mocha also works great for testing Marko components. Mocha, however, has no
 understanding of
 [browser shims](https://github.com/defunctzombie/package-browser-field-spec)
-which means out of the box it can only work with server side Marko components.
+which means out of the box it can only work with server-side Marko components.
 
-To run server side Marko tests with `mocha` you can simply run the following
+To run server-side Marko tests with `mocha` you can simply run the following
 command:
 
 ```console
-mocha -r marko/node-require
+mocha --require marko/node-require
 ```
 
 This enables the
 [Marko require hook](https://markojs.com/docs/installing/#require-marko-views)
-and allows you to require server side Marko templates directly in your tests.
+and allows you to require server-side Marko templates directly in your tests.
 
-For client side testing of your components with Mocha often you will use a
+For client-side testing of your components with Mocha often you will use a
 bundler to build your tests (this will properly resolve the browser shims
 mentioned above) and then you can load these tests in some kind of browser
 context.
diff --git a/docs/native-testing-library/api.md b/docs/native-testing-library/api.md
deleted file mode 100644
index 20bf4ab8a..000000000
--- a/docs/native-testing-library/api.md
+++ /dev/null
@@ -1,171 +0,0 @@
----
-id: api
-title: API
-sidebar_label: API
----
-
-Here you'll find a high level summary of the most frequently used parts of
-Native Testing Library. For a more comprehensive look at what's possible, check
-out the [main docs site](https://native-testing-library.com).
-
-- [`render`](#render)
-- [`act`](#act)
-
-## `render`
-
-```typescript
-function render(
-  ui: React.ReactElement,
-  options?: {
-    /* You won't often use this, expand below for docs on options */
-  }
-): RenderResult
-```
-
-Create a `ReactTestRenderer` Instance.
-
-```jsx
-import { render } from '@testing-library/react-native'
-
-render(Hello, World! )
-  expect(getByText('Hello, world!')).toBeTruthy()
-  expect(container.toJSON()).toMatchInlineSnapshot(`
-    Hello, World! 
-  `)
-})
-```
-
-## `render` Options
-
-Most of the time you won't need to pass any options to `render`, but when you
-do, you will pass them as the second parameter. There are some important key
-differences between this and `React Testing Library` that you will want to be
-aware of.
-
-### `wrapper`
-
-Pass a React Component as the `wrapper` option to have it rendered around the
-inner element. This is most useful for creating reusable custom render functions
-for common data providers. See [setup](setup.md#custom-render) for examples.
-
-### `queries`
-
-Queries to bind. Overrides the default set from `Native Testing Library` unless
-merged.
-
-```js
-// Example, a function to traverse table contents
-import * as tableQueries from 'my-table-query-libary'
-import queries from '@testing-library/react-native'
-
-const { getByRowColumn, getByText } = render(
-    Hello World 
-   
-)
-debug()
-// 
-//   
-//     Hello World
-//    
-//  
-```
-
-This is a simple wrapper around `prettyPrint` which is also exported.
-
-### `rerender`
-
-Although its likely better to test updating your props the way a user would
-(through events and interaction), this method will allow you to re-render your
-entire tree at the base with new props.
-
-```jsx
-import { render } from '@testing-library/react-native'
-
-const { rerender } = render( setCount(count + 1)}>{count} 
+}
+
+const {
+  container: {firstChild: buttonNode},
+} = render(
+      Show Message 
+      
+  )
+}
+```
+
+## Test
+
+```jsx
+// NOTE: jest-dom adds handy assertions to Jest and it is recommended, but not required.
+import '@testing-library/jest-dom'
+
+import {h} from 'preact'
+import {render, fireEvent} from '@testing-library/preact'
+
+import HiddenMessage from '../hidden-message'
+
+test('shows the children when the checkbox is checked', () => {
+  const testMessage = 'Test Message'
+
+  const {queryByText, getByLabelText, getByText} = render(
+    {testMessage} ,
+  )
+
+  // query* functions will return the element or null if it cannot be found.
+  // get* functions will return the element or throw an error if it cannot be found.
+  expect(queryByText(testMessage)).toBeNull()
+
+  // The queries can accept a regex to make your selectors more resilient to content tweaks and changes.
+  fireEvent.click(getByLabelText(/show/i))
+
+  // .toBeInTheDocument() is an assertion that comes from jest-dom.
+  // Otherwise you could use .toBeDefined().
+  expect(getByText(testMessage)).toBeInTheDocument()
+})
+```
diff --git a/docs/preact-testing-library/intro.mdx b/docs/preact-testing-library/intro.mdx
new file mode 100644
index 000000000..dfda61344
--- /dev/null
+++ b/docs/preact-testing-library/intro.mdx
@@ -0,0 +1,46 @@
+---
+id: intro
+title: Intro
+sidebar_label: Introduction
+---
+
+[Preact Testing Library on GitHub][gh]
+
+[gh]: https://github.com/testing-library/preact-testing-library
+
+```bash npm2yarn
+npm install --save-dev @testing-library/preact
+```
+
+> This library is built on top of
+> [`DOM Testing Library`](dom-testing-library/intro.mdx) which is where most of
+> the logic behind the queries is.
+
+## The Problem
+
+You want to write tests for your Preact components so that they avoid including
+implementation details, and are maintainable in the long run.
+
+## This Solution
+
+The Preact Testing Library is a very lightweight solution for testing Preact
+components. It provides light utility functions on top of `preact/test-utils`,
+in a way that encourages better testing practices. Its primary guiding principle
+is:
+
+> [The more your tests resemble the way your software is used, the more confidence they can give you.](https://twitter.com/kentcdodds/status/977018512689455106)
+
+See the [Dom introduction][dom-solution-explainer] and [React
+introduction][react-solution-explainer] for a more in-depth explanation.
+
+[dom-solution-explainer]: ../dom-testing-library/intro.mdx#this-solution
+[react-solution-explainer]: ../react-testing-library/intro.mdx#this-solution
+
+**What this library is not**:
+
+1.  A test runner or framework.
+2.  Specific to a testing framework.
+
+We recommend Jest as our preference. You can checkout
+[Using Without Jest](react-testing-library/setup.mdx#using-without-jest) if
+you're looking to use another framework.
diff --git a/docs/preact-testing-library/learn.mdx b/docs/preact-testing-library/learn.mdx
new file mode 100644
index 000000000..f16af57c9
--- /dev/null
+++ b/docs/preact-testing-library/learn.mdx
@@ -0,0 +1,33 @@
+---
+id: learn
+title: Learn
+sidebar_label: Learn
+---
+
+Due to the similarities between React and Preact (including the testing
+libraries), you should be able to comfortably use any React based examples,
+docs, answers on stack overflow etc.
+
+Take note of the
+[differences between React and Preact](https://preactjs.com/guide/v10/differences-to-react).
+
+If you're still hungry for more at this point than checkout:
+
+- The dom-testing-library:
+  - [Introduction](intro.mdx)
+  - [Queries](queries/about.mdx)
+  - [Firing Events](dom-testing-library/api-events.mdx)
+  - [Async Utilities](dom-testing-library/api-async.mdx)
+  - [Helpers](dom-testing-library/api-custom-queries.mdx)
+  - [FAQ](dom-testing-library/faq.mdx)
+- The react-testing-library:
+  - [API](react-testing-library/api.mdx)
+  - [Example](react-testing-library/example-intro.mdx)
+  - [Migrate from Enzyme](react-testing-library/migrate-from-enzyme.mdx)
+  - [Sandbox](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples)
+  - [FAQ](react-testing-library/faq.mdx)
+- This YouTube video by LevelUpTuts called
+  [What is React Testing Library?](https://youtu.be/JKOwJUM4_RM)
+- Extending Jest with
+  [custom matchers](https://github.com/testing-library/jest-dom) to test the
+  state of the DOM.
diff --git a/docs/queries/about.mdx b/docs/queries/about.mdx
new file mode 100644
index 000000000..53de0b1f0
--- /dev/null
+++ b/docs/queries/about.mdx
@@ -0,0 +1,402 @@
+---
+id: about
+title: About Queries
+---
+
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+## Overview
+
+Queries are the methods that Testing Library gives you to find elements on the
+page. There are several [types of queries](#types-of-queries) ("get", "find",
+"query"); the difference between them is whether the query will throw an error
+if no element is found or if it will return a Promise and retry. Depending on
+what page content you are selecting, different queries may be more or less
+appropriate. See the [priority guide](#priority) for recommendations on how to
+make use of semantic queries to test your page in the most accessible way.
+
+After selecting an element, you can use the
+[Events API](dom-testing-library/api-events.mdx) or
+[user-event](user-event/intro.mdx) to fire events and simulate user interactions
+with the page, or use Jest and [jest-dom](ecosystem-jest-dom.mdx) to make
+assertions about the element.
+
+There are Testing Library helper methods that work with queries. As elements
+appear and disappear in response to actions,
+[Async APIs](dom-testing-library/api-async.mdx) like
+[`waitFor`](dom-testing-library/api-async.mdx#waitfor) or
+[`findBy` queries](dom-testing-library/api-async.mdx#findby-queries) can be used
+to await the changes in the DOM. To find only elements that are children of a
+specific element, you can use [`within`](dom-testing-library/api-within.mdx). If
+necessary, there are also a few options you can
+[configure](dom-testing-library/api-configuration.mdx), like the timeout for
+retries and the default testID attribute.
+
+## Example
+
+```jsx
+import {render, screen} from '@testing-library/react' // (or /dom, /vue, ...)
+
+test('should show login form', () => {
+  render(
+
+Summary Table 
+
+ 
+
+## Priority
+
+Based on [the Guiding Principles](guiding-principles.mdx), your test should
+resemble how users interact with your code (component, page, etc.) as much as
+possible. With this in mind, we recommend this order of priority:
+
+1. **Queries Accessible to Everyone** Queries that reflect the experience of
+   visual/mouse users as well as those that use assistive technology.
+   1. `getByRole`: This can be used to query every element that is exposed in
+      the
+      [accessibility tree](https://developer.mozilla.org/en-US/docs/Glossary/AOM).
+      With the `name` option you can filter the returned elements by their
+      [accessible name](https://www.w3.org/TR/accname-1.1/). This should be your
+      top preference for just about everything. There's not much you can't get
+      with this (if you can't, it's possible your UI is inaccessible). Most
+      often, this will be used with the `name` option like so:
+      `getByRole('button', {name: /submit/i})`. Check the
+      [list of roles](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques#Roles).
+   1. `getByLabelText`: This method is really good for form fields. When
+      navigating through a website form, users find elements using label text.
+      This method emulates that behavior, so it should be your top preference.
+   1. `getByPlaceholderText`:
+      [A placeholder is not a substitute for a label](https://www.nngroup.com/articles/form-design-placeholders/).
+      But if that's all you have, then it's better than alternatives.
+   1. `getByText`: Outside of forms, text content is the main way users find
+      elements. This method can be used to find non-interactive elements (like
+      divs, spans, and paragraphs).
+   1. `getByDisplayValue`: The current value of a form element can be useful
+      when navigating a page with filled-in values.
+1. **Semantic Queries** HTML5 and ARIA compliant selectors. Note that the user
+   experience of interacting with these attributes varies greatly across
+   browsers and assistive technology.
+   1. `getByAltText`: If your element is one which supports `alt` text (`img`,
+      `area`, `input`, and any custom element), then you can use this to find
+      that element.
+   1. `getByTitle`: The title attribute is not consistently read by
+      screenreaders, and is not visible by default for sighted users
+1. **Test IDs**
+   1. `getByTestId`: The user cannot see (or hear) these, so this is only
+      recommended for cases where you can't match by role or text or it doesn't
+      make sense (e.g. the text is dynamic).
+
+## Using Queries
+
+The base queries from DOM Testing Library require you to pass a `container` as
+the first argument. Most framework-implementations of Testing Library provide a
+pre-bound version of these queries when you render your components with them
+which means you _do not have to provide a container_. In addition, if you just
+want to query `document.body` then you can use the [`screen`](#screen) export as
+demonstrated below (using `screen` is recommended).
+
+The primary argument to a query can be a _string_, _regular expression_, or
+_function_. There are also options to adjust how node text is parsed. See
+[TextMatch](#textmatch) for documentation on what can be passed to a query.
+
+Given the following DOM elements (which can be rendered by React, Vue, Angular,
+or plain HTML code):
+
+```js
+
+  
+    Username 
+    
+
+```
+
+You can use a query to find an element (byLabelText, in this case):
+
+```js
+import {screen, getByLabelText} from '@testing-library/dom'
+
+// With screen:
+const inputNode1 = screen.getByLabelText('Username')
+
+// Without screen, you need to provide a container:
+const container = document.querySelector('#app')
+const inputNode2 = getByLabelText(container, 'Username')
+```
+
+### `queryOptions`
+
+You can pass a `queryOptions` object with the query type. See the docs for each
+query type to see available options, e.g. [byRole API](queries/byrole.mdx#api).
+
+### `screen`
+
+All of the queries exported by DOM Testing Library accept a `container` as the
+first argument. Because querying the entire `document.body` is very common, DOM
+Testing Library also exports a `screen` object which has every query that is
+pre-bound to `document.body` (using the
+[`within`](dom-testing-library/api-within.mdx) functionality). Wrappers such as
+React Testing Library re-export `screen` so you can use it the same way.
+
+Here's how you use it:
+
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+document.body.innerHTML = `
+  Example 
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render(
+  
+    Example 
+    
,
+)
+
+const exampleInput = screen.getByLabelText('Example')
+```
+
+   
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(`
+  
+    Example 
+    
+`)
+
+const exampleInput = screen.getByLabelText('Example')
+```
+
+   
+  
+
+```js
+cy.findByLabelText('Example').should('exist')
+```
+
+   
+   
+
+> **Note**
+>
+> You need a global DOM environment to use `screen`. If you're using jest, with
+> the
+> [testEnvironment](https://jestjs.io/docs/en/configuration#testenvironment-string)
+> set to `jsdom`, a global DOM environment will be available for you.
+>
+> If you're loading your test with a `script` tag, make sure it comes after the
+> `body`. An example can be seen
+> [here](https://github.com/testing-library/dom-testing-library/issues/700#issuecomment-692218886).
+
+## `TextMatch`
+
+Most of the query APIs take a `TextMatch` as an argument, which means the
+argument can be either a _string_, _regex_, or a _function_ of signature
+`(content?: string, element?: Element | null) => boolean` which returns `true`
+for a match and `false` for a mismatch.
+
+### TextMatch Examples
+
+Given the following HTML:
+
+```html
+Hello World
+```
+
+**_Will_ find the div:**
+
+```javascript
+// Matching a string:
+screen.getByText('Hello World') // full string match
+screen.getByText('llo Worl', {exact: false}) // substring match
+screen.getByText('hello world', {exact: false}) // ignore case
+
+// Matching a regex:
+screen.getByText(/World/) // substring match
+screen.getByText(/world/i) // substring match, ignore case
+screen.getByText(/^hello world$/i) // full string match, ignore case
+screen.getByText(/Hello W?oRlD/i) // substring match, ignore case, searches for "hello world" or "hello orld"
+
+// Matching with a custom function:
+screen.getByText((content, element) => content.startsWith('Hello'))
+```
+
+**_Will not_ find the div:**
+
+```javascript
+// full string does not match
+screen.getByText('Goodbye World')
+
+// case-sensitive regex with different case
+screen.getByText(/hello world/)
+
+// function looking for a span when it's actually a div:
+screen.getByText((content, element) => {
+  return element.tagName.toLowerCase() === 'span' && content.startsWith('Hello')
+})
+```
+
+### Precision
+
+Queries that take a `TextMatch` also accept an object as the final argument that
+can contain options that affect the precision of string matching:
+
+- `exact`: Defaults to `true`; matches full strings, case-sensitive. When false,
+  matches substrings and is not case-sensitive.
+  - it has no effect when used together with `regex` or `function` arguments.
+  - in most cases, using a regex instead of a string combined with `{ exact: false }`
+    gives you more control over fuzzy matching so it should be preferred.
+- `normalizer`: An optional function which overrides normalization behavior. See
+  [`Normalization`](#normalization).
+
+### Normalization
+
+Before running any matching logic against text in the DOM, `DOM Testing Library`
+automatically normalizes that text. By default, normalization consists of
+trimming whitespace from the start and end of text, and **collapsing multiple
+adjacent whitespace characters within the string into a single space**.
+
+If you want to prevent that normalization, or provide alternative normalization
+(e.g. to remove Unicode control characters), you can provide a `normalizer`
+function in the options object. This function will be given a string and is
+expected to return a normalized version of that string.
+
+> **Note**
+>
+> Specifying a value for `normalizer` _replaces_ the built-in normalization, but
+> you can call `getDefaultNormalizer` to obtain a built-in normalizer, either to
+> adjust that normalization or to call it from your own normalizer.
+
+`getDefaultNormalizer` takes an options object which allows the selection of
+behaviour:
+
+- `trim`: Defaults to `true`. Trims leading and trailing whitespace
+- `collapseWhitespace`: Defaults to `true`. Collapses inner whitespace
+  (newlines, tabs, repeated spaces) into a single space.
+
+#### Normalization Examples
+
+To perform a match against text without trimming:
+
+```javascript
+screen.getByText('text', {
+  normalizer: getDefaultNormalizer({trim: false}),
+})
+```
+
+To override normalization to remove some Unicode characters whilst keeping some
+(but not all) of the built-in normalization behavior:
+
+```javascript
+screen.getByText('text', {
+  normalizer: str =>
+    getDefaultNormalizer({trim: false})(str).replace(/[\u200E-\u200F]*/g, ''),
+})
+```
+
+## Manual Queries
+
+On top of the queries provided by the testing library, you can use the regular
+[`querySelector` DOM API](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
+to query elements. Note that using this as an escape hatch to query by class or
+id is not recommended because they are invisible to the user. Use a testid if
+you have to, to make your intention to fall back to non-semantic queries clear
+and establish a stable API contract in the HTML.
+
+```jsx
+// @testing-library/react
+const {container} = render(`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/applet)
+as it's deprecated).
+
+```html
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+const incrediblesPosterImg = screen.getByAltText(/incredibles.*? poster/i)
+```
+
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render( 
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(MyComponent)
+const incrediblesPosterImg = screen.getByAltText(/incredibles.*? poster/i)
+```
+
+   
+  
+
+```js
+cy.findByAltText(/incredibles.*? poster/i).should('exist')
+```
+
+   
+   
+
+## Options
+
+[TextMatch](queries/about.mdx#textmatch) options
diff --git a/docs/queries/bydisplayvalue.mdx b/docs/queries/bydisplayvalue.mdx
new file mode 100644
index 000000000..519af79db
--- /dev/null
+++ b/docs/queries/bydisplayvalue.mdx
@@ -0,0 +1,205 @@
+---
+id: bydisplayvalue
+title: ByDisplayValue
+---
+
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+> getByDisplayValue, queryByDisplayValue, getAllByDisplayValue,
+> queryAllByDisplayValue, findByDisplayValue, findAllByDisplayValue
+
+## API
+
+```typescript
+getByDisplayValue(
+  // If you're using `screen`, then skip the container argument:
+  container: HTMLElement,
+  value: TextMatch,
+  options?: {
+    exact?: boolean = true,
+    normalizer?: NormalizerFn,
+  }): HTMLElement
+```
+
+Returns the `input`, `textarea`, or `select` element that has the matching
+display value.
+
+### `input` tags
+
+```html
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+const lastNameInput = screen.getByDisplayValue('Norris')
+```
+
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render( 
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(MyComponent)
+const lastNameInput = screen.getByDisplayValue('Norris')
+```
+
+   
+  
+
+```js
+cy.findByDisplayValue('Norris').should('exist')
+```
+
+   
+   
+
+### `textarea` tags
+
+```html
+
+```
+
+```js
+document.getElementById('messageTextArea').value = 'Hello World'
+```
+
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+const messageTextArea = screen.getByDisplayValue('Hello World')
+```
+
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render( 
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(MyComponent)
+const messageTextArea = screen.getByDisplayValue('Hello World')
+```
+
+   
+  
+
+```js
+cy.findByDisplayValue('Hello World').should('exist')
+```
+
+   
+   
+
+### `select` tags
+
+In case of `select`, this will search for a `` whose selected ``
+matches the given [`TextMatch`](queries/about.mdx#textmatch).
+
+```html
+
+  State 
+  Alabama 
+  Alaska 
+  Arizona 
+ 
+```
+
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+const selectElement = screen.getByDisplayValue('Alaska')
+```
+
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render( 
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(MyComponent)
+const selectElement = screen.getByDisplayValue('Alaska')
+```
+
+   
+  
+
+```js
+cy.findByDisplayValue('Alaska').should('exist')
+```
+
+   
+   
+
+## Options
+
+[TextMatch](queries/about.mdx#textmatch) options
diff --git a/docs/queries/bylabeltext.mdx b/docs/queries/bylabeltext.mdx
new file mode 100644
index 000000000..e532f50d7
--- /dev/null
+++ b/docs/queries/bylabeltext.mdx
@@ -0,0 +1,150 @@
+---
+id: bylabeltext
+title: ByLabelText
+---
+
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+> getByLabelText, queryByLabelText, getAllByLabelText, queryAllByLabelText,
+> findByLabelText, findAllByLabelText
+
+## API
+
+```typescript
+getByLabelText(
+  // If you're using `screen`, then skip the container argument:
+  container: HTMLElement,
+  text: TextMatch,
+  options?: {
+    selector?: string = '*',
+    exact?: boolean = true,
+    normalizer?: NormalizerFn,
+  }): HTMLElement
+```
+
+This will search for the label that matches the given
+[`TextMatch`](queries/about.mdx#textmatch), then find the element associated
+with that label.
+
+The example below will find the input node for the following DOM structures:
+
+```js
+// for/htmlFor relationship between label and form element id
+Username 
+Username 
+Username  
+
+// Wrapper labels where the label text is in another child element
+
+  Username 
+   
+
+// aria-label attributes
+// Take care because this is not a label that users can see on the page,
+// so the purpose of your input must be obvious to visual users.
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+const inputNode = screen.getByLabelText('Username')
+```
+
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render( 
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(Login)
+
+const inputNode = screen.getByLabelText('Username')
+```
+
+   
+  
+
+```js
+cy.findByLabelText('Username').should('exist')
+```
+
+   
+   
+
+## Options
+
+### `name`
+
+The example above does NOT find the input node for label text broken up by
+elements. You can use `getByRole('textbox', { name: 'Username' })` instead which
+is robust against switching to `aria-label` or `aria-labelledby`.
+
+### `selector`
+
+If it is important that you query a specific element (e.g. an `Username 
+Please enter your username 
+
+// Multiple labels with the same text
+
+  Username
+   
+
+  Username
+  
+ 
+```
+
+```js
+const inputNode = screen.getByLabelText('Username', {selector: 'input'})
+```
+
+> **Note**
+>
+> `getByLabelText` will not work in the case where a `for` attribute on a
+> `` element matches an `id` attribute on a non-form element.
+
+```js
+// This case is not valid
+// for/htmlFor between label and an element that is not a form element
+
+```
diff --git a/docs/queries/byplaceholdertext.mdx b/docs/queries/byplaceholdertext.mdx
new file mode 100644
index 000000000..d70f847b2
--- /dev/null
+++ b/docs/queries/byplaceholdertext.mdx
@@ -0,0 +1,86 @@
+---
+id: byplaceholdertext
+title: ByPlaceholderText
+---
+
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+> getByPlaceholderText, queryByPlaceholderText, getAllByPlaceholderText,
+> queryAllByPlaceholderText, findByPlaceholderText, findAllByPlaceholderText
+
+## API
+
+```typescript
+getByPlaceholderText(
+  // If you're using `screen`, then skip the container argument:
+  container: HTMLElement,
+  text: TextMatch,
+  options?: {
+    exact?: boolean = true,
+    normalizer?: NormalizerFn,
+  }): HTMLElement
+```
+
+This will search for all elements with a placeholder attribute and find one that
+matches the given [`TextMatch`](queries/about.mdx#textmatch).
+
+```html
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+const inputNode = screen.getByPlaceholderText('Username')
+```
+
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render( 
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(MyComponent)
+const inputNode = screen.getByPlaceholderText('Username')
+```
+
+   
+  
+
+```js
+cy.findByPlaceholderText('Username').should('exist')
+```
+
+   
+   
+
+> **Note**
+>
+> A placeholder is not a good substitute for a label so you should generally use
+> `getByLabelText` instead.
+
+## Options
+
+[TextMatch](queries/about.mdx#textmatch) options
diff --git a/docs/queries/byrole.mdx b/docs/queries/byrole.mdx
new file mode 100644
index 000000000..53ecd33be
--- /dev/null
+++ b/docs/queries/byrole.mdx
@@ -0,0 +1,489 @@
+---
+id: byrole
+title: ByRole
+---
+
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+> getByRole, queryByRole, getAllByRole, queryAllByRole, findByRole,
+> findAllByRole
+
+## API
+
+```typescript
+getByRole(
+  // If you're using `screen`, then skip the container argument:
+  container: HTMLElement,
+  role: string,
+  options?: {
+    hidden?: boolean = false,
+    name?: TextMatch,
+    description?: TextMatch,
+    selected?: boolean,
+    busy?: boolean,
+    checked?: boolean,
+    pressed?: boolean,
+    suggest?: boolean,
+    current?: boolean | string,
+    expanded?: boolean,
+    queryFallbacks?: boolean,
+    level?: number,
+    value?: {
+      min?: number,
+      max?: number,
+      now?: number,
+      text?: TextMatch,
+    }
+  }): HTMLElement
+```
+
+Queries for elements with the given role (and it also accepts a
+[`TextMatch`](queries/about.mdx#textmatch)). Default roles are taken into
+consideration e.g. `
+    Open dialog 
+   
+  
+    Close dialog 
+  
+
+```
+
+`getByRole('button')` would only return the `Close dialog`-button. To make
+assertions about the `Open dialog`-button you would need to use
+`getAllByRole('button', { hidden: true })`.
+
+The default value for `hidden` can
+[be configured](../dom-testing-library/api-configuration.mdx#configuration).
+
+### `selected`
+
+You can filter the returned elements by their selected state by setting
+`selected: true` or `selected: false`.
+
+For example in
+
+```html
+
+  
+    Native 
+    React 
+    Cypress 
+  
+
+```
+
+you can get the "Native"-tab by calling `getByRole('tab', { selected: true })`.
+To learn more about the selected state and which elements can have this state
+see [ARIA `aria-selected`](https://www.w3.org/TR/wai-aria-1.2/#aria-selected).
+
+### `busy`
+
+You can filter the returned elements by their busy state by setting `busy: true`
+or `busy: false`.
+
+For example in
+
+```html
+
+  
+    Login failed
+    Error: Loading message...
+   
+
+```
+
+you can get the "Login failed" alert by calling
+`getByRole('alert', { busy: false })`. To learn more about the busy state see
+[ARIA `aria-busy`](https://www.w3.org/TR/wai-aria-1.2/#aria-busy) and
+[MDN `aria-busy` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-busy).
+
+### `checked`
+
+You can filter the returned elements by their checked state by setting
+`checked: true` or `checked: false`.
+
+For example in
+
+```html
+
+  
+    Sugar 
+    Gummy bears 
+    Whipped cream 
+   
+
+```
+
+you can get the "Sugar" option by calling
+`getByRole('checkbox', { checked: true })`. To learn more about the checked
+state and which elements can have this state see
+[ARIA `aria-checked`](https://www.w3.org/TR/wai-aria-1.2/#aria-checked).
+
+> **Note**
+>
+> Checkboxes have a "mixed" state, which is considered neither checked nor
+> unchecked (details [here](https://www.w3.org/TR/html-aam-1.0/#details-id-56)).
+
+### `current`
+
+You can filter the returned elements by their current state by setting
+`current: boolean | string`. Note that no `aria-current` attribute will match
+`current: false` since `false` is the default value for `aria-current`.
+
+For example in
+
+```html
+
+  
+    👍 
+    👎 
+   
+
+```
+
+you can get the "👍" link by calling `getByRole('link', { current: 'page' })`
+and the "👎" by calling `getByRole('link', { current: false })`. To learn more
+about the current state see
+[ARIA `aria-current`](https://www.w3.org/TR/wai-aria-1.2/#aria-current).
+
+### `pressed`
+
+Buttons can have a pressed state. You can filter the returned elements by their
+pressed state by setting `pressed: true` or `pressed: false`.
+
+For example in
+
+```html
+
+  
+
+```
+
+you can get the "👍" button by calling `getByRole('button', { pressed: true })`.
+To learn more about the pressed state see
+[ARIA `aria-pressed`](https://www.w3.org/TR/wai-aria-1.2/#aria-pressed).
+
+### `suggest`
+
+You can disable the ability to
+[throw suggestions](../dom-testing-library/api-configuration.mdx#throwsuggestions-experimental)
+for a specific query by setting this value to `false`.  
+Setting this value to `true` will throw suggestions for the specific query.
+
+### `expanded`
+
+You can filter the returned elements by their expanded state by setting
+`expanded: true` or `expanded: false`.
+
+For example in
+
+```html
+
+  
+    
+   
+
+```
+
+you can get the "Expandable Menu Item" link by calling
+`getByRole('link', { expanded: false })`. To learn more about the expanded state
+and which elements can have this state see
+[ARIA `aria-expanded`](https://www.w3.org/TR/wai-aria-1.2/#aria-expanded).
+
+```html
+...
+```
+
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+const dialogContainer = screen.getByRole('dialog')
+```
+
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render( 
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(MyComponent)
+const dialogContainer = screen.getByRole('dialog')
+```
+
+   
+  
+
+```js
+cy.findByRole('dialog').should('exist')
+```
+
+   
+   
+
+### `queryFallbacks`
+
+By default, it's assumed that the first role of each element is supported, so
+only the first role can be queried. If you need to query an element by any of
+its fallback roles instead, you can use `queryFallbacks: true`.
+
+For example, `getByRole('switch')` would always match
+`
` because it's the first role, while
+`getByRole('checkbox')` would not. However,
+`getByRole('checkbox', { queryFallbacks: true })` would enable all fallback
+roles and therefore match the same element.
+
+> An element doesn't have multiple roles in a given environment. It has a single
+> one. Multiple roles in the attribute are evaluated from left to right until
+> the environment finds the first role it understands. This is useful when new
+> roles get introduced and you want to start supporting those as well as older
+> environments that don't understand that role (yet).
+
+### `level`
+
+An element with the `heading` role can be queried by any heading level
+`getByRole('heading')` or by a specific heading level using the `level` option
+`getByRole('heading', { level: 2 })`.
+
+The `level` option queries the element(s) with the `heading` role matching the
+indicated level determined by the semantic HTML heading elements `-` or
+matching the `aria-level` attribute.
+
+Given the example below,
+
+```html
+
+  
+    Heading Level One 
+    First Heading Level Two 
+    Heading Level Three 
+    Second Heading Level Two
+   
+
+```
+
+you can query the `Heading Level Three` heading using
+`getByRole('heading', { level: 3 })`.
+
+```js
+getByRole('heading', {level: 1})
+// Heading Level One 
+
+getAllByRole('heading', {level: 2})
+// [
+//   First Heading Level Two ,
+//     Second Heading Level Two
+// ]
+```
+
+While it is possible to explicitly set `role="heading"` and `aria-level`
+attribute on an element, it is **strongly encouraged** to use the semantic HTML
+headings `-`.
+
+To learn more about the `aria-level` property, see
+[ARIA `aria-level`](https://www.w3.org/TR/wai-aria-1.2/#aria-level).
+
+> The `level` option is _only_ applicable to the `heading` role. An error will
+> be thrown when used with any other role.
+
+### `value`
+
+A range widget can be queried by any value `getByRole('spinbutton')` or by a
+specific value using the `level` option
+`getByRole('spinbutton', { value: { now: 5, min: 0, max: 10, text: 'medium' } })`.
+
+Note that you don't have to specify all properties in `value`. A subset is
+sufficient e.g.
+`getByRole('spinbutton', { value: { now: 5, text: 'medium' } })`.
+
+Given the example below,
+
+```html
+
+  
+    
+      Volume
+     
+    
+      Pitch
+     
+   
+
+```
+
+you can query specific spinbutton(s) with the following queries,
+
+```js
+getByRole('spinbutton', {value: {now: 5}})
+// Volume 
+
+getAllByRole('spinbutton', {value: {min: 0}})
+// [
+//   Volume ,
+//   Pitch 
+// ]
+```
+
+> Every specified property in `value` must match. For example, if you query for
+> `{value: {min: 0, now: 3}}` `aria-valuemin` must be equal to 0 **AND** >
+> `aria-valuenow` must be equal to 3
+
+> The `value` option is _only_ applicable to certain roles (check the linked MDN
+> pages below for applicable roles). An error will be thrown when used with any
+> other role.
+
+To learn more about the `aria-value*` properties, see
+[MDN `aria-valuemin`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuemin),
+[MDN `aria-valuemax`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuemax),
+[MDN `aria-valuenow`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuenow),
+[MDN `aria-valuetext`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuetext).
+
+### `description`
+
+You can filter the returned elements by their
+[accessible description](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_description)
+for those cases where you have several elements with the same role and they
+don't have an accessible name but they do have a description.  
+```
+
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+const element = screen.getByTestId('custom-element')
+```
+
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render( 
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(MyComponent)
+const element = screen.getByTestId('custom-element')
+```
+
+   
+  
+
+```js
+cy.findByTestId('custom-element').should('exist')
+```
+
+   
+   
+
+> In the spirit of [the guiding principles](guiding-principles.mdx), it is
+> recommended to use this only after the other queries don't work for your use
+> case. Using data-testid attributes do not resemble how your software is used
+> and should be avoided if possible. That said, they are _way_ better than
+> querying based on DOM structure or styling css class names. Learn more about
+> `data-testid`s from the blog post
+> ["Making your UI tests resilient to change"](https://kentcdodds.com/blog/making-your-ui-tests-resilient-to-change)
+
+## Options
+
+[TextMatch](queries/about.mdx#textmatch) options
+
+## Overriding `data-testid`
+
+The `...ByTestId` functions in `DOM Testing Library` use the attribute
+`data-testid` by default, following the precedent set by
+[React Native Web](https://github.com/testing-library/react-testing-library/issues/1)
+which uses a `testID` prop to emit a `data-testid` attribute on the element, and
+we recommend you adopt that attribute where possible. But if you already have an
+existing codebase that uses a different attribute for this purpose, you can
+override this value via
+`configure({testIdAttribute: 'data-my-test-attribute'})`.
diff --git a/docs/queries/bytext.mdx b/docs/queries/bytext.mdx
new file mode 100644
index 000000000..7c754764f
--- /dev/null
+++ b/docs/queries/bytext.mdx
@@ -0,0 +1,107 @@
+---
+id: bytext
+title: ByText
+---
+
+import Tabs from '@theme/Tabs'
+import TabItem from '@theme/TabItem'
+
+> getByText, queryByText, getAllByText, queryAllByText, findByText,
+> findAllByText
+
+## API
+
+```typescript
+getByText(
+  // If you're using `screen`, then skip the container argument:
+  container: HTMLElement,
+  text: TextMatch,
+  options?: {
+    selector?: string = '*',
+    exact?: boolean = true,
+    ignore?: string|boolean = 'script, style',
+    normalizer?: NormalizerFn,
+  }): HTMLElement
+```
+
+This will search for all elements that have a text node with `textContent`
+matching the given [`TextMatch`](queries/about.mdx#textmatch).
+
+```html
+About ℹ️ 
+```
+
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+const aboutAnchorNode = screen.getByText(/about/i)
+```
+
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render( 
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(MyComponent)
+const aboutAnchorNode = screen.getByText(/about/i)
+```
+
+   
+  
+
+```js
+cy.findByText(/about/i).should('exist')
+```
+
+   
+   
+
+It also works with `input`s whose `type` attribute is either `submit` or
+`button`:
+
+```js
+
+  Close 
+   
+```
+
+
+
+
+```js
+import {screen} from '@testing-library/dom'
+
+const deleteElement = screen.getByTitle('Delete')
+const closeElement = screen.getByTitle('Close')
+```
+
+   
+  
+
+```jsx
+import {render, screen} from '@testing-library/react'
+
+render( 
+  
+
+```ts
+import {render, screen} from '@testing-library/angular'
+
+await render(MyComponent)
+const deleteElement = screen.getByTitle('Delete')
+const closeElement = screen.getByTitle('Close')
+```
+
+   
+  
+
+```js
+cy.findByTitle('Delete').should('exist')
+cy.findByTitle('Close').should('exist')
+```
+
+   
+   
+
+## Options
+
+[TextMatch](queries/about.mdx#textmatch) options
diff --git a/docs/qwik-testing-library/api.mdx b/docs/qwik-testing-library/api.mdx
new file mode 100644
index 000000000..09edcce59
--- /dev/null
+++ b/docs/qwik-testing-library/api.mdx
@@ -0,0 +1,203 @@
+---
+id: api
+title: API
+sidebar_label: API
+---
+
+`@noma.to/qwik-testing-library` re-exports everything from
+[`@testing-library/dom`][@testing-library/dom], as well as:
+
+- [`render`](#render)
+- [`cleanup`](#cleanup)
+
+[@testing-library/dom]: ../dom-testing-library/api.mdx
+
+## `render`
+
+Render your component to the DOM with Qwik. By default, when no options are
+provided, the component will be rendered into a `` appended to
+`document.body`.
+
+```tsx
+import {render} from '@noma.to/qwik-testing-library'
+import {MockProvider} from './MockProvider'
+import {MyComponent} from './MyComponent'
+
+const result = await render( (count.value++))}>
+      Click to increase: {count}
+     
+  )
+});
+
+const {getByText, asFragment} = await render( {
+  // get the latest posts
+  return Promise.resolve([])
+})
+```
+
+```tsx title="~/components/latest-post-list.tsx"
+import {render, screen, waitFor} from '@noma.to/qwik-testing-library'
+import {LatestPostList} from './latest-post-list'
+
+vi.mock('~/server/blog-posts', () => ({
+  // the mocked function should end with `Qrl` instead of `$`
+  getLatestPostsQrl: () => {
+    return Promise.resolve([
+      {id: 'post-1', title: 'Post 1'},
+      {id: 'post-2', title: 'Post 2'},
+    ])
+  },
+}))
+
+describe('
       
@@ -53,13 +43,13 @@ const AllTheProviders = ({ children }) => {
 }
 
 const customRender = (ui, options) =>
-  render(ui, { wrapper: AllTheProviders, ...options })
+  render(ui, {wrapper: AllTheProviders, ...options})
 
 // re-export everything
 export * from '@testing-library/react-native'
 
 // override render method
-export { customRender as render }
+export {customRender as render}
 ```
 
 ### Configuring Jest with Test Utils
@@ -71,14 +61,12 @@ Jest `moduleDirectories` option.
 This will make all the `.js` files in the test-utils directory importable
 without `../`.
 
-```diff
-// my-component.test.js
+```diff title="my-component.test.js"
 - import { render, fireEvent } from '../test-utils';
 + import { render, fireEvent } from 'test-utils';
 ```
 
-```diff
-// jest.config.js
+```diff title="jest.config.js"
 module.exports = {
   moduleDirectories: [
     'node_modules',
diff --git a/docs/react-testing-library/api.md b/docs/react-testing-library/api.md
deleted file mode 100644
index b3508770e..000000000
--- a/docs/react-testing-library/api.md
+++ /dev/null
@@ -1,285 +0,0 @@
----
-id: api
-title: API
----
-
-`React Testing Library` re-exports everything from `DOM Testing Library` as well
-as these methods:
-
-- [`render`](#render)
-- [`cleanup`](#cleanup)
-- [`act`](#act)
-
----
-
-## `render`
-
-```typescript
-function render(
-  ui: React.ReactElement,
-  options?: {
-    /* You won't often use this, expand below for docs on options */
-  }
-): RenderResult
-```
-
-Render into a container which is appended to `document.body`.
-
-```jsx
-import { render } from '@testing-library/react'
-
-render(
)
-```
-
-```jsx
-import { render } from '@testing-library/react'
-import '@testing-library/jest-dom/extend-expect'
-
-test('renders a message', () => {
-  const { container, getByText } = render(Hello, World! 
-  `)
-})
-```
-
-## `render` Options
-
-You won't often need to specify options, but if you ever do, here are the
-available options which you could provide as a second argument to `render`.
-
-### `container`
-
-By default, `React Testing Library` will create a `div` and append that `div` to
-the `document.body` and this is where your React component will be rendered. If
-you provide your own HTMLElement `container` via this option, it will not be
-appended to the `document.body` automatically.
-
-For example: If you are unit testing a `tablebody` element, it cannot be a child
-of a `div`. In this case, you can specify a `table` as the render `container`.
-
-```jsx
-const table = document.createElement('table')
-
-const { container } = render(Hello World 
-const { debug } = render(
-//   
Hello World 
-// 
-// you can also pass an element: debug(getByTestId('messages'))
-```
-
-This is a simple wrapper around `prettyDOM` which is also exposed and comes from
-[`DOM Testing Library`](https://github.com/testing-library/dom-testing-library/blob/master/README.md#prettydom).
-
-### `rerender`
-
-It'd probably be better if you test the component that's doing the prop updating
-to ensure that the props are being updated correctly (see
-[the Guiding Principles section](guiding-principles.md)). That said, if you'd
-prefer to update the props of a rendered component in your test, this function
-can be used to update props of the rendered component.
-
-```jsx
-import { render } from '@testing-library/react'
-
-const { rerender } = render( setCounter(count => count + 1)}>
-      Click to increase: {count}
-     
-  )
-}
-
-const { getByText, asFragment } = render(
)
-  // ...
-})
-
-// ... more tests ...
-```
-
-Failing to call `cleanup` when you've called `render` could result in a memory
-leak and tests which are not "idempotent" (which can lead to difficult to debug
-errors in your tests).
-
----
-
-## `act`
-
-This is a light wrapper around the
-[`react-dom/test-utils` `act` function](https://reactjs.org/docs/test-utils.html#act).
-All it does is forward all arguments to the act function if your version of
-react supports `act`.
diff --git a/docs/react-testing-library/api.mdx b/docs/react-testing-library/api.mdx
new file mode 100644
index 000000000..449c76f52
--- /dev/null
+++ b/docs/react-testing-library/api.mdx
@@ -0,0 +1,519 @@
+---
+id: api
+title: API
+---
+
+`React Testing Library` re-exports everything from `DOM Testing Library` as well
+as these methods:
+
+- [`render`](#render)
+- [`render` Options](#render-options)
+  - [`container`](#container)
+  - [`baseElement`](#baseelement)
+  - [`hydrate`](#hydrate)
+  - [`legacyRoot`](#legacyroot)
+  - [`onCaughtError`](#oncaughterror)
+  - [`onRecoverableError`](#onrecoverableerror)
+  - [`wrapper`](#wrapper)
+  - [`queries`](#queries)
+  - [`reactStrictMode`](#render-options-reactstrictmode)
+- [`render` Result](#render-result)
+  - [`...queries`](#queries-1)
+  - [`container`](#container-1)
+  - [`baseElement`](#baseelement-1)
+  - [`debug`](#debug)
+  - [`rerender`](#rerender)
+  - [`unmount`](#unmount)
+  - [`asFragment`](#asfragment)
+- [`cleanup`](#cleanup)
+- [`act`](#act)
+- [`renderHook`](#renderhook)
+- [`renderHook` Options](#renderhook-options)
+  - [`initialProps`](#initialprops)
+  - [`onCaughtError`](#oncaughterror)
+  - [`onRecoverableError`](#onrecoverableerror)
+  - [`wrapper`](#renderhook-options-wrapper)
+  - [`reactStrictMode`](#renderhook-options-reactstrictmode)
+- [`renderHook` Result](#renderhook-result)
+  - [`result`](#result)
+  - [`rerender`](#rerender-1)
+  - [`unmount`](#unmount-1)
+- [`configure`](#configure)
+- [`configure` Options](#configure-options)
+
+---
+
+## `render`
+
+```typescript
+function render(
+  ui: React.ReactElement,
+  options?: {
+    /* You won't often use this, expand below for docs on options */
+  },
+): RenderResult
+```
+
+Render into a container which is appended to `document.body`.
+
+```jsx
+import {render} from '@testing-library/react'
+
+render(
)
+```
+
+```jsx
+import {render} from '@testing-library/react'
+import '@testing-library/jest-dom'
+
+test('renders a message', () => {
+  const {asFragment, getByText} = render(Hello, World! 
+  `)
+})
+```
+
+## `render` Options
+
+You won't often need to specify options, but if you ever do, here are the
+available options which you could provide as a second argument to `render`.
+
+### `container`
+
+By default, `React Testing Library` will create a `div` and append that `div` to
+the `document.body` and this is where your React component will be rendered. If
+you provide your own HTMLElement `container` via this option, it will not be
+appended to the `document.body` automatically.
+
+For example: If you are unit testing a `tablebody` element, it cannot be a child
+of a `div`. In this case, you can specify a `table` as the render `container`.
+
+```jsx
+const table = document.createElement('table')
+
+const {container} = render(`](https://react.dev/reference/react/StrictMode) is rendered around the inner element.
+If defined, overrides the value of `reactStrictMode` set in [`configure`](https://testing-library.com/docs/react-testing-library/api/#configure-options).
+
+## `render` Result
+
+The `render` method returns an object that has a few properties:
+
+### `...queries`
+
+The most important feature of `render` is that the queries from
+[DOM Testing Library](queries/about.mdx) are automatically returned with their
+first argument bound to the [baseElement](#baseelement), which defaults to
+`document.body`.
+
+See [Queries](queries/about.mdx) for a complete list.
+
+**Example**
+
+```jsx
+const {getByLabelText, queryAllByTestId} = render(Hello World 
+const {debug} = render(
+//   
Hello World 
+// 
+// you can also pass an element: debug(getByTestId('messages'))
+// and you can pass all the same arguments to debug as you can
+// to prettyDOM:
+// const maxLengthToPrint = 10000
+// debug(getByTestId('messages'), maxLengthToPrint, {highlight: false})
+```
+
+This is a simple wrapper around `prettyDOM` which is also exposed and comes from
+[`DOM Testing Library`](dom-testing-library/api-debugging.mdx#prettydom).
+
+### `rerender`
+
+It'd probably be better if you test the component that's doing the prop updating
+to ensure that the props are being updated correctly (see
+[the Guiding Principles section](guiding-principles.mdx)). That said, if you'd
+prefer to update the props of a rendered component in your test, this function
+can be used to update props of the rendered component.
+
+```jsx
+import {render} from '@testing-library/react'
+
+const {rerender} = render( setCounter(count => count + 1)}>
+      Click to increase: {count}
+     
+  )
+}
+
+const {getByText, asFragment} = render(
)
+  // ...
+})
+
+// ... more tests ...
+```
+
+Failing to call `cleanup` when you've called `render` could result in a memory
+leak and tests which are not "idempotent" (which can lead to difficult to debug
+errors in your tests).
+
+---
+
+## `act`
+
+This is a light wrapper around the
+[`react` `act` function](https://react.dev/reference/react/act).
+All it does is forward all arguments to the act function if your version of
+react supports `act`. It is recommended to use the import from
+`@testing-library/react` over `react` for consistency reasons.
+
+## `renderHook`
+
+This is a convenience wrapper around `render` with a custom test component. The
+API emerged from a popular testing pattern and is mostly interesting for
+libraries publishing hooks. You should prefer `render` since a custom test
+component results in more readable and robust tests since the thing you want to
+test is not hidden behind an abstraction.
+
+```typescript
+function renderHook<
+  Result,
+  Props,
+  Q extends Queries = typeof queries,
+  Container extends Element | DocumentFragment = HTMLElement,
+  BaseElement extends Element | DocumentFragment = Container
+>(
+  render: (initialProps: Props) => Result,
+  options?: RenderHookOptions,
+): RenderHookResult
+```
+
+Example:
+
+```jsx
+import {renderHook} from '@testing-library/react'
+
+test('returns logged in user', () => {
+  const {result} = renderHook(() => useLoggedInUser())
+  expect(result.current).toEqual({name: 'Alice'})
+})
+```
+
+## `renderHook` Options
+
+### `renderHook` Options `initialProps`
+
+Declares the props that are passed to the render-callback when first invoked.
+These will **not** be passed if you call `rerender` without props.
+
+```jsx
+import {renderHook} from '@testing-library/react'
+
+test('returns logged in user', () => {
+  const {result, rerender} = renderHook((props = {}) => props, {
+    initialProps: {name: 'Alice'},
+  })
+  expect(result.current).toEqual({name: 'Alice'})
+  rerender()
+  expect(result.current).toEqual({name: undefined})
+})
+```
+
+> NOTE: When using `renderHook` in conjunction with the `wrapper` and
+> `initialProps` options, the `initialProps` are not passed to the `wrapper`
+> component. To provide props to the `wrapper` component, consider a solution
+> like this:
+>
+> ```js
+> const createWrapper = (Wrapper, props) => {
+>   return function CreatedWrapper({ children }) {
+>     return {children} ;
+>   };
+> };
+>
+> ...
+>
+> {
+>   wrapper: createWrapper(Wrapper, { value: 'foo' }),
+> }
+> ```
+
+### `onCaughtError`
+
+Callback called when React catches an error in an Error Boundary.
+Behaves the same as [`onCaughtError` in `ReactDOMClient.createRoot`](https://react.dev/reference/react-dom/client/createRoot#parameters).
+
+### `onRecoverableError`
+
+Callback called when React automatically recovers from errors. 
+Behaves the same as [`onRecoverableError` in `ReactDOMClient.createRoot`](https://react.dev/reference/react-dom/client/createRoot#parameters).
+
+### `renderHook` Options `wrapper`
+
+See [`wrapper` option for `render`](#wrapper)
+
+
+### `renderHook` Options `reactStrictMode`
+
+See [`reactStrictMode` option for `render`](#render-options-reactstrictmode)
+
+## `renderHook` Result
+
+The `renderHook` method returns an object that has a few properties:
+
+### `result`
+
+Holds the value of the most recently **committed** return value of the
+render-callback:
+
+```jsx
+import {renderHook} from '@testing-library/react'
+
+const {result} = renderHook(() => {
+  const [name, setName] = useState('')
+  React.useEffect(() => {
+    setName('Alice')
+  }, [])
+
+  return name
+})
+
+expect(result.current).toBe('Alice')
+```
+
+Note that the value is held in `result.current`. Think of `result` as a
+[ref](https://react.dev/learn/referencing-values-with-refs) for the most recently
+**committed** value.
+
+### `rerender`
+
+Renders the previously rendered render-callback with the new props:
+
+```jsx
+import {renderHook} from '@testing-library/react'
+
+const {rerender} = renderHook(({name = 'Alice'} = {}) => name)
+
+// re-render the same hook with different props
+rerender({name: 'Bob'})
+```
+
+### `unmount`
+
+Unmounts the test hook.
+
+```jsx
+import {renderHook} from '@testing-library/react'
+
+const {unmount} = renderHook(({name = 'Alice'} = {}) => name)
+
+unmount()
+```
+
+## `configure`
+
+Changes global options. Basic usage can be seen at
+[Configuration Options](dom-testing-library/api-configuration.mdx).
+
+React Testing Library also has dedicated options.
+
+```typescript
+import {configure} from '@testing-library/react'
+
+configure({reactStrictMode: true})
+```
+
+## `configure` Options
+
+### `reactStrictMode`
+
+When enabled, [``](https://react.dev/reference/react/StrictMode) is
+rendered around the inner element. Defaults to `false`.
+
+This setting can be changed for a single test by providing `reactStrictMode` in the options argument of the [`render`](#render-options-reactstrictmode) function. 
\ No newline at end of file
diff --git a/docs/react-testing-library/cheatsheet.md b/docs/react-testing-library/cheatsheet.mdx
similarity index 74%
rename from docs/react-testing-library/cheatsheet.md
rename to docs/react-testing-library/cheatsheet.mdx
index a59a99135..a50d82543 100644
--- a/docs/react-testing-library/cheatsheet.md
+++ b/docs/react-testing-library/cheatsheet.mdx
@@ -8,22 +8,23 @@ title: Cheatsheet
 A short guide to all the exported functions in `React Testing Library`
 
 - **render** `const {/* */} = render(Component)` returns:
-  - all the queries from `DOM Testing Library`, bound to the document so there
-    is no need to pass a node as the first argument
   - `unmount` function to unmount the component
   - `container` reference to the DOM node where the component is mounted
+  - all the queries from `DOM Testing Library`, bound to the document so there
+    is no need to pass a node as the first argument (usually, you can use the
+    `screen` import instead)
 
 ```jsx
-import { render, fireEvent } from '@testing-library/react'
+import {render, fireEvent, screen} from '@testing-library/react'
 
 test('loads items eventually', async () => {
-  const { getByText, findByText } = render(
-      
-          {buttonText}
-       
-      {greeting ? 
{greeting}  : null}
-    
-    )
-}
-```
-
-```jsx
-expect(axiosMock.get).toHaveBeenCalledTimes(1)
-expect(axiosMock.get).toHaveBeenCalledWith(url)
-expect(getByTestId('greeting-text')).toHaveTextContent('hello there')
-expect(getByTestId('ok-button')).toHaveAttribute('disabled')
-
-// snapshots work great with regular DOM nodes!
-expect(container).toMatchInlineSnapshot(`
-  
-    
-      
-        Ok
-       
-      
-        hello there
-       
-    
-  
+  Quickstart (Annotated Example) 
+
+```jsx
+// import react-testing methods
+import {render, screen} from '@testing-library/react'
+// userEvent library simulates user interactions by dispatching the events that would happen if the interaction took place in a browser.
+import userEvent from '@testing-library/user-event'
+// add custom jest matchers from jest-dom
+import '@testing-library/jest-dom'
+// the component to test
+import Fetch from './fetch'
+
+test('loads and displays greeting', async () => {
+  // Render a React element into the DOM
+  render( 
+
+## Full Example
+
+See the following sections for a detailed breakdown of the test
+
+:::note 
+
+We recommend using the
+[Mock Service Worker (MSW)](https://github.com/mswjs/msw) library to
+declaratively mock API communication in your tests instead of stubbing
+`window.fetch`, or relying on third-party adapters.
+
+:::
+
+:::note 
+
+Our example here uses axios to make its API calls. If your application uses [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch) to make its API calls, then be aware that by default JSDOM does not include fetch. If you are using vitest as your test runner, it will be included for you. For jest you may wish to manually polyfill `fetch()` or use the [jest-fixed-jsdom](https://github.com/mswjs/jest-fixed-jsdom) environment which includes fetch. 
+
+:::
+
+```jsx title="__tests__/fetch.test.jsx"
+import React from 'react'
+import {http, HttpResponse} from 'msw'
+import {setupServer} from 'msw/node'
+import {render, fireEvent, screen} from '@testing-library/react'
+import '@testing-library/jest-dom'
+import Fetch from '../fetch'
+
+const server = setupServer(
+  http.get('/greeting', () => {
+    return HttpResponse.json({greeting: 'hello there'})
+  }),
+)
+
+beforeAll(() => server.listen())
+afterEach(() => server.resetHandlers())
+afterAll(() => server.close())
+
+test('loads and displays greeting', async () => {
+  render(
+      
 fetchGreeting(url)} disabled={buttonClicked}>
+        {buttonText}
+       
+      {greeting && 
{greeting} }
+      {error && 
Oops, failed to fetch!
}
+    
-
-How do I test input onChange handlers? 
-
-TL;DR:
-[Go to the `on-change.js` example](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?module=%2Fsrc%2F__tests__%2Fon-change.js&previewwindow=tests)
-
-In summary:
-
-```javascript
-import React from 'react'
-import { render, fireEvent } from '@testing-library/react'
-
-test('change values via the fireEvent.change method', () => {
-  const handleChange = jest.fn()
-  const { container } = render( 
-
-
-
-Can I write unit tests with this library? 
-
-Definitely yes! You can write unit and integration tests with this library. See
-below for more on how to mock dependencies (because this library intentionally
-does NOT support shallow rendering) if you want to unit test a high level
-component. The tests in this project show several examples of unit testing with
-this library.
-
-As you write your tests, keep in mind:
-
-> The more your tests resemble the way your software is used, the more
-> confidence they can give you. - [17 Feb 2018][guiding-principle]
-
- 
-
-
-
-If I can't use shallow rendering, how do I mock out components in tests? 
-
-In general, you should avoid mocking out components (see
-[the Guiding Principles section](guiding-principles.md)). However if you need
-to, then it's pretty trivial using
-[Jest's mocking feature](https://facebook.github.io/jest/docs/en/manual-mocks.html).
-One case that I've found mocking to be especially useful is for animation
-libraries. I don't want my tests to wait for animations to end.
-
-```javascript
-jest.mock('react-transition-group', () => {
-  const FakeTransition = jest.fn(({ children }) => children)
-  const FakeCSSTransition = jest.fn(props =>
-    props.in ? {props.children}  : null
-  )
-  return { CSSTransition: FakeCSSTransition, Transition: FakeTransition }
-})
-
-test('you can mock things with jest.mock', () => {
-  const { getByTestId, queryByTestId } = render(
-     
-
-
-
-What about enzyme is "bloated with complexity and features" and "encourage
-poor testing practices"? 
-
-Most of the damaging features have to do with encouraging testing implementation
-details. Primarily, these are
-[shallow rendering](http://airbnb.io/enzyme/docs/api/shallow.html), APIs which
-allow selecting rendered elements by component constructors, and APIs which
-allow you to get and interact with component instances (and their
-state/properties) (most of enzyme's wrapper APIs allow this).
-
-The guiding principle for this library is:
-
-> The more your tests resemble the way your software is used, the more
-> confidence they can give you. - [17 Feb 2018][guiding-principle]
-
-Because users can't directly interact with your app's component instances,
-assert on their internal state or what components they render, or call their
-internal methods, doing those things in your tests reduce the confidence they're
-able to give you.
-
-That's not to say that there's never a use case for doing those things, so they
-should be possible to accomplish, just not the default and natural way to test
-react components.
-
- 
-
-
-
-Why isn't snapshot diffing working? 
-
-If you use the [snapshot-diff](https://github.com/jest-community/snapshot-diff)
-library to save snapshot diffs, it won't work out of the box because this
-library uses the DOM which is mutable. Changes don't return new objects so
-snapshot-diff will think it's the same object and avoid diffing it.
-
-Luckily there's an easy way to make it work: clone the DOM when passing it into
-snapshot-diff. It looks like this:
-
-```js
-const firstVersion = container.cloneNode(true)
-// Do some changes
-snapshotDiff(firstVersion, container.cloneNode(true))
-```
-
- 
-
-
-  
-How do I fix "an update was not wrapped in act(...)" warnings? 
-
-This warning is usually caused by an async operation causing an update after
-the test has already finished. There are 2 approaches to resolve it:
-
-1. Wait for the result of the operation in your test by using one of
-   [the async utilities](/docs/dom-testing-library/api-async) like
-   [wait](/docs/dom-testing-library/api-async#wait) or a
-   [`find*` query](/docs/dom-testing-library/api-queries#findby). For example:
-   `const userAddress = await findByLabel(/address/i)`.
-2. Mocking out the asynchronous operation so that it doesn't trigger state updates.
-
-Generally speaking, approach 1 is preferred since it better matches the expectations
-of a user interacting with your app.
-
-In addition, you may find
-[this blog post](https://kentcdodds.com/blog/write-fewer-longer-tests) helpful as you
-consider how best to write tests that give you confidence and avoid these warnings.
-
- 
-
-
-
-
-
-[guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106
-[data-testid-blog-post]: https://blog.kentcdodds.com/making-your-ui-tests-resilient-to-change-d37a6ee37269
-[dom-testing-lib-textmatch]: https://github.com/testing-library/dom-testing-library#textmatch
-
-
diff --git a/docs/react-testing-library/faq.mdx b/docs/react-testing-library/faq.mdx
new file mode 100644
index 000000000..b939e8e61
--- /dev/null
+++ b/docs/react-testing-library/faq.mdx
@@ -0,0 +1,353 @@
+---
+id: faq
+title: FAQ
+---
+
+See also the [main FAQ](dom-testing-library/faq.mdx) for questions not specific
+to React testing.
+
+
+
+How do I test input onChange handlers? 
+
+TL;DR:
+[Go to the `on-change.js` example](https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/main/?module=%2Fsrc%2F__tests__%2Fon-change.js&previewwindow=tests)
+
+In summary:
+
+```jsx
+import React from 'react'
+import {render, fireEvent} from '@testing-library/react'
+
+test('change values via the fireEvent.change method', () => {
+  const handleChange = jest.fn()
+  const {container} = render(
+      1 
+      2 
+     ,
+  )
+  const select = container.firstChild
+  const option1 = container.getElementsByTagName('option').item(0)
+  const option2 = container.getElementsByTagName('option').item(1)
+
+  fireEvent.change(select, {target: {value: '2'}})
+
+  expect(handleChange).toHaveBeenCalledTimes(1)
+  expect(option1.selected).toBe(false)
+  expect(option2.selected).toBe(true)
+})
+
+test('checkboxes (and radios) must use fireEvent.click', () => {
+  const handleChange = jest.fn()
+  const {container} = render( 
+
+
+
+How do I test error boundaries 
+
+To test if an error boundary successfully catches an error, you should make sure that if the fallback of the boundary is displayed when a child threw.
+
+Here's an example of how you can test an error boundary:
+
+```jsx
+import React from 'react'
+import {render, screen} from '@testing-library/react'
+
+class ErrorBoundary extends React.Component {
+  state = {error: null}
+  static getDerivedStateFromError(error) {
+    return {error}
+  }
+  render() {
+    const {error} = this.state
+    if (error) {
+      return Something went wrong
+    }
+    return this.props.children
+  }
+}
+
+test('error boundary catches error', () => {
+  const {container} = render(
+    
+       ,
+  )
+  expect(container.textContent).toEqual('Something went wrong.')
+})
+```
+
+If the error boundary did not catch the error, the test would fail since the `render` call would throw the error the Component produced.
+
+
+:::info
+
+React 18 will call `console.error` with an extended error message.
+React 19 will call `console.warn` with an extended error message.
+
+To disable the additional `console.warn` call in React 19, you can provide a custom `onCaughtError` callback e.g. `render( 
+
+
+
+Can I write unit tests with this library? 
+
+Definitely yes! You can write unit and integration tests with this library. See
+below for more on how to mock dependencies (because this library intentionally
+does NOT support shallow rendering) if you want to unit test a high level
+component. The tests in this project show several examples of unit testing with
+this library.
+
+As you write your tests, keep in mind:
+
+> The more your tests resemble the way your software is used, the more
+> confidence they can give you. - [17 Feb 2018][guiding-principle]
+
+ 
+
+
+
+How do I test thrown errors in a Component or Hook? 
+
+If a component throws during render, the origin of the state update will throw if wrapped in `act`.
+By default, `render` and `fireEvent` are wrapped in `act`.
+You can just wrap it in a try-catch or use dedicated matchers if your test runner supports these.
+For example, in Jest you can use `toThrow`:
+
+```jsx
+function Thrower() {
+  throw new Error('I throw')
+}
+
+test('it throws', () => {
+  expect(() => render( 
+
+
+
+
+  If I can't use shallow rendering, how do I mock out components in tests?
+ 
+
+In general, you should avoid mocking out components (see
+[the Guiding Principles section](guiding-principles.mdx)). However, if you need
+to, then try to use
+[Jest's mocking feature](https://facebook.github.io/jest/docs/en/manual-mocks.html).
+One case where I've found mocking to be especially useful is for animation
+libraries. I don't want my tests to wait for animations to end.
+
+```jsx
+jest.mock('react-transition-group', () => {
+  const FakeTransition = jest.fn(({children}) => children)
+  const FakeCSSTransition = jest.fn(props =>
+    props.in ? {props.children}  : null,
+  )
+  return {CSSTransition: FakeCSSTransition, Transition: FakeTransition}
+})
+
+test('you can mock things with jest.mock', () => {
+  const {getByTestId, queryByTestId} = render(
+     
+
+
+
+
+  What about enzyme is "bloated with complexity and features" and "encourage
+  poor testing practices"?
+ 
+
+Most of the damaging features have to do with encouraging testing implementation
+details. Primarily, these are
+[shallow rendering](http://airbnb.io/enzyme/docs/api/shallow.html), APIs which
+allow selecting rendered elements by component constructors, and APIs which
+allow you to get and interact with component instances (and their
+state/properties) (most of enzyme's wrapper APIs allow this).
+
+The guiding principle for this library is:
+
+> The more your tests resemble the way your software is used, the more
+> confidence they can give you. - [17 Feb 2018][guiding-principle]
+
+Because users can't directly interact with your app's component instances,
+assert on their internal state or what components they render, or call their
+internal methods, doing those things in your tests reduce the confidence they're
+able to give you.
+
+That's not to say that there's never a use case for doing those things, so they
+should be possible to accomplish, just not the default and natural way to test
+react components.
+
+ 
+
+
+
+Why isn't snapshot diffing working? 
+
+If you use the [snapshot-diff](https://github.com/jest-community/snapshot-diff)
+library to save snapshot diffs, it won't work out of the box because this
+library uses the DOM which is mutable. Changes don't return new objects so
+snapshot-diff will think it's the same object and avoid diffing it.
+
+Luckily there's an easy way to make it work: clone the DOM when passing it into
+snapshot-diff. It looks like this:
+
+```js
+const firstVersion = container.cloneNode(true)
+// Do some changes
+snapshotDiff(firstVersion, container.cloneNode(true))
+```
+
+ 
+
+
+  
+How do I fix "an update was not wrapped in act(...)" warnings? 
+
+This warning is usually caused by an async operation causing an update after the
+test has already finished. There are 2 approaches to resolve it:
+
+1. Wait for the result of the operation in your test by using one of
+   [the async utilities](dom-testing-library/api-async.mdx) like
+   [waitFor](dom-testing-library/api-async.mdx#waitfor) or a
+   [`find*` query](queries/about.mdx#types-of-queries). For example:
+   `const userAddress = await findByLabel(/address/i)`.
+2. Mocking out the asynchronous operation so that it doesn't trigger state
+   updates.
+
+Generally speaking, approach 1 is preferred since it better matches the
+expectations of a user interacting with your app.
+
+In addition, you may find
+[this blog post](https://kentcdodds.com/blog/write-fewer-longer-tests) helpful
+as you consider how best to write tests that give you confidence and avoid these
+warnings.
+
+ 
+
+
+  
+What level of a component tree should I test? Children, parents, or both? 
+
+Following the guiding principle of this library, it is useful to break down how
+tests are organized around how the user experiences and interacts with
+application functionality rather than around specific components themselves. In
+some cases, for example for reusable component libraries, it might be useful to
+include developers in the list of users to test for and test each of the
+reusable components individually. Other times, the specific break down of a
+component tree is just an implementation detail and testing every component
+within that tree individually can cause issues (see
+https://kentcdodds.com/blog/avoid-the-test-user).
+
+In practice this means that it is often preferable to test high enough up the
+component tree to simulate realistic user interactions. The question of whether
+it is worth additionally testing at a higher or lower level on top of this comes
+down to a question of tradeoffs and what will provide enough value for the cost
+(see https://kentcdodds.com/blog/unit-vs-integration-vs-e2e-tests on more info
+on different levels of testing).
+
+For a more in-depth discussion of this topic see
+[this video](https://youtu.be/0qmPdcV-rN8).
+
+ 
+
+
+
+
+
+[guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106
+
+
diff --git a/docs/react-testing-library/intro.md b/docs/react-testing-library/intro.mdx
similarity index 70%
rename from docs/react-testing-library/intro.md
rename to docs/react-testing-library/intro.mdx
index 0637887d5..7d8d026c4 100644
--- a/docs/react-testing-library/intro.md
+++ b/docs/react-testing-library/intro.mdx
@@ -7,11 +7,23 @@ sidebar_label: Introduction
 [`React Testing Library`][gh] builds on top of `DOM Testing Library` by adding
 APIs for working with React components.
 
+## Installation
+
+To get started with `React Testing Library`, you'll need to install it together
+with its peerDependency `@testing-library/dom`:
+
+```bash npm2yarn
+npm install --save-dev @testing-library/react @testing-library/dom
 ```
-npm install --save-dev @testing-library/react
-```
 
-- [React Testing Library on GitHub][gh]
+### With TypeScript
+
+To get full type coverage, you need to install the types for `react` and `react-dom` as 
+well:
+
+```bash npm2yarn
+npm install --save-dev @testing-library/react @testing-library/dom @types/react @types/react-dom
+```
 
 [gh]: https://github.com/testing-library/react-testing-library
 
@@ -32,11 +44,11 @@ components. It provides light utility functions on top of `react-dom` and
 `react-dom/test-utils`, in a way that encourages better testing practices. Its
 primary guiding principle is:
 
-> [The more your tests resemble the way your software is used, the more confidence they can give you.](guiding-principles.md)
+> [The more your tests resemble the way your software is used, the more confidence they can give you.](guiding-principles.mdx)
 
 So rather than dealing with instances of rendered React components, your tests
 will work with actual DOM nodes. The utilities this library provides facilitate
-querying the DOM in the same way the user would. Finding for elements by their
+querying the DOM in the same way the user would. Finding form elements by their
 label text (just like a user would), finding links and buttons from their text
 (like a user would). It also exposes a recommended way to find elements by a
 `data-testid` as an "escape hatch" for elements where the text content and label
@@ -51,24 +63,32 @@ This library is a replacement for [Enzyme](http://airbnb.io/enzyme/). While you
 _can_ follow these guidelines using Enzyme itself, enforcing this is harder
 because of all the extra utilities that Enzyme provides (utilities which
 facilitate testing implementation details). Read more about this in
-[the FAQ](./faq).
+[the FAQ](react-testing-library/faq.mdx).
 
 **What this library is not**:
 
 1.  A test runner or framework
 2.  Specific to a testing framework (though we recommend Jest as our preference,
     the library works with any framework. See
-    [Using Without Jest](./setup#using-without-jest))
+    [Using Without Jest](setup.mdx#using-without-jest))
 
 > NOTE: This library is built on top of
-> [`DOM Testing Library`](dom-testing-library/intro.md) which is where most of
+> [`DOM Testing Library`](dom-testing-library/intro.mdx) which is where most of
 > the logic behind the queries is.
 
-## Video
+## Tutorials
 
 Have a look at the "What is React Testing library?" video below for an
 introduction to the library.
 
 
-   
+
+Also, don't miss this
+[tutorial for React Testing Library](https://www.robinwieruch.de/react-testing-library).
diff --git a/docs/react-testing-library/migrate-from-enzyme.mdx b/docs/react-testing-library/migrate-from-enzyme.mdx
new file mode 100644
index 000000000..cf04d9298
--- /dev/null
+++ b/docs/react-testing-library/migrate-from-enzyme.mdx
@@ -0,0 +1,368 @@
+---
+id: migrate-from-enzyme
+title: Migrate from Enzyme
+sidebar_label: Migrate from Enzyme
+---
+
+This page is intended for developers who have experience with Enzyme and are
+trying to understand how to migrate to React Testing Library. It does not go
+into great detail about how to migrate all types of tests, but it does have some
+helpful information for those who are comparing Enzyme with React Testing
+Library.
+
+## What is React Testing Library?
+
+React Testing Library is part of an open-source project named
+[Testing Library](https://github.com/testing-library). There are several other
+helpful tools and libraries in the Testing Library project which you can use to
+write more concise and useful tests. Besides React Testing Library, here are
+some of the project's other libraries that can help you along the way:
+
+- **[@testing-library/jest-dom](https://github.com/testing-library/jest-dom)**:
+  `jest-dom` provides a set of custom Jest matchers that you can use to extend
+  Jest. These make your tests more declarative, clearer to read, and easier to
+  maintain.
+
+- **[@testing-library/user-event](https://github.com/testing-library/user-event):**
+  `user-event` tries to simulate the real events that happen in the browser as
+  the user interacts with elements on the page. For example,
+  `userEvent.click(checkbox)` would change the state of the checkbox.
+
+## Why should I use React Testing Library?
+
+Enzyme is a powerful test library, and its contributors did a lot for the
+JavaScript community. In fact, many of the React Testing Library maintainers
+used and contributed to Enzyme for years before developing and working on React
+Testing Library. So we want to say thank you to the contributors of Enzyme!
+
+The primary purpose of React Testing Library is to increase confidence in your
+tests by testing your components in the way a user would use them. Users don't
+care what happens behind the scenes, they just see and interact with the output.
+Instead of accessing the components' internal APIs or evaluating their `state`,
+you'll get more confidence by writing your tests based on the component output.
+
+React Testing Library aims to solve the problem that many developers face when
+writing tests with Enzyme, which allows (and encourages) developers to test
+[implementation details](https://kentcdodds.com/blog/testing-implementation-details).
+Tests which do this ultimately prevent you from modifying and refactoring the
+component without changing its tests. As a result, the tests slow down
+development speed and productivity. Every small change may require rewriting
+some part of your tests, even if the change does not affect the component's
+output.
+
+Rewriting your tests in React Testing library is worthwhile because you'll be
+trading tests that slow you down for tests that give you more confidence and
+increase your productivity in the long run.
+
+## How to migrate from Enzyme to React Testing Library?
+
+To ensure a successful migration, we recommend doing it incrementally by running
+the two test libraries side by side in the same application, porting your Enzyme
+tests to React Testing Library one by one. That makes it possible to migrate
+even large and complex applications without disrupting other business because
+the work can be done collaboratively and spread out over time.
+
+## Install React Testing Library
+
+First, install React Testing Library and the `jest-dom` helper library (you can
+check [this page](setup.mdx) for the complete installation and setup guide).
+
+```bash npm2yarn
+npm install --save-dev @testing-library/react @testing-library/jest-dom
+```
+
+## Import React Testing Library to your test
+
+If you're using Jest (you can use other test frameworks), then you only need to
+import the following modules into your test file:
+
+```jsx
+// import React so you can use JSX (React.createElement) in your test
+import React from 'react'
+
+/**
+ * render: lets us render the component as React would
+ * screen: a utility for finding elements the same way the user does
+ */
+import {render, screen} from '@testing-library/react'
+```
+
+The test structure can be the same as you would write with Enzyme:
+
+```jsx
+test('test title', () => {
+  // Your tests come here...
+})
+```
+
+> Note: you can also use `describe` and `it` blocks with React Testing Library.
+> React Testing Library doesn't replace Jest, just Enzyme. We recommend `test`
+> because it helps with this:
+> [Avoid Nesting When You're Testing](https://kentcdodds.com/blog/avoid-nesting-when-youre-testing).
+
+## Basic Enzyme to React Testing Library migration examples
+
+One thing to keep in mind is that there's not a one-to-one mapping of Enzyme
+features to React Testing Library features. Many Enzyme features result in
+inefficient tests anyway, so some of the features you're accustomed to with
+Enzyme need to be left behind (no more need for a `wrapper` variable or
+`wrapper.update()` calls, etc.).
+
+React Testing Library has helpful queries which let you access your component's
+elements and their properties. We'll show some typical Enzyme tests along with
+alternatives using React Testing Library.
+
+Let's say we have a `Welcome` component which shows a welcome message. We will
+have a look at both Enzyme and React Testing Library tests to learn how we can
+test this component:
+
+**React Component**
+
+The following component gets a `name` from `props` and shows a welcome message
+in an `h1` element. It also has a text input which users can change to a
+different name, and the template updates accordingly. Check the live version on
+[CodeSandbox](https://codesandbox.io/s/ecstatic-hellman-fh7in).
+
+```jsx
+const Welcome = props => {
+  const [values, setValues] = useState({
+    firstName: props.firstName,
+    lastName: props.lastName,
+  })
+
+  const handleChange = event => {
+    setValues({...values, [event.target.name]: event.target.value})
+  }
+
+  return (
+    
+      
+        Welcome, {values.firstName} {values.lastName}
+       
+
+      
+    
+  )
+}
+
+export default Welcome
+```
+
+### Test 1: Render the component, and check if the `h1` value is correct
+
+**Enzyme test**
+
+```jsx
+test('has correct welcome text', () => {
+  const wrapper = shallow(