[{"data":1,"prerenderedAt":5011},["ShallowReactive",2],{"\u002Fdocs\u002Frest-api":3,"all-docs":314,"sidebar-docs":2916},{"id":4,"title":5,"author":6,"body":9,"date":305,"description":306,"extension":307,"image":8,"meta":308,"navigation":309,"path":310,"seo":311,"stem":312,"tags":8,"__hash__":313},"docs\u002Fdocs\u002Frest-api.md","REST API (any backend)",{"name":7,"avatar":8},"PlainKey",null,{"type":10,"value":11,"toc":299},"minimark",[12,20,23,37,42,45,56,59,122,125,131,134,138,146,149,158,161,167,172,178,184,190,193,228,231,265,275,289,295],[13,14,15],"p",{},[16,17,19],"a",{"href":18},"\u002Fdocs\u002Fserver","← Back to server setup alternatives",[13,21,22],{},"Use the PlainKey REST API if your backend is not Node.js.",[13,24,25,26,36],{},"For all available endpoints, see the ",[27,28,29],"strong",{},[16,30,35],{"href":31,"target":32,"rel":33},"https:\u002F\u002Fapi.plainkey.io\u002Fserver","_blank",[34],"noopener","Server API Reference",".",[38,39,41],"h2",{"id":40},"authentication","Authentication",[13,43,44],{},"All requests require a project access token. Get one by exchanging your project ID and client secret:",[46,47,52],"pre",{"className":48,"code":50,"language":51},[49],"language-text","POST https:\u002F\u002Fapi.plainkey.io\u002Fserver\u002Faccess-token\nContent-Type: application\u002Fx-www-form-urlencoded\n\nclient_id=YOUR_PROJECT_ID\nclient_secret=YOUR_CLIENT_SECRET\n","text",[53,54,50],"code",{"__ignoreMap":55},"",[13,57,58],{},"Expected response:",[46,60,64],{"className":61,"code":62,"language":63,"meta":55,"style":55},"language-json shiki shiki-themes github-light github-dark","{\n  \"access_token\": \"...\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 3600\n}\n","json",[53,65,66,75,92,105,116],{"__ignoreMap":55},[67,68,71],"span",{"class":69,"line":70},"line",1,[67,72,74],{"class":73},"sVt8B","{\n",[67,76,78,82,85,89],{"class":69,"line":77},2,[67,79,81],{"class":80},"sj4cs","  \"access_token\"",[67,83,84],{"class":73},": ",[67,86,88],{"class":87},"sZZnC","\"...\"",[67,90,91],{"class":73},",\n",[67,93,95,98,100,103],{"class":69,"line":94},3,[67,96,97],{"class":80},"  \"token_type\"",[67,99,84],{"class":73},[67,101,102],{"class":87},"\"Bearer\"",[67,104,91],{"class":73},[67,106,108,111,113],{"class":69,"line":107},4,[67,109,110],{"class":80},"  \"expires_in\"",[67,112,84],{"class":73},[67,114,115],{"class":80},"3600\n",[67,117,119],{"class":69,"line":118},5,[67,120,121],{"class":73},"}\n",[13,123,124],{},"Include the token in all subsequent requests:",[46,126,129],{"className":127,"code":128,"language":51},[49],"Authorization: Bearer YOUR_ACCESS_TOKEN\nx-project-id: YOUR_PROJECT_ID\n",[53,130,128],{"__ignoreMap":55},[13,132,133],{},"Access tokens expire after 60 minutes. Fetch a new one when needed.",[38,135,137],{"id":136},"verify-authentication-token","Verify authentication token",[13,139,140,141,145],{},"A user is authenticated in the frontend using the ",[16,142,144],{"href":143},"\u002Fdocs\u002Fbrowser","Browser SDK",". Authentication occurs when the user authenticates with a passkey, but also when a user is first created with a passkey, or when a user adds a new passkey.",[13,147,148],{},"In your backend, build an endpoint that receives the authentication token from the frontend and verifies it with PlainKey. On success, PlainKey returns the user's PlainKey user ID.",[150,151,152],"info",{},[13,153,154,155,36],{},"The user ID is a UUID. For example: ",[53,156,157],{},"123e4567-e89b-12d3-a456-426614174000",[13,159,160],{},"You must store this user ID with your user record. This is your primary reference to the PlainKey user.",[162,163,164],"warning",{},[13,165,166],{},"Authentication tokens expire after 15 minutes. Do not store the token in any database or storage. Always keep it in memory and verify it immediately.",[168,169,171],"h3",{"id":170},"endpoint-flow-exchanging-authentication-token-for-user-session","Endpoint flow: Exchanging authentication token for user session",[13,173,174,177],{},[27,175,176],{},"1."," Your endpoint receives the authentication token from the frontend.",[13,179,180,183],{},[27,181,182],{},"2."," Verify it with PlainKey:",[46,185,188],{"className":186,"code":187,"language":51},[49],"POST https:\u002F\u002Fapi.plainkey.io\u002Fserver\u002Fauthentication-token\u002Fverify\nContent-Type: application\u002Fjson\n\n{ \"token\": \"AUTHENTICATION_TOKEN\" }\n",[53,189,187],{"__ignoreMap":55},[13,191,192],{},"On success:",[46,194,196],{"className":61,"code":195,"language":63,"meta":55,"style":55},"{\n  \"valid\": true,\n  \"userId\": \"123e4567-e89b-12d3-a456-426614174000\"\n}\n",[53,197,198,202,214,224],{"__ignoreMap":55},[67,199,200],{"class":69,"line":70},[67,201,74],{"class":73},[67,203,204,207,209,212],{"class":69,"line":77},[67,205,206],{"class":80},"  \"valid\"",[67,208,84],{"class":73},[67,210,211],{"class":80},"true",[67,213,91],{"class":73},[67,215,216,219,221],{"class":69,"line":94},[67,217,218],{"class":80},"  \"userId\"",[67,220,84],{"class":73},[67,222,223],{"class":87},"\"123e4567-e89b-12d3-a456-426614174000\"\n",[67,225,226],{"class":69,"line":107},[67,227,121],{"class":73},[13,229,230],{},"On failure (invalid or expired token):",[46,232,234],{"className":61,"code":233,"language":63,"meta":55,"style":55},"{\n  \"valid\": false,\n  \"error\": \"...\"\n}\n",[53,235,236,240,251,261],{"__ignoreMap":55},[67,237,238],{"class":69,"line":70},[67,239,74],{"class":73},[67,241,242,244,246,249],{"class":69,"line":77},[67,243,206],{"class":80},[67,245,84],{"class":73},[67,247,248],{"class":80},"false",[67,250,91],{"class":73},[67,252,253,256,258],{"class":69,"line":94},[67,254,255],{"class":80},"  \"error\"",[67,257,84],{"class":73},[67,259,260],{"class":87},"\"...\"\n",[67,262,263],{"class":69,"line":107},[67,264,121],{"class":73},[13,266,267,270,271,274],{},[27,268,269],{},"3."," If ",[53,272,273],{},"valid"," is false, return a 401 to the frontend.",[13,276,277,280,281,284,285,288],{},[27,278,279],{},"4."," Use ",[53,282,283],{},"userId"," to find or create the user in your database. If the user doesn't exist yet, this is their first sign-in (signup). In that case, you may want to pass a ",[53,286,287],{},"userName"," or other identity information for your own user table, alongside the token, to your endpoint so you have something to create the user with.",[13,290,291,294],{},[27,292,293],{},"5."," Continue doing what suits your application. For sign-in, this usually involves creating a session for the user and returning it to the frontend.",[296,297,298],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":55,"searchDepth":77,"depth":77,"links":300},[301,302],{"id":40,"depth":77,"text":41},{"id":136,"depth":77,"text":137,"children":303},[304],{"id":170,"depth":94,"text":171},"2026-01-29","Use the PlainKey REST API to verify authentication tokens from any backend language.","md",{},true,"\u002Fdocs\u002Frest-api",{"title":5,"description":306},"docs\u002Frest-api","16E66AX2_SulFQ5M2fDUH5R30Z4zqF1WN_UoXqbwmrA",[315,651,855,1986,2005,2817],{"id":316,"title":317,"author":318,"body":319,"date":644,"description":645,"extension":307,"image":8,"meta":646,"navigation":309,"path":647,"seo":648,"stem":649,"tags":8,"__hash__":650},"docs\u002Fdocs\u002Fdocs-mcp.md","Docs for AI",{"name":7,"avatar":8},{"type":10,"value":320,"toc":636},[321,331,335,338,341,344,348,353,356,363,369,377,402,407,410,413,417,420,451,455,470,543,548,552,563,619,623,626,633],[13,322,323,324,330],{},"All PlainKey documentation and articles are available as AI-friendly Markdown files via ",[16,325,329],{"href":326,"rel":327},"https:\u002F\u002Fplainkey.io\u002Fllms.txt",[328],"nofollow","llms.txt",". PlainKey also provides an MCP server that lets your AI assistant read and query the docs directly.",[38,332,334],{"id":333},"plainkey-docs-mcp","PlainKey Docs MCP",[13,336,337],{},"MCP (Model Context Protocol) is an open-source standard for connecting AI applications to external systems. Using MCP, AI applications like ChatGPT, Cursor and Claude Code can connect to data sources, tools and workflows.",[13,339,340],{},"PlainKey Docs MCP is an MCP server that allows your AI assistant to read and understand PlainKey's documentation and articles. This way, it can assist you with setting up PlainKey for your web app.",[13,342,343],{},"It has access to all documentation pages and articles on plainkey.io.",[38,345,347],{"id":346},"chatgpt-setup","ChatGPT Setup",[150,349,350],{},[13,351,352],{},"Custom MCP connectors are available on ChatGPT for Pro and Plus accounts.",[13,354,355],{},"Follow these steps to set up PlainKey Docs as a connector within ChatGPT:",[357,358,359],"ol",{},[360,361,362],"li",{},"Enable Developer mode:",[364,365,366],"ul",{},[360,367,368],{},"Go to \"Settings\" > \"Connectors\" > \"Advanced settings\" > \"Developer mode\"",[357,370,371,374],{"start":77},[360,372,373],{},"Open ChatGPT settings",[360,375,376],{},"In the Connectors tab, create a new connector:",[364,378,379,384,390,396],{},[360,380,381,382],{},"Give it a name: ",[53,383,334],{},[360,385,386,387],{},"Description: ",[53,388,389],{},"Provides documentation for PlainKey, a passkey authentication service",[360,391,392,393],{},"MCP server URL: ",[53,394,395],{},"https:\u002F\u002Fdocs-mcp.plainkey.io\u002Fmcp",[360,397,398,399],{},"Authentication: ",[53,400,401],{},"None",[357,403,404],{"start":107},[360,405,406],{},"Click Create",[13,408,409],{},"You can now ask ChatGPT to help you with setting up PlainKey for your project.",[13,411,412],{},"If ChatGPT says it doesn't have access, try clicking the + in the chat -> More -> PlainKey Docs to make ChatGPT aware you specifically want to use that connector.",[38,414,416],{"id":415},"claude-code-setup","Claude Code Setup",[13,418,419],{},"Add the server using the CLI command:",[46,421,425],{"className":422,"code":423,"language":424,"meta":55,"style":55},"language-bash shiki shiki-themes github-light github-dark","claude mcp add --transport http plainkey-docs-mcp https:\u002F\u002Fdocs-mcp.plainkey.io\u002Fmcp\n","bash",[53,426,427],{"__ignoreMap":55},[67,428,429,433,436,439,442,445,448],{"class":69,"line":70},[67,430,432],{"class":431},"sScJk","claude",[67,434,435],{"class":87}," mcp",[67,437,438],{"class":87}," add",[67,440,441],{"class":80}," --transport",[67,443,444],{"class":87}," http",[67,446,447],{"class":87}," plainkey-docs-mcp",[67,449,450],{"class":87}," https:\u002F\u002Fdocs-mcp.plainkey.io\u002Fmcp\n",[38,452,454],{"id":453},"claude-desktop-setup","Claude Desktop Setup",[357,456,457,460,463],{},[360,458,459],{},"Open Claude Desktop and navigate to \"Settings\" > \"Developer\".",[360,461,462],{},"Click on \"Edit Config\". This will open the local Claude directory.",[360,464,465,466,469],{},"Modify the ",[53,467,468],{},"claude_desktop_config.json"," file with your custom MCP server configuration.",[46,471,473],{"className":61,"code":472,"filename":468,"language":63,"meta":55,"style":55},"{\n  \"mcpServers\": {\n    \"plainkey-docs\": {\n      \"command\": \"npx\",\n      \"args\": [\"mcp-remote\", \"https:\u002F\u002Fdocs-mcp.plainkey.io\u002Fmcp\"]\n    }\n  }\n}\n",[53,474,475,479,487,494,506,526,532,538],{"__ignoreMap":55},[67,476,477],{"class":69,"line":70},[67,478,74],{"class":73},[67,480,481,484],{"class":69,"line":77},[67,482,483],{"class":80},"  \"mcpServers\"",[67,485,486],{"class":73},": {\n",[67,488,489,492],{"class":69,"line":94},[67,490,491],{"class":80},"    \"plainkey-docs\"",[67,493,486],{"class":73},[67,495,496,499,501,504],{"class":69,"line":107},[67,497,498],{"class":80},"      \"command\"",[67,500,84],{"class":73},[67,502,503],{"class":87},"\"npx\"",[67,505,91],{"class":73},[67,507,508,511,514,517,520,523],{"class":69,"line":118},[67,509,510],{"class":80},"      \"args\"",[67,512,513],{"class":73},": [",[67,515,516],{"class":87},"\"mcp-remote\"",[67,518,519],{"class":73},", ",[67,521,522],{"class":87},"\"https:\u002F\u002Fdocs-mcp.plainkey.io\u002Fmcp\"",[67,524,525],{"class":73},"]\n",[67,527,529],{"class":69,"line":528},6,[67,530,531],{"class":73},"    }\n",[67,533,535],{"class":69,"line":534},7,[67,536,537],{"class":73},"  }\n",[67,539,541],{"class":69,"line":540},8,[67,542,121],{"class":73},[357,544,545],{"start":107},[360,546,547],{},"Restart Claude Desktop app. The PlainKey Docs MCP server should now be registered.",[38,549,551],{"id":550},"cursor-setup","Cursor Setup",[357,553,554,557,560],{},[360,555,556],{},"Open Cursor and go to \"Settings\" > \"Tools & MCP\"",[360,558,559],{},"Click \"New MCP Server\"",[360,561,562],{},"Add the following configuration to the JSON file:",[46,564,567],{"className":61,"code":565,"filename":566,"language":63,"meta":55,"style":55},"{\n  \"mcpServers\": {\n    \"plainkey-docs\": {\n      \"type\": \"http\",\n      \"url\": \"https:\u002F\u002Fdocs-mcp.plainkey.io\u002Fmcp\"\n    }\n  }\n}\n",".cursor\u002Fmcp.json",[53,568,569,573,579,585,597,607,611,615],{"__ignoreMap":55},[67,570,571],{"class":69,"line":70},[67,572,74],{"class":73},[67,574,575,577],{"class":69,"line":77},[67,576,483],{"class":80},[67,578,486],{"class":73},[67,580,581,583],{"class":69,"line":94},[67,582,491],{"class":80},[67,584,486],{"class":73},[67,586,587,590,592,595],{"class":69,"line":107},[67,588,589],{"class":80},"      \"type\"",[67,591,84],{"class":73},[67,593,594],{"class":87},"\"http\"",[67,596,91],{"class":73},[67,598,599,602,604],{"class":69,"line":118},[67,600,601],{"class":80},"      \"url\"",[67,603,84],{"class":73},[67,605,606],{"class":87},"\"https:\u002F\u002Fdocs-mcp.plainkey.io\u002Fmcp\"\n",[67,608,609],{"class":69,"line":528},[67,610,531],{"class":73},[67,612,613],{"class":69,"line":534},[67,614,537],{"class":73},[67,616,617],{"class":69,"line":540},[67,618,121],{"class":73},[38,620,622],{"id":621},"other-ai-assistants","Other AI assistants",[13,624,625],{},"Different AI assistants have different ways of adding MCP servers. We recommend using the official documentation for your specific assistant.",[13,627,628,629,632],{},"The URL to PlainKey Docs MCP is ",[16,630,395],{"href":395,"rel":631},[328],". It uses http transport.",[296,634,635],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":55,"searchDepth":77,"depth":77,"links":637},[638,639,640,641,642,643],{"id":333,"depth":77,"text":334},{"id":346,"depth":77,"text":347},{"id":415,"depth":77,"text":416},{"id":453,"depth":77,"text":454},{"id":550,"depth":77,"text":551},{"id":621,"depth":77,"text":622},"2026-02-20","Use PlainKey's documentation with your AI assistant, via llms.txt or our Docs MCP server.",{},"\u002Fdocs\u002Fdocs-mcp",{"title":317,"description":645},"docs\u002Fdocs-mcp","aIpP1bDGvONLCd0ssorCrezKIeBhyTg0Sys0ARlwWd8",{"id":4,"title":5,"author":652,"body":653,"date":305,"description":306,"extension":307,"image":8,"meta":853,"navigation":309,"path":310,"seo":854,"stem":312,"tags":8,"__hash__":313},{"name":7,"avatar":8},{"type":10,"value":654,"toc":847},[655,659,661,668,670,672,677,679,719,721,726,728,730,734,736,742,744,748,750,754,758,763,765,795,797,827,833,841,845],[13,656,657],{},[16,658,19],{"href":18},[13,660,22],{},[13,662,25,663,36],{},[27,664,665],{},[16,666,35],{"href":31,"target":32,"rel":667},[34],[38,669,41],{"id":40},[13,671,44],{},[46,673,675],{"className":674,"code":50,"language":51},[49],[53,676,50],{"__ignoreMap":55},[13,678,58],{},[46,680,681],{"className":61,"code":62,"language":63,"meta":55,"style":55},[53,682,683,687,697,707,715],{"__ignoreMap":55},[67,684,685],{"class":69,"line":70},[67,686,74],{"class":73},[67,688,689,691,693,695],{"class":69,"line":77},[67,690,81],{"class":80},[67,692,84],{"class":73},[67,694,88],{"class":87},[67,696,91],{"class":73},[67,698,699,701,703,705],{"class":69,"line":94},[67,700,97],{"class":80},[67,702,84],{"class":73},[67,704,102],{"class":87},[67,706,91],{"class":73},[67,708,709,711,713],{"class":69,"line":107},[67,710,110],{"class":80},[67,712,84],{"class":73},[67,714,115],{"class":80},[67,716,717],{"class":69,"line":118},[67,718,121],{"class":73},[13,720,124],{},[46,722,724],{"className":723,"code":128,"language":51},[49],[53,725,128],{"__ignoreMap":55},[13,727,133],{},[38,729,137],{"id":136},[13,731,140,732,145],{},[16,733,144],{"href":143},[13,735,148],{},[150,737,738],{},[13,739,154,740,36],{},[53,741,157],{},[13,743,160],{},[162,745,746],{},[13,747,166],{},[168,749,171],{"id":170},[13,751,752,177],{},[27,753,176],{},[13,755,756,183],{},[27,757,182],{},[46,759,761],{"className":760,"code":187,"language":51},[49],[53,762,187],{"__ignoreMap":55},[13,764,192],{},[46,766,767],{"className":61,"code":195,"language":63,"meta":55,"style":55},[53,768,769,773,783,791],{"__ignoreMap":55},[67,770,771],{"class":69,"line":70},[67,772,74],{"class":73},[67,774,775,777,779,781],{"class":69,"line":77},[67,776,206],{"class":80},[67,778,84],{"class":73},[67,780,211],{"class":80},[67,782,91],{"class":73},[67,784,785,787,789],{"class":69,"line":94},[67,786,218],{"class":80},[67,788,84],{"class":73},[67,790,223],{"class":87},[67,792,793],{"class":69,"line":107},[67,794,121],{"class":73},[13,796,230],{},[46,798,799],{"className":61,"code":233,"language":63,"meta":55,"style":55},[53,800,801,805,815,823],{"__ignoreMap":55},[67,802,803],{"class":69,"line":70},[67,804,74],{"class":73},[67,806,807,809,811,813],{"class":69,"line":77},[67,808,206],{"class":80},[67,810,84],{"class":73},[67,812,248],{"class":80},[67,814,91],{"class":73},[67,816,817,819,821],{"class":69,"line":94},[67,818,255],{"class":80},[67,820,84],{"class":73},[67,822,260],{"class":87},[67,824,825],{"class":69,"line":107},[67,826,121],{"class":73},[13,828,829,270,831,274],{},[27,830,269],{},[53,832,273],{},[13,834,835,280,837,284,839,288],{},[27,836,279],{},[53,838,283],{},[53,840,287],{},[13,842,843,294],{},[27,844,293],{},[296,846,298],{},{"title":55,"searchDepth":77,"depth":77,"links":848},[849,850],{"id":40,"depth":77,"text":41},{"id":136,"depth":77,"text":137,"children":851},[852],{"id":170,"depth":94,"text":171},{},{"title":5,"description":306},{"id":856,"title":857,"author":858,"body":859,"date":1979,"description":1980,"extension":307,"image":8,"meta":1981,"navigation":309,"path":1982,"seo":1983,"stem":1984,"tags":8,"__hash__":1985},"docs\u002Fdocs\u002Fserver-sdk.md","Server SDK (Node.js)",{"name":7,"avatar":8},{"type":10,"value":860,"toc":1967},[861,865,868,871,875,878,894,898,901,904,907,974,979,981,985,992,995,1001,1003,1006,1010,1014,1017,1020,1031,1474,1479,1483,1640,1643,1698,1702,1705,1740,1744,1861,1865,1868,1871,1914,1927,1964],[13,862,863],{},[16,864,19],{"href":18},[13,866,867],{},"In your backend, you must verify authentication tokens. The Server SDK is recommended for Node.js projects. This includes if your backend is built with Express, Hono, Fastify, Next.js, Nuxt, SvelteKit etc.",[13,869,870],{},"The Server SDK also allows you to manage users and passkeys.",[38,872,874],{"id":873},"installation","Installation",[13,876,877],{},"In the terminal:",[46,879,881],{"className":422,"code":880,"language":424,"meta":55,"style":55},"npm install @plainkey\u002Fserver\n",[53,882,883],{"__ignoreMap":55},[67,884,885,888,891],{"class":69,"line":70},[67,886,887],{"class":431},"npm",[67,889,890],{"class":87}," install",[67,892,893],{"class":87}," @plainkey\u002Fserver\n",[38,895,897],{"id":896},"initialise","Initialise",[13,899,900],{},"It is recommended to initialise the PlainKey Server SDK in a single location and import it wherever you need it.",[13,902,903],{},"This is because the SDK handles access token management internally. If you were to initialise it on every request, the SDK would fetch a new access token on each request.",[13,905,906],{},"Having it in a single location will make it fetch new access tokens only when needed, which will make the Server SDK more efficient.",[46,908,912],{"className":909,"code":910,"language":911,"meta":55,"style":55},"language-ts shiki shiki-themes github-light github-dark","\u002F\u002F server\u002FplainKeyServer.ts or similar\nimport { PlainKeyServer } from \"@plainkey\u002Fserver\"\n\nexport const plainKeyServer = new PlainKeyServer(\"YOUR_PROJECT_ID\", \"YOUR_CLIENT_SECRET\")\n","ts",[53,913,914,920,935,940],{"__ignoreMap":55},[67,915,916],{"class":69,"line":70},[67,917,919],{"class":918},"sJ8bj","\u002F\u002F server\u002FplainKeyServer.ts or similar\n",[67,921,922,926,929,932],{"class":69,"line":77},[67,923,925],{"class":924},"szBVR","import",[67,927,928],{"class":73}," { PlainKeyServer } ",[67,930,931],{"class":924},"from",[67,933,934],{"class":87}," \"@plainkey\u002Fserver\"\n",[67,936,937],{"class":69,"line":94},[67,938,939],{"emptyLinePlaceholder":309},"\n",[67,941,942,945,948,951,954,957,960,963,966,968,971],{"class":69,"line":107},[67,943,944],{"class":924},"export",[67,946,947],{"class":924}," const",[67,949,950],{"class":80}," plainKeyServer",[67,952,953],{"class":924}," =",[67,955,956],{"class":924}," new",[67,958,959],{"class":431}," PlainKeyServer",[67,961,962],{"class":73},"(",[67,964,965],{"class":87},"\"YOUR_PROJECT_ID\"",[67,967,519],{"class":73},[67,969,970],{"class":87},"\"YOUR_CLIENT_SECRET\"",[67,972,973],{"class":73},")\n",[150,975,976],{},[13,977,978],{},"You can find your project ID and client secret on the PlainKey admin dashboard. The client secret is a secret and must not be exposed.",[38,980,137],{"id":136},[13,982,140,983,145],{},[16,984,144],{"href":143},[13,986,987,988,991],{},"In your backend, build an endpoint that receives the authentication token and exchanges it for a user session or whatever fits your application. You use the PlainKey Server SDK's ",[53,989,990],{},".verifyAuthenticationToken()"," method to verify the token.",[13,993,994],{},"On verification success, the SDK returns the user's PlainKey User ID, which you use to find or create the user in your database.",[150,996,997],{},[13,998,154,999,36],{},[53,1000,157],{},[13,1002,160],{},[13,1004,1005],{},"After verification and storing the user ID, you continue doing what suits your application. For sign-in, this usually involves creating your own session for the user and returning the session data to the frontend.",[162,1007,1008],{},[13,1009,166],{},[168,1011,1013],{"id":1012},"endpoint-example-exchanging-authentication-token-for-user-session","Endpoint example: Exchanging authentication token for user session",[13,1015,1016],{},"This shows an endpoint that receives the authentication token and exchanges it for a user login session. The endpoint is used for both sign-in and sign-up.",[13,1018,1019],{},"Three things happen in this endpoint:",[357,1021,1022,1025,1028],{},[360,1023,1024],{},"Verify the authentication token with PlainKey. On success, you get the user's PlainKey user ID.",[360,1026,1027],{},"Find or create the user in your database using the user ID.",[360,1029,1030],{},"Establish a session for the user (or whatever fits your application).",[46,1032,1034],{"className":909,"code":1033,"language":911,"meta":55,"style":55},"\u002F**\n * Endpoint handler that receives authentication token and exchanges it for a user session\n *\u002F\napp.post(\"\u002Fapi\u002Fauth\u002Fexchange\", async (request, response) => {\n  \u002F\u002F In this example, we pass in the authentication token, but also optionally a userName for first signup.\n  const { token, userName } = request.body\n\n  if (!token) {\n    return response.status(400)\n  }\n\n  \u002F\u002F 1. Verify authentication token with PlainKey.\n  \u002F\u002F    On success it returns the PlainKey user ID.\n  \u002F\u002F    An invalid or expired token is a normal outcome. Always check success.\n  const { success, data, error } = await plainKeyServer.verifyAuthenticationToken(token)\n\n  if (!success) {\n    return response.status(401).json({ error: error?.message })\n  }\n\n  const plainKeyUserId = data?.userId\n\n  \u002F\u002F 2. Find or create user in your database\n  let user = await findUserByPlainKeyId(plainKeyUserId)\n\n  if (!user) {\n    \u002F\u002F First time we've seen this user (signup).\n    \u002F\u002F In this case we'd usually have passed a userName or some identity information to the endpoint.\n    if (!userName) {\n      return response.status(400)\n    }\n\n    user = await createUser({\n      plainKeyUserId,\n      userName\n    })\n  }\n\n  \u002F\u002F 3. For sign-in: Establish a session for the user\n  \u002F\u002F    (typically by creating a session and setting a first-party cookie)\n  await establishUserSession(response, user.id)\n\n  response.json({ success: true })\n})\n",[53,1035,1036,1041,1046,1051,1090,1095,1119,1123,1136,1155,1160,1165,1171,1177,1183,1219,1224,1236,1258,1263,1268,1281,1286,1292,1311,1316,1328,1334,1340,1353,1369,1374,1379,1395,1401,1407,1413,1418,1423,1429,1435,1447,1452,1468],{"__ignoreMap":55},[67,1037,1038],{"class":69,"line":70},[67,1039,1040],{"class":918},"\u002F**\n",[67,1042,1043],{"class":69,"line":77},[67,1044,1045],{"class":918}," * Endpoint handler that receives authentication token and exchanges it for a user session\n",[67,1047,1048],{"class":69,"line":94},[67,1049,1050],{"class":918}," *\u002F\n",[67,1052,1053,1056,1059,1061,1064,1066,1069,1072,1076,1078,1081,1084,1087],{"class":69,"line":107},[67,1054,1055],{"class":73},"app.",[67,1057,1058],{"class":431},"post",[67,1060,962],{"class":73},[67,1062,1063],{"class":87},"\"\u002Fapi\u002Fauth\u002Fexchange\"",[67,1065,519],{"class":73},[67,1067,1068],{"class":924},"async",[67,1070,1071],{"class":73}," (",[67,1073,1075],{"class":1074},"s4XuR","request",[67,1077,519],{"class":73},[67,1079,1080],{"class":1074},"response",[67,1082,1083],{"class":73},") ",[67,1085,1086],{"class":924},"=>",[67,1088,1089],{"class":73}," {\n",[67,1091,1092],{"class":69,"line":118},[67,1093,1094],{"class":918},"  \u002F\u002F In this example, we pass in the authentication token, but also optionally a userName for first signup.\n",[67,1096,1097,1100,1103,1106,1108,1110,1113,1116],{"class":69,"line":528},[67,1098,1099],{"class":924},"  const",[67,1101,1102],{"class":73}," { ",[67,1104,1105],{"class":80},"token",[67,1107,519],{"class":73},[67,1109,287],{"class":80},[67,1111,1112],{"class":73}," } ",[67,1114,1115],{"class":924},"=",[67,1117,1118],{"class":73}," request.body\n",[67,1120,1121],{"class":69,"line":534},[67,1122,939],{"emptyLinePlaceholder":309},[67,1124,1125,1128,1130,1133],{"class":69,"line":540},[67,1126,1127],{"class":924},"  if",[67,1129,1071],{"class":73},[67,1131,1132],{"class":924},"!",[67,1134,1135],{"class":73},"token) {\n",[67,1137,1139,1142,1145,1148,1150,1153],{"class":69,"line":1138},9,[67,1140,1141],{"class":924},"    return",[67,1143,1144],{"class":73}," response.",[67,1146,1147],{"class":431},"status",[67,1149,962],{"class":73},[67,1151,1152],{"class":80},"400",[67,1154,973],{"class":73},[67,1156,1158],{"class":69,"line":1157},10,[67,1159,537],{"class":73},[67,1161,1163],{"class":69,"line":1162},11,[67,1164,939],{"emptyLinePlaceholder":309},[67,1166,1168],{"class":69,"line":1167},12,[67,1169,1170],{"class":918},"  \u002F\u002F 1. Verify authentication token with PlainKey.\n",[67,1172,1174],{"class":69,"line":1173},13,[67,1175,1176],{"class":918},"  \u002F\u002F    On success it returns the PlainKey user ID.\n",[67,1178,1180],{"class":69,"line":1179},14,[67,1181,1182],{"class":918},"  \u002F\u002F    An invalid or expired token is a normal outcome. Always check success.\n",[67,1184,1186,1188,1190,1193,1195,1198,1200,1203,1205,1207,1210,1213,1216],{"class":69,"line":1185},15,[67,1187,1099],{"class":924},[67,1189,1102],{"class":73},[67,1191,1192],{"class":80},"success",[67,1194,519],{"class":73},[67,1196,1197],{"class":80},"data",[67,1199,519],{"class":73},[67,1201,1202],{"class":80},"error",[67,1204,1112],{"class":73},[67,1206,1115],{"class":924},[67,1208,1209],{"class":924}," await",[67,1211,1212],{"class":73}," plainKeyServer.",[67,1214,1215],{"class":431},"verifyAuthenticationToken",[67,1217,1218],{"class":73},"(token)\n",[67,1220,1222],{"class":69,"line":1221},16,[67,1223,939],{"emptyLinePlaceholder":309},[67,1225,1227,1229,1231,1233],{"class":69,"line":1226},17,[67,1228,1127],{"class":924},[67,1230,1071],{"class":73},[67,1232,1132],{"class":924},[67,1234,1235],{"class":73},"success) {\n",[67,1237,1239,1241,1243,1245,1247,1250,1253,1255],{"class":69,"line":1238},18,[67,1240,1141],{"class":924},[67,1242,1144],{"class":73},[67,1244,1147],{"class":431},[67,1246,962],{"class":73},[67,1248,1249],{"class":80},"401",[67,1251,1252],{"class":73},").",[67,1254,63],{"class":431},[67,1256,1257],{"class":73},"({ error: error?.message })\n",[67,1259,1261],{"class":69,"line":1260},19,[67,1262,537],{"class":73},[67,1264,1266],{"class":69,"line":1265},20,[67,1267,939],{"emptyLinePlaceholder":309},[67,1269,1271,1273,1276,1278],{"class":69,"line":1270},21,[67,1272,1099],{"class":924},[67,1274,1275],{"class":80}," plainKeyUserId",[67,1277,953],{"class":924},[67,1279,1280],{"class":73}," data?.userId\n",[67,1282,1284],{"class":69,"line":1283},22,[67,1285,939],{"emptyLinePlaceholder":309},[67,1287,1289],{"class":69,"line":1288},23,[67,1290,1291],{"class":918},"  \u002F\u002F 2. Find or create user in your database\n",[67,1293,1295,1298,1301,1303,1305,1308],{"class":69,"line":1294},24,[67,1296,1297],{"class":924},"  let",[67,1299,1300],{"class":73}," user ",[67,1302,1115],{"class":924},[67,1304,1209],{"class":924},[67,1306,1307],{"class":431}," findUserByPlainKeyId",[67,1309,1310],{"class":73},"(plainKeyUserId)\n",[67,1312,1314],{"class":69,"line":1313},25,[67,1315,939],{"emptyLinePlaceholder":309},[67,1317,1319,1321,1323,1325],{"class":69,"line":1318},26,[67,1320,1127],{"class":924},[67,1322,1071],{"class":73},[67,1324,1132],{"class":924},[67,1326,1327],{"class":73},"user) {\n",[67,1329,1331],{"class":69,"line":1330},27,[67,1332,1333],{"class":918},"    \u002F\u002F First time we've seen this user (signup).\n",[67,1335,1337],{"class":69,"line":1336},28,[67,1338,1339],{"class":918},"    \u002F\u002F In this case we'd usually have passed a userName or some identity information to the endpoint.\n",[67,1341,1343,1346,1348,1350],{"class":69,"line":1342},29,[67,1344,1345],{"class":924},"    if",[67,1347,1071],{"class":73},[67,1349,1132],{"class":924},[67,1351,1352],{"class":73},"userName) {\n",[67,1354,1356,1359,1361,1363,1365,1367],{"class":69,"line":1355},30,[67,1357,1358],{"class":924},"      return",[67,1360,1144],{"class":73},[67,1362,1147],{"class":431},[67,1364,962],{"class":73},[67,1366,1152],{"class":80},[67,1368,973],{"class":73},[67,1370,1372],{"class":69,"line":1371},31,[67,1373,531],{"class":73},[67,1375,1377],{"class":69,"line":1376},32,[67,1378,939],{"emptyLinePlaceholder":309},[67,1380,1382,1385,1387,1389,1392],{"class":69,"line":1381},33,[67,1383,1384],{"class":73},"    user ",[67,1386,1115],{"class":924},[67,1388,1209],{"class":924},[67,1390,1391],{"class":431}," createUser",[67,1393,1394],{"class":73},"({\n",[67,1396,1398],{"class":69,"line":1397},34,[67,1399,1400],{"class":73},"      plainKeyUserId,\n",[67,1402,1404],{"class":69,"line":1403},35,[67,1405,1406],{"class":73},"      userName\n",[67,1408,1410],{"class":69,"line":1409},36,[67,1411,1412],{"class":73},"    })\n",[67,1414,1416],{"class":69,"line":1415},37,[67,1417,537],{"class":73},[67,1419,1421],{"class":69,"line":1420},38,[67,1422,939],{"emptyLinePlaceholder":309},[67,1424,1426],{"class":69,"line":1425},39,[67,1427,1428],{"class":918},"  \u002F\u002F 3. For sign-in: Establish a session for the user\n",[67,1430,1432],{"class":69,"line":1431},40,[67,1433,1434],{"class":918},"  \u002F\u002F    (typically by creating a session and setting a first-party cookie)\n",[67,1436,1438,1441,1444],{"class":69,"line":1437},41,[67,1439,1440],{"class":924},"  await",[67,1442,1443],{"class":431}," establishUserSession",[67,1445,1446],{"class":73},"(response, user.id)\n",[67,1448,1450],{"class":69,"line":1449},42,[67,1451,939],{"emptyLinePlaceholder":309},[67,1453,1455,1458,1460,1463,1465],{"class":69,"line":1454},43,[67,1456,1457],{"class":73},"  response.",[67,1459,63],{"class":431},[67,1461,1462],{"class":73},"({ success: ",[67,1464,211],{"class":80},[67,1466,1467],{"class":73}," })\n",[67,1469,1471],{"class":69,"line":1470},44,[67,1472,1473],{"class":73},"})\n",[150,1475,1476],{},[13,1477,1478],{},"This example is intentionally simplified. You should add proper input validation and error handling in production.",[38,1480,1482],{"id":1481},"manage-users","Manage users",[46,1484,1486],{"className":909,"code":1485,"language":911,"meta":55,"style":55},"\u002F\u002F Get a user by their PlainKey user ID\nconst user = await plainKeyServer.getUser(\"user-id\")\n\n\u002F\u002F Find a user by userName\nconst user = await plainKeyServer.findUser(\"user@example.com\")\n\n\u002F\u002F Create a user\nconst user = await plainKeyServer.createUser(\"user@example.com\")\n\n\u002F\u002F Update a user's userName. Pass null to clear it.\nconst user = await plainKeyServer.updateUser({ userId: \"user-id\" }, { userName: \"new@example.com\" })\n\n\u002F\u002F Delete a user and all their passkeys\nawait plainKeyServer.deleteUser({ userId: \"user-id\" })\n",[53,1487,1488,1493,1517,1521,1526,1548,1552,1557,1578,1582,1587,1615,1619,1624],{"__ignoreMap":55},[67,1489,1490],{"class":69,"line":70},[67,1491,1492],{"class":918},"\u002F\u002F Get a user by their PlainKey user ID\n",[67,1494,1495,1498,1501,1503,1505,1507,1510,1512,1515],{"class":69,"line":77},[67,1496,1497],{"class":924},"const",[67,1499,1500],{"class":80}," user",[67,1502,953],{"class":924},[67,1504,1209],{"class":924},[67,1506,1212],{"class":73},[67,1508,1509],{"class":431},"getUser",[67,1511,962],{"class":73},[67,1513,1514],{"class":87},"\"user-id\"",[67,1516,973],{"class":73},[67,1518,1519],{"class":69,"line":94},[67,1520,939],{"emptyLinePlaceholder":309},[67,1522,1523],{"class":69,"line":107},[67,1524,1525],{"class":918},"\u002F\u002F Find a user by userName\n",[67,1527,1528,1530,1532,1534,1536,1538,1541,1543,1546],{"class":69,"line":118},[67,1529,1497],{"class":924},[67,1531,1500],{"class":80},[67,1533,953],{"class":924},[67,1535,1209],{"class":924},[67,1537,1212],{"class":73},[67,1539,1540],{"class":431},"findUser",[67,1542,962],{"class":73},[67,1544,1545],{"class":87},"\"user@example.com\"",[67,1547,973],{"class":73},[67,1549,1550],{"class":69,"line":528},[67,1551,939],{"emptyLinePlaceholder":309},[67,1553,1554],{"class":69,"line":534},[67,1555,1556],{"class":918},"\u002F\u002F Create a user\n",[67,1558,1559,1561,1563,1565,1567,1569,1572,1574,1576],{"class":69,"line":540},[67,1560,1497],{"class":924},[67,1562,1500],{"class":80},[67,1564,953],{"class":924},[67,1566,1209],{"class":924},[67,1568,1212],{"class":73},[67,1570,1571],{"class":431},"createUser",[67,1573,962],{"class":73},[67,1575,1545],{"class":87},[67,1577,973],{"class":73},[67,1579,1580],{"class":69,"line":1138},[67,1581,939],{"emptyLinePlaceholder":309},[67,1583,1584],{"class":69,"line":1157},[67,1585,1586],{"class":918},"\u002F\u002F Update a user's userName. Pass null to clear it.\n",[67,1588,1589,1591,1593,1595,1597,1599,1602,1605,1607,1610,1613],{"class":69,"line":1162},[67,1590,1497],{"class":924},[67,1592,1500],{"class":80},[67,1594,953],{"class":924},[67,1596,1209],{"class":924},[67,1598,1212],{"class":73},[67,1600,1601],{"class":431},"updateUser",[67,1603,1604],{"class":73},"({ userId: ",[67,1606,1514],{"class":87},[67,1608,1609],{"class":73}," }, { userName: ",[67,1611,1612],{"class":87},"\"new@example.com\"",[67,1614,1467],{"class":73},[67,1616,1617],{"class":69,"line":1167},[67,1618,939],{"emptyLinePlaceholder":309},[67,1620,1621],{"class":69,"line":1173},[67,1622,1623],{"class":918},"\u002F\u002F Delete a user and all their passkeys\n",[67,1625,1626,1629,1631,1634,1636,1638],{"class":69,"line":1179},[67,1627,1628],{"class":924},"await",[67,1630,1212],{"class":73},[67,1632,1633],{"class":431},"deleteUser",[67,1635,1604],{"class":73},[67,1637,1514],{"class":87},[67,1639,1467],{"class":73},[13,1641,1642],{},"Users can be identified by their PlainKey user ID or their userName:",[46,1644,1646],{"className":909,"code":1645,"language":911,"meta":55,"style":55},"\u002F\u002F By PlainKey user ID\n{\n  userId: \"user-id\"\n}\n\n\u002F\u002F By userName\n{\n  userName: \"user@example.com\"\n}\n",[53,1647,1648,1653,1657,1667,1671,1675,1680,1684,1694],{"__ignoreMap":55},[67,1649,1650],{"class":69,"line":70},[67,1651,1652],{"class":918},"\u002F\u002F By PlainKey user ID\n",[67,1654,1655],{"class":69,"line":77},[67,1656,74],{"class":73},[67,1658,1659,1662,1664],{"class":69,"line":94},[67,1660,1661],{"class":431},"  userId",[67,1663,84],{"class":73},[67,1665,1666],{"class":87},"\"user-id\"\n",[67,1668,1669],{"class":69,"line":107},[67,1670,121],{"class":73},[67,1672,1673],{"class":69,"line":118},[67,1674,939],{"emptyLinePlaceholder":309},[67,1676,1677],{"class":69,"line":528},[67,1678,1679],{"class":918},"\u002F\u002F By userName\n",[67,1681,1682],{"class":69,"line":534},[67,1683,74],{"class":73},[67,1685,1686,1689,1691],{"class":69,"line":540},[67,1687,1688],{"class":431},"  userName",[67,1690,84],{"class":73},[67,1692,1693],{"class":87},"\"user@example.com\"\n",[67,1695,1696],{"class":69,"line":1138},[67,1697,121],{"class":73},[168,1699,1701],{"id":1700},"bulk-create-users","Bulk create users",[13,1703,1704],{},"Useful for migrating existing users to PlainKey. Pass an array of userNames.",[46,1706,1708],{"className":909,"code":1707,"language":911,"meta":55,"style":55},"const users = await plainKeyServer.bulkCreateUsers([\"user1@example.com\", \"user2@example.com\"])\n",[53,1709,1710],{"__ignoreMap":55},[67,1711,1712,1714,1717,1719,1721,1723,1726,1729,1732,1734,1737],{"class":69,"line":70},[67,1713,1497],{"class":924},[67,1715,1716],{"class":80}," users",[67,1718,953],{"class":924},[67,1720,1209],{"class":924},[67,1722,1212],{"class":73},[67,1724,1725],{"class":431},"bulkCreateUsers",[67,1727,1728],{"class":73},"([",[67,1730,1731],{"class":87},"\"user1@example.com\"",[67,1733,519],{"class":73},[67,1735,1736],{"class":87},"\"user2@example.com\"",[67,1738,1739],{"class":73},"])\n",[38,1741,1743],{"id":1742},"manage-passkeys","Manage passkeys",[46,1745,1747],{"className":909,"code":1746,"language":911,"meta":55,"style":55},"\u002F\u002F Get all passkeys for a user\nconst passkeys = await plainKeyServer.getUserCredentials(\"user-id\")\n\n\u002F\u002F Get a specific passkey\nconst passkey = await plainKeyServer.getCredential(\"credential-id\")\n\n\u002F\u002F Delete a passkey\nawait plainKeyServer.deleteCredential(\"credential-id\")\n\n\u002F\u002F Update a passkey's label. Pass null to clear it.\nawait plainKeyServer.updateCredentialLabel(\"credential-id\", \"My security key\")\n",[53,1748,1749,1754,1776,1780,1785,1808,1812,1817,1832,1836,1841],{"__ignoreMap":55},[67,1750,1751],{"class":69,"line":70},[67,1752,1753],{"class":918},"\u002F\u002F Get all passkeys for a user\n",[67,1755,1756,1758,1761,1763,1765,1767,1770,1772,1774],{"class":69,"line":77},[67,1757,1497],{"class":924},[67,1759,1760],{"class":80}," passkeys",[67,1762,953],{"class":924},[67,1764,1209],{"class":924},[67,1766,1212],{"class":73},[67,1768,1769],{"class":431},"getUserCredentials",[67,1771,962],{"class":73},[67,1773,1514],{"class":87},[67,1775,973],{"class":73},[67,1777,1778],{"class":69,"line":94},[67,1779,939],{"emptyLinePlaceholder":309},[67,1781,1782],{"class":69,"line":107},[67,1783,1784],{"class":918},"\u002F\u002F Get a specific passkey\n",[67,1786,1787,1789,1792,1794,1796,1798,1801,1803,1806],{"class":69,"line":118},[67,1788,1497],{"class":924},[67,1790,1791],{"class":80}," passkey",[67,1793,953],{"class":924},[67,1795,1209],{"class":924},[67,1797,1212],{"class":73},[67,1799,1800],{"class":431},"getCredential",[67,1802,962],{"class":73},[67,1804,1805],{"class":87},"\"credential-id\"",[67,1807,973],{"class":73},[67,1809,1810],{"class":69,"line":528},[67,1811,939],{"emptyLinePlaceholder":309},[67,1813,1814],{"class":69,"line":534},[67,1815,1816],{"class":918},"\u002F\u002F Delete a passkey\n",[67,1818,1819,1821,1823,1826,1828,1830],{"class":69,"line":540},[67,1820,1628],{"class":924},[67,1822,1212],{"class":73},[67,1824,1825],{"class":431},"deleteCredential",[67,1827,962],{"class":73},[67,1829,1805],{"class":87},[67,1831,973],{"class":73},[67,1833,1834],{"class":69,"line":1138},[67,1835,939],{"emptyLinePlaceholder":309},[67,1837,1838],{"class":69,"line":1157},[67,1839,1840],{"class":918},"\u002F\u002F Update a passkey's label. Pass null to clear it.\n",[67,1842,1843,1845,1847,1850,1852,1854,1856,1859],{"class":69,"line":1162},[67,1844,1628],{"class":924},[67,1846,1212],{"class":73},[67,1848,1849],{"class":431},"updateCredentialLabel",[67,1851,962],{"class":73},[67,1853,1805],{"class":87},[67,1855,519],{"class":73},[67,1857,1858],{"class":87},"\"My security key\"",[67,1860,973],{"class":73},[38,1862,1864],{"id":1863},"server-initiated-passkey-registration","Server-initiated passkey registration",[13,1866,1867],{},"You can start a passkey registration from your backend without the user authenticating with PlainKey first.",[13,1869,1870],{},"This is useful when you already know who the user is. For example, prompting an already signed-in user to add a passkey, or sending existing users an email to register one.",[46,1872,1874],{"className":909,"code":1873,"language":911,"meta":55,"style":55},"const { options, authenticationToken } = await plainKeyServer.beginCredentialRegistration({\n  userId: \"user-id\"\n})\n",[53,1875,1876,1903,1910],{"__ignoreMap":55},[67,1877,1878,1880,1882,1885,1887,1890,1892,1894,1896,1898,1901],{"class":69,"line":70},[67,1879,1497],{"class":924},[67,1881,1102],{"class":73},[67,1883,1884],{"class":80},"options",[67,1886,519],{"class":73},[67,1888,1889],{"class":80},"authenticationToken",[67,1891,1112],{"class":73},[67,1893,1115],{"class":924},[67,1895,1209],{"class":924},[67,1897,1212],{"class":73},[67,1899,1900],{"class":431},"beginCredentialRegistration",[67,1902,1394],{"class":73},[67,1904,1905,1908],{"class":69,"line":77},[67,1906,1907],{"class":73},"  userId: ",[67,1909,1666],{"class":87},[67,1911,1912],{"class":69,"line":94},[67,1913,1473],{"class":73},[13,1915,1916,1917,1919,1920,1922,1923,1926],{},"Pass both ",[53,1918,1884],{}," and ",[53,1921,1889],{}," to your frontend, then call ",[53,1924,1925],{},".completePasskeyRegistration()"," from the Browser SDK:",[46,1928,1930],{"className":909,"code":1929,"language":911,"meta":55,"style":55},"\u002F\u002F In your frontend\nconst { success, error } = await plainKey.completePasskeyRegistration(authenticationToken, options)\n",[53,1931,1932,1937],{"__ignoreMap":55},[67,1933,1934],{"class":69,"line":70},[67,1935,1936],{"class":918},"\u002F\u002F In your frontend\n",[67,1938,1939,1941,1943,1945,1947,1949,1951,1953,1955,1958,1961],{"class":69,"line":77},[67,1940,1497],{"class":924},[67,1942,1102],{"class":73},[67,1944,1192],{"class":80},[67,1946,519],{"class":73},[67,1948,1202],{"class":80},[67,1950,1112],{"class":73},[67,1952,1115],{"class":924},[67,1954,1209],{"class":924},[67,1956,1957],{"class":73}," plainKey.",[67,1959,1960],{"class":431},"completePasskeyRegistration",[67,1962,1963],{"class":73},"(authenticationToken, options)\n",[296,1965,1966],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":55,"searchDepth":77,"depth":77,"links":1968},[1969,1970,1971,1974,1977,1978],{"id":873,"depth":77,"text":874},{"id":896,"depth":77,"text":897},{"id":136,"depth":77,"text":137,"children":1972},[1973],{"id":1012,"depth":94,"text":1013},{"id":1481,"depth":77,"text":1482,"children":1975},[1976],{"id":1700,"depth":94,"text":1701},{"id":1742,"depth":77,"text":1743},{"id":1863,"depth":77,"text":1864},"2026-01-20","Use the PlainKey Server SDK to verify authentication tokens and manage users and passkeys in your Node.js backend.",{},"\u002Fdocs\u002Fserver-sdk",{"title":857,"description":1980},"docs\u002Fserver-sdk","CET5HJd6BZFa6R7BcTiheIYN47ZftctjhEt8-hcRVyU",{"id":1987,"title":1988,"author":8,"body":1989,"date":1999,"description":2000,"extension":307,"image":8,"meta":2001,"navigation":309,"path":18,"seo":2002,"stem":2003,"tags":8,"__hash__":2004},"docs\u002Fdocs\u002Fserver.md","Server Setup",{"type":10,"value":1990,"toc":1997},[1991,1994],[1992,1993],"server-choice-cards",{},[13,1995,1996],{},"Select your backend technology to continue.",{"title":55,"searchDepth":77,"depth":77,"links":1998},[],"2026-01-15","PlainKey requires your backend to verify authentication tokens, and for managing users and passkeys.",{"avatar":8},{"title":1988,"description":2000},"docs\u002Fserver","wHZCLguNo2ysDkInrL2Dilz0A3tOrw8ImypmSODyx2g",{"id":2006,"title":144,"author":2007,"body":2008,"date":2811,"description":2812,"extension":307,"image":8,"meta":2813,"navigation":309,"path":143,"seo":2814,"stem":2815,"tags":8,"__hash__":2816},"docs\u002Fdocs\u002Fbrowser.md",{"name":7,"avatar":8},{"type":10,"value":2009,"toc":2800},[2010,2013,2017,2019,2033,2035,2076,2079,2083,2086,2089,2123,2126,2131,2138,2146,2151,2155,2158,2189,2192,2195,2272,2275,2280,2284,2293,2296,2476,2481,2484,2489,2491,2493,2500,2504,2507,2515,2522,2705,2707,2711,2716,2732,2781,2789,2793,2797],[13,2011,2012],{},"In your frontend, you will use the PlainKey Browser SDK. It handles user registration, passkey registration, and authentication.",[38,2014,2016],{"id":2015},"install-plainkey-browser-sdk","Install PlainKey Browser SDK",[13,2018,877],{},[46,2020,2022],{"className":422,"code":2021,"language":424,"meta":55,"style":55},"npm install @plainkey\u002Fbrowser\n",[53,2023,2024],{"__ignoreMap":55},[67,2025,2026,2028,2030],{"class":69,"line":70},[67,2027,887],{"class":431},[67,2029,890],{"class":87},[67,2031,2032],{"class":87}," @plainkey\u002Fbrowser\n",[38,2034,897],{"id":896},[46,2036,2038],{"className":909,"code":2037,"language":911,"meta":55,"style":55},"import { PlainKey } from \"@plainkey\u002Fbrowser\"\n\nconst plainKey = new PlainKey(\"YOUR_PROJECT_ID\")\n",[53,2039,2040,2052,2056],{"__ignoreMap":55},[67,2041,2042,2044,2047,2049],{"class":69,"line":70},[67,2043,925],{"class":924},[67,2045,2046],{"class":73}," { PlainKey } ",[67,2048,931],{"class":924},[67,2050,2051],{"class":87}," \"@plainkey\u002Fbrowser\"\n",[67,2053,2054],{"class":69,"line":77},[67,2055,939],{"emptyLinePlaceholder":309},[67,2057,2058,2060,2063,2065,2067,2070,2072,2074],{"class":69,"line":94},[67,2059,1497],{"class":924},[67,2061,2062],{"class":80}," plainKey",[67,2064,953],{"class":924},[67,2066,956],{"class":924},[67,2068,2069],{"class":431}," PlainKey",[67,2071,962],{"class":73},[67,2073,965],{"class":87},[67,2075,973],{"class":73},[13,2077,2078],{},"You can find your project ID on the PlainKey admin dashboard.",[38,2080,2082],{"id":2081},"create-user-with-passkey","Create user with passkey",[13,2084,2085],{},"While your database is the source of truth for your users, you must also register them as users in PlainKey. A PlainKey user can have multiple passkeys.",[13,2087,2088],{},"Registration of a brand new user can be done directly in your frontend, at the same time as the registration of their first passkey.",[46,2090,2092],{"className":909,"code":2091,"language":911,"meta":55,"style":55},"const { data, error } = await plainKey.createUserWithPasskey(\"user@example.com\")\n",[53,2093,2094],{"__ignoreMap":55},[67,2095,2096,2098,2100,2102,2104,2106,2108,2110,2112,2114,2117,2119,2121],{"class":69,"line":70},[67,2097,1497],{"class":924},[67,2099,1102],{"class":73},[67,2101,1197],{"class":80},[67,2103,519],{"class":73},[67,2105,1202],{"class":80},[67,2107,1112],{"class":73},[67,2109,1115],{"class":924},[67,2111,1209],{"class":924},[67,2113,1957],{"class":73},[67,2115,2116],{"class":431},"createUserWithPasskey",[67,2118,962],{"class":73},[67,2120,1545],{"class":87},[67,2122,973],{"class":73},[13,2124,2125],{},"This will make the browser prompt the user to create a passkey.",[150,2127,2128],{},[13,2129,2130],{},"The \"userName\" parameter is an informational field like an email address or user name. It is used as a label for the passkey.\nIt is usually visible to the user when the browser prompts them to choose a passkey to authenticate with. In PlainKey it is unique within a project.",[13,2132,2133,2134,2137],{},"On success, the user is created, their passkey is registered, and the user is authenticated. The response contains an ",[27,2135,2136],{},"authentication token"," to be verified in your backend.",[13,2139,2140,2141,2145],{},"Follow the ",[16,2142,2144],{"href":2143},"#on-authentication-success","\"On authentication success\""," section for what to do next.",[150,2147,2148],{},[13,2149,2150],{},"It is also possible to create users through the PlainKey Server SDK or API.\nThis is useful if you want to create a user without the user having to register a passkey at the same time, or for creating already existing users from your database.",[38,2152,2154],{"id":2153},"authenticate-user","Authenticate user",[13,2156,2157],{},"A user must have been registered in PlainKey with a passkey before they can be authenticated.",[46,2159,2161],{"className":909,"code":2160,"language":911,"meta":55,"style":55},"const { data, error } = await plainKey.authenticate()\n",[53,2162,2163],{"__ignoreMap":55},[67,2164,2165,2167,2169,2171,2173,2175,2177,2179,2181,2183,2186],{"class":69,"line":70},[67,2166,1497],{"class":924},[67,2168,1102],{"class":73},[67,2170,1197],{"class":80},[67,2172,519],{"class":73},[67,2174,1202],{"class":80},[67,2176,1112],{"class":73},[67,2178,1115],{"class":924},[67,2180,1209],{"class":924},[67,2182,1957],{"class":73},[67,2184,2185],{"class":431},"authenticate",[67,2187,2188],{"class":73},"()\n",[13,2190,2191],{},"By not passing any parameters to .authenticate(), the browser will prompt the user to authenticate with any passkey stored on their device for the current domain. This is recommended for sign-in. The user doesn't have to enter their username or email address.",[13,2193,2194],{},"You can also pass the PlainKey User ID or userName to .authenticate(), which will restrict the authentication to that user's passkeys.",[46,2196,2198],{"className":909,"code":2197,"language":911,"meta":55,"style":55},"\u002F\u002F By PlainKey User ID\nconst { data, error } = await plainKey.authenticate({ userId: \"user-id-here\" })\n\n\u002F\u002F Or by user name\nconst { data, error } = await plainKey.authenticate({ userName: \"user@example.com\" })\n",[53,2199,2200,2205,2234,2238,2243],{"__ignoreMap":55},[67,2201,2202],{"class":69,"line":70},[67,2203,2204],{"class":918},"\u002F\u002F By PlainKey User ID\n",[67,2206,2207,2209,2211,2213,2215,2217,2219,2221,2223,2225,2227,2229,2232],{"class":69,"line":77},[67,2208,1497],{"class":924},[67,2210,1102],{"class":73},[67,2212,1197],{"class":80},[67,2214,519],{"class":73},[67,2216,1202],{"class":80},[67,2218,1112],{"class":73},[67,2220,1115],{"class":924},[67,2222,1209],{"class":924},[67,2224,1957],{"class":73},[67,2226,2185],{"class":431},[67,2228,1604],{"class":73},[67,2230,2231],{"class":87},"\"user-id-here\"",[67,2233,1467],{"class":73},[67,2235,2236],{"class":69,"line":94},[67,2237,939],{"emptyLinePlaceholder":309},[67,2239,2240],{"class":69,"line":107},[67,2241,2242],{"class":918},"\u002F\u002F Or by user name\n",[67,2244,2245,2247,2249,2251,2253,2255,2257,2259,2261,2263,2265,2268,2270],{"class":69,"line":118},[67,2246,1497],{"class":924},[67,2248,1102],{"class":73},[67,2250,1197],{"class":80},[67,2252,519],{"class":73},[67,2254,1202],{"class":80},[67,2256,1112],{"class":73},[67,2258,1115],{"class":924},[67,2260,1209],{"class":924},[67,2262,1957],{"class":73},[67,2264,2185],{"class":431},[67,2266,2267],{"class":73},"({ userName: ",[67,2269,1545],{"class":87},[67,2271,1467],{"class":73},[13,2273,2274],{},"Use this when you need to authenticate a specific user and already know their identity. For example, if they are already signed in on an admin panel.",[150,2276,2277],{},[13,2278,2279],{},"If you opt to use userName to scope authentication attempts, you must make sure that any future changes to the user's userName in your database are also updated to PlainKey.",[38,2281,2283],{"id":2282},"on-authentication-success","On authentication success",[13,2285,2286,2287,2289,2290,2292],{},"On authentication success, the result includes a ",[27,2288,1197],{}," object, which contains an ",[27,2291,1889],{}," object.",[13,2294,2295],{},"It must be passed to your backend so it can verify the token and learn which user it belongs to.",[46,2297,2299],{"className":909,"code":2298,"language":911,"meta":55,"style":55},"const { data, error } = await plainKey.authenticate() \u002F\u002F or .createUserWithPasskey() or .addPasskey()\n\nif (error) {\n  \u002F\u002F Method will not throw an error. Handle error as you see fit.\n  console.error(error)\n  return\n}\n\nif (data) {\n  const authenticationToken: string = data.authenticationToken.token\n\n  \u002F\u002F Call your backend API to verify the authentication token. Do not store the token.\n  \u002F\u002F On signup you'd typically pass in a userName or some identity information to the endpoint here too.\n  await fetch(\"\u002Fapi\u002Fauth\u002Fexchange\", {\n    method: \"POST\",\n    body: JSON.stringify({ token: authenticationToken }),\n    headers: {\n      \"Content-Type\": \"application\u002Fjson\"\n    }\n  })\n}\n",[53,2300,2301,2329,2333,2341,2346,2356,2361,2365,2369,2376,2394,2398,2403,2408,2422,2432,2448,2453,2463,2467,2472],{"__ignoreMap":55},[67,2302,2303,2305,2307,2309,2311,2313,2315,2317,2319,2321,2323,2326],{"class":69,"line":70},[67,2304,1497],{"class":924},[67,2306,1102],{"class":73},[67,2308,1197],{"class":80},[67,2310,519],{"class":73},[67,2312,1202],{"class":80},[67,2314,1112],{"class":73},[67,2316,1115],{"class":924},[67,2318,1209],{"class":924},[67,2320,1957],{"class":73},[67,2322,2185],{"class":431},[67,2324,2325],{"class":73},"() ",[67,2327,2328],{"class":918},"\u002F\u002F or .createUserWithPasskey() or .addPasskey()\n",[67,2330,2331],{"class":69,"line":77},[67,2332,939],{"emptyLinePlaceholder":309},[67,2334,2335,2338],{"class":69,"line":94},[67,2336,2337],{"class":924},"if",[67,2339,2340],{"class":73}," (error) {\n",[67,2342,2343],{"class":69,"line":107},[67,2344,2345],{"class":918},"  \u002F\u002F Method will not throw an error. Handle error as you see fit.\n",[67,2347,2348,2351,2353],{"class":69,"line":118},[67,2349,2350],{"class":73},"  console.",[67,2352,1202],{"class":431},[67,2354,2355],{"class":73},"(error)\n",[67,2357,2358],{"class":69,"line":528},[67,2359,2360],{"class":924},"  return\n",[67,2362,2363],{"class":69,"line":534},[67,2364,121],{"class":73},[67,2366,2367],{"class":69,"line":540},[67,2368,939],{"emptyLinePlaceholder":309},[67,2370,2371,2373],{"class":69,"line":1138},[67,2372,2337],{"class":924},[67,2374,2375],{"class":73}," (data) {\n",[67,2377,2378,2380,2383,2386,2389,2391],{"class":69,"line":1157},[67,2379,1099],{"class":924},[67,2381,2382],{"class":80}," authenticationToken",[67,2384,2385],{"class":924},":",[67,2387,2388],{"class":80}," string",[67,2390,953],{"class":924},[67,2392,2393],{"class":73}," data.authenticationToken.token\n",[67,2395,2396],{"class":69,"line":1162},[67,2397,939],{"emptyLinePlaceholder":309},[67,2399,2400],{"class":69,"line":1167},[67,2401,2402],{"class":918},"  \u002F\u002F Call your backend API to verify the authentication token. Do not store the token.\n",[67,2404,2405],{"class":69,"line":1173},[67,2406,2407],{"class":918},"  \u002F\u002F On signup you'd typically pass in a userName or some identity information to the endpoint here too.\n",[67,2409,2410,2412,2415,2417,2419],{"class":69,"line":1179},[67,2411,1440],{"class":924},[67,2413,2414],{"class":431}," fetch",[67,2416,962],{"class":73},[67,2418,1063],{"class":87},[67,2420,2421],{"class":73},", {\n",[67,2423,2424,2427,2430],{"class":69,"line":1185},[67,2425,2426],{"class":73},"    method: ",[67,2428,2429],{"class":87},"\"POST\"",[67,2431,91],{"class":73},[67,2433,2434,2437,2440,2442,2445],{"class":69,"line":1221},[67,2435,2436],{"class":73},"    body: ",[67,2438,2439],{"class":80},"JSON",[67,2441,36],{"class":73},[67,2443,2444],{"class":431},"stringify",[67,2446,2447],{"class":73},"({ token: authenticationToken }),\n",[67,2449,2450],{"class":69,"line":1226},[67,2451,2452],{"class":73},"    headers: {\n",[67,2454,2455,2458,2460],{"class":69,"line":1238},[67,2456,2457],{"class":87},"      \"Content-Type\"",[67,2459,84],{"class":73},[67,2461,2462],{"class":87},"\"application\u002Fjson\"\n",[67,2464,2465],{"class":69,"line":1260},[67,2466,531],{"class":73},[67,2468,2469],{"class":69,"line":1265},[67,2470,2471],{"class":73},"  })\n",[67,2473,2474],{"class":69,"line":1270},[67,2475,121],{"class":73},[162,2477,2478],{},[13,2479,2480],{},"Your frontend must not rely on the successful response for authentication alone. Always verify the token in your backend.\nDo not store the token in any database or storage. Always keep it in memory.",[13,2482,2483],{},"In the backend, you verify the authentication token using the PlainKey Server SDK or API.",[13,2485,2486,2487,1252],{},"This will return the user's PlainKey User ID, which you use to find or create the user in your database. The user ID is a UUID (for example: ",[53,2488,157],{},[13,2490,160],{},[13,2492,1005],{},[13,2494,2495,2496,2499],{},"Go to ",[16,2497,2498],{"href":18},"Server Setup -->"," to see how to verify the authentication token in your backend.",[38,2501,2503],{"id":2502},"add-passkey-to-existing-user","Add passkey to existing user",[13,2505,2506],{},"A PlainKey user can have multiple passkeys.",[13,2508,2509,2510,2514],{},"To add a new passkey, the user must first be authenticated. Follow the ",[16,2511,2513],{"href":2512},"#authenticate-user","\"Authenticate user\""," section to do this.",[13,2516,2517,2518,2521],{},"Once authenticated, call ",[53,2519,2520],{},".addPasskey()"," using the returned authentication token.",[46,2523,2525],{"className":909,"code":2524,"language":911,"meta":55,"style":55},"\u002F\u002F 1. Authenticate the user\nconst { data: authData, error: authError } = await plainKey.authenticate({\n  userName: \"user@example.com\"\n})\n\nif (authError) {\n  \u002F\u002F Method will not throw, but return an error object.\n  \u002F\u002F Handle error as you see fit.\n  console.error(authError)\n  return\n}\n\n\u002F\u002F 2. Create a new passkey using the returned authentication token\nif (authData) {\n  const token = authData.authenticationToken.token\n  const { success, error } = await plainKey.addPasskey(token)\n\n  if (error) {\n    \u002F\u002F Handle error as you see fit.\n    console.error(error)\n    return\n  }\n}\n",[53,2526,2527,2532,2566,2573,2577,2581,2588,2593,2598,2607,2611,2615,2619,2624,2631,2643,2668,2672,2678,2683,2692,2697,2701],{"__ignoreMap":55},[67,2528,2529],{"class":69,"line":70},[67,2530,2531],{"class":918},"\u002F\u002F 1. Authenticate the user\n",[67,2533,2534,2536,2538,2540,2542,2545,2547,2549,2551,2554,2556,2558,2560,2562,2564],{"class":69,"line":77},[67,2535,1497],{"class":924},[67,2537,1102],{"class":73},[67,2539,1197],{"class":1074},[67,2541,84],{"class":73},[67,2543,2544],{"class":80},"authData",[67,2546,519],{"class":73},[67,2548,1202],{"class":1074},[67,2550,84],{"class":73},[67,2552,2553],{"class":80},"authError",[67,2555,1112],{"class":73},[67,2557,1115],{"class":924},[67,2559,1209],{"class":924},[67,2561,1957],{"class":73},[67,2563,2185],{"class":431},[67,2565,1394],{"class":73},[67,2567,2568,2571],{"class":69,"line":94},[67,2569,2570],{"class":73},"  userName: ",[67,2572,1693],{"class":87},[67,2574,2575],{"class":69,"line":107},[67,2576,1473],{"class":73},[67,2578,2579],{"class":69,"line":118},[67,2580,939],{"emptyLinePlaceholder":309},[67,2582,2583,2585],{"class":69,"line":528},[67,2584,2337],{"class":924},[67,2586,2587],{"class":73}," (authError) {\n",[67,2589,2590],{"class":69,"line":534},[67,2591,2592],{"class":918},"  \u002F\u002F Method will not throw, but return an error object.\n",[67,2594,2595],{"class":69,"line":540},[67,2596,2597],{"class":918},"  \u002F\u002F Handle error as you see fit.\n",[67,2599,2600,2602,2604],{"class":69,"line":1138},[67,2601,2350],{"class":73},[67,2603,1202],{"class":431},[67,2605,2606],{"class":73},"(authError)\n",[67,2608,2609],{"class":69,"line":1157},[67,2610,2360],{"class":924},[67,2612,2613],{"class":69,"line":1162},[67,2614,121],{"class":73},[67,2616,2617],{"class":69,"line":1167},[67,2618,939],{"emptyLinePlaceholder":309},[67,2620,2621],{"class":69,"line":1173},[67,2622,2623],{"class":918},"\u002F\u002F 2. Create a new passkey using the returned authentication token\n",[67,2625,2626,2628],{"class":69,"line":1179},[67,2627,2337],{"class":924},[67,2629,2630],{"class":73}," (authData) {\n",[67,2632,2633,2635,2638,2640],{"class":69,"line":1185},[67,2634,1099],{"class":924},[67,2636,2637],{"class":80}," token",[67,2639,953],{"class":924},[67,2641,2642],{"class":73}," authData.authenticationToken.token\n",[67,2644,2645,2647,2649,2651,2653,2655,2657,2659,2661,2663,2666],{"class":69,"line":1221},[67,2646,1099],{"class":924},[67,2648,1102],{"class":73},[67,2650,1192],{"class":80},[67,2652,519],{"class":73},[67,2654,1202],{"class":80},[67,2656,1112],{"class":73},[67,2658,1115],{"class":924},[67,2660,1209],{"class":924},[67,2662,1957],{"class":73},[67,2664,2665],{"class":431},"addPasskey",[67,2667,1218],{"class":73},[67,2669,2670],{"class":69,"line":1226},[67,2671,939],{"emptyLinePlaceholder":309},[67,2673,2674,2676],{"class":69,"line":1238},[67,2675,1127],{"class":924},[67,2677,2340],{"class":73},[67,2679,2680],{"class":69,"line":1260},[67,2681,2682],{"class":918},"    \u002F\u002F Handle error as you see fit.\n",[67,2684,2685,2688,2690],{"class":69,"line":1265},[67,2686,2687],{"class":73},"    console.",[67,2689,1202],{"class":431},[67,2691,2355],{"class":73},[67,2693,2694],{"class":69,"line":1270},[67,2695,2696],{"class":924},"    return\n",[67,2698,2699],{"class":69,"line":1283},[67,2700,537],{"class":73},[67,2702,2703],{"class":69,"line":1288},[67,2704,121],{"class":73},[13,2706,2125],{},[168,2708,2710],{"id":2709},"optional-provide-a-username","Optional: Provide a userName",[13,2712,2713,2715],{},[53,2714,2520],{}," accepts an optional userName parameter. The userName is a label stored on the passkey.",[364,2717,2718,2725],{},[360,2719,2720,2721,2724],{},"If a userName is ",[27,2722,2723],{},"not"," provided, the user's stored userName is used.",[360,2726,2727,2728,2731],{},"If a userName ",[27,2729,2730],{},"is"," provided, it is used for the new passkey. It does not update the user's stored userName.",[46,2733,2735],{"className":909,"code":2734,"language":911,"meta":55,"style":55},"\u002F\u002F Provide a userName to override the user's stored userName.\nconst { success, error } = await plainKey.addPasskey(\n  authData.authenticationToken.token,\n  \"user@example.com\"\n)\n",[53,2736,2737,2742,2767,2772,2777],{"__ignoreMap":55},[67,2738,2739],{"class":69,"line":70},[67,2740,2741],{"class":918},"\u002F\u002F Provide a userName to override the user's stored userName.\n",[67,2743,2744,2746,2748,2750,2752,2754,2756,2758,2760,2762,2764],{"class":69,"line":77},[67,2745,1497],{"class":924},[67,2747,1102],{"class":73},[67,2749,1192],{"class":80},[67,2751,519],{"class":73},[67,2753,1202],{"class":80},[67,2755,1112],{"class":73},[67,2757,1115],{"class":924},[67,2759,1209],{"class":924},[67,2761,1957],{"class":73},[67,2763,2665],{"class":431},[67,2765,2766],{"class":73},"(\n",[67,2768,2769],{"class":69,"line":94},[67,2770,2771],{"class":73},"  authData.authenticationToken.token,\n",[67,2773,2774],{"class":69,"line":107},[67,2775,2776],{"class":87},"  \"user@example.com\"\n",[67,2778,2779],{"class":69,"line":118},[67,2780,973],{"class":73},[150,2782,2783,2786],{},[13,2784,2785],{},"You can also initiate passkey registration from your backend using the PlainKey Server SDK or REST API.",[13,2787,2788],{},"This is useful when you already know who the user is, for example when prompting an already signed-in user to add a passkey, or sending existing users an email to register one.",[38,2790,2792],{"id":2791},"next-step","Next step",[13,2794,2795],{},[16,2796,2498],{"href":18},[296,2798,2799],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":55,"searchDepth":77,"depth":77,"links":2801},[2802,2803,2804,2805,2806,2807,2810],{"id":2015,"depth":77,"text":2016},{"id":896,"depth":77,"text":897},{"id":2081,"depth":77,"text":2082},{"id":2153,"depth":77,"text":2154},{"id":2282,"depth":77,"text":2283},{"id":2502,"depth":77,"text":2503,"children":2808},[2809],{"id":2709,"depth":94,"text":2710},{"id":2791,"depth":77,"text":2792},"2026-01-07","Learn how to use the PlainKey Browser SDK to add passkey authentication to your app.",{},{"title":144,"description":2812},"docs\u002Fbrowser","dhtM_QQyoUMCoYjOkN8mg1YOUriFYt5gQnclzQvE6BE",{"id":2818,"title":2819,"author":2820,"body":2821,"date":2909,"description":2910,"extension":307,"image":8,"meta":2911,"navigation":309,"path":2912,"seo":2913,"stem":2914,"tags":8,"__hash__":2915},"docs\u002Fdocs\u002Fgetting-started.md","Getting started with PlainKey",{"name":7,"avatar":8},{"type":10,"value":2822,"toc":2904},[2823,2827,2842,2846,2855,2868,2871,2888,2897,2899],[38,2824,2826],{"id":2825},"prerequisites","Prerequisites",[364,2828,2829,2836,2839],{},[360,2830,2831,2832,2835],{},"A web application that can use packages from the npm registry and run JavaScript or TypeScript.",[2833,2834],"br",{},"This includes frameworks like React, Next.js, Vue.js, Nuxt.js, Angular, Svelte, and more.",[360,2837,2838],{},"A database where you store your users",[360,2840,2841],{},"A backend connected to your user database. It must be able to call our REST API or use our JavaScript\u002FTypeScript SDK.",[38,2843,2845],{"id":2844},"sign-up-with-plainkey","Sign up with PlainKey",[13,2847,2848,2849,36],{},"Begin with ",[16,2850,2854],{"href":2851,"rel":2852,"target":2853},"https:\u002F\u002Fplainkey.io\u002Fsignup",[328],"\\_blank","signing up at plainkey.io",[364,2856,2857],{},[360,2858,2859,2860,2863,2864,2867],{},"During sign-up, enter the domain name where you will implement passkeys (i.e. ",[53,2861,2862],{},"example.com","). You can use a subdomain (like ",[53,2865,2866],{},"admin.example.com","), but then passkeys registered on that subdomain will only work on that subdomain.",[13,2869,2870],{},"PlainKey will create your first project. From the project settings, you can generate your client secret.",[364,2872,2873,2879],{},[360,2874,2875,2878],{},[27,2876,2877],{},"Project ID",": Identifies your project when using the SDK\u002FAPIs. Used in both frontend and backend requests.",[360,2880,2881,2884,2885],{},[27,2882,2883],{},"Client secret",": Used to get an access token for backend requests. It is scoped to the project. ",[27,2886,2887],{},"Keep this secret safe and never share it.",[150,2889,2890],{},[13,2891,2892,2893,2896],{},"For local development, you can create a new project and use ",[53,2894,2895],{},"localhost"," as the domain.",[38,2898,2792],{"id":2791},[13,2900,2901],{},[16,2902,2903],{"href":143},"Browser SDK --> ",{"title":55,"searchDepth":77,"depth":77,"links":2905},[2906,2907,2908],{"id":2825,"depth":77,"text":2826},{"id":2844,"depth":77,"text":2845},{"id":2791,"depth":77,"text":2792},"2026-01-01","Learn how to quickly add passkey authentication to your website.",{},"\u002Fdocs\u002Fgetting-started",{"title":2819,"description":2910},"docs\u002Fgetting-started","BtQXWhbzI0ndOemNlCt_RnYCNROJ2t9w8vT9ayBcH7o",[2917,2981,3660,3671,4565,4769],{"id":2818,"title":2819,"author":2918,"body":2919,"date":2909,"description":2910,"extension":307,"image":8,"meta":2979,"navigation":309,"path":2912,"seo":2980,"stem":2914,"tags":8,"__hash__":2915},{"name":7,"avatar":8},{"type":10,"value":2920,"toc":2974},[2921,2923,2933,2935,2940,2948,2950,2962,2968,2970],[38,2922,2826],{"id":2825},[364,2924,2925,2929,2931],{},[360,2926,2831,2927,2835],{},[2833,2928],{},[360,2930,2838],{},[360,2932,2841],{},[38,2934,2845],{"id":2844},[13,2936,2848,2937,36],{},[16,2938,2854],{"href":2851,"rel":2939,"target":2853},[328],[364,2941,2942],{},[360,2943,2859,2944,2863,2946,2867],{},[53,2945,2862],{},[53,2947,2866],{},[13,2949,2870],{},[364,2951,2952,2956],{},[360,2953,2954,2878],{},[27,2955,2877],{},[360,2957,2958,2884,2960],{},[27,2959,2883],{},[27,2961,2887],{},[150,2963,2964],{},[13,2965,2892,2966,2896],{},[53,2967,2895],{},[38,2969,2792],{"id":2791},[13,2971,2972],{},[16,2973,2903],{"href":143},{"title":55,"searchDepth":77,"depth":77,"links":2975},[2976,2977,2978],{"id":2825,"depth":77,"text":2826},{"id":2844,"depth":77,"text":2845},{"id":2791,"depth":77,"text":2792},{},{"title":2819,"description":2910},{"id":2006,"title":144,"author":2982,"body":2983,"date":2811,"description":2812,"extension":307,"image":8,"meta":3658,"navigation":309,"path":143,"seo":3659,"stem":2815,"tags":8,"__hash__":2816},{"name":7,"avatar":8},{"type":10,"value":2984,"toc":3647},[2985,2987,2989,2991,3003,3005,3041,3043,3045,3047,3049,3081,3083,3087,3091,3095,3099,3101,3103,3131,3133,3135,3207,3209,3213,3215,3221,3223,3375,3379,3381,3385,3387,3389,3393,3395,3397,3401,3405,3571,3573,3575,3579,3589,3633,3639,3641,3645],[13,2986,2012],{},[38,2988,2016],{"id":2015},[13,2990,877],{},[46,2992,2993],{"className":422,"code":2021,"language":424,"meta":55,"style":55},[53,2994,2995],{"__ignoreMap":55},[67,2996,2997,2999,3001],{"class":69,"line":70},[67,2998,887],{"class":431},[67,3000,890],{"class":87},[67,3002,2032],{"class":87},[38,3004,897],{"id":896},[46,3006,3007],{"className":909,"code":2037,"language":911,"meta":55,"style":55},[53,3008,3009,3019,3023],{"__ignoreMap":55},[67,3010,3011,3013,3015,3017],{"class":69,"line":70},[67,3012,925],{"class":924},[67,3014,2046],{"class":73},[67,3016,931],{"class":924},[67,3018,2051],{"class":87},[67,3020,3021],{"class":69,"line":77},[67,3022,939],{"emptyLinePlaceholder":309},[67,3024,3025,3027,3029,3031,3033,3035,3037,3039],{"class":69,"line":94},[67,3026,1497],{"class":924},[67,3028,2062],{"class":80},[67,3030,953],{"class":924},[67,3032,956],{"class":924},[67,3034,2069],{"class":431},[67,3036,962],{"class":73},[67,3038,965],{"class":87},[67,3040,973],{"class":73},[13,3042,2078],{},[38,3044,2082],{"id":2081},[13,3046,2085],{},[13,3048,2088],{},[46,3050,3051],{"className":909,"code":2091,"language":911,"meta":55,"style":55},[53,3052,3053],{"__ignoreMap":55},[67,3054,3055,3057,3059,3061,3063,3065,3067,3069,3071,3073,3075,3077,3079],{"class":69,"line":70},[67,3056,1497],{"class":924},[67,3058,1102],{"class":73},[67,3060,1197],{"class":80},[67,3062,519],{"class":73},[67,3064,1202],{"class":80},[67,3066,1112],{"class":73},[67,3068,1115],{"class":924},[67,3070,1209],{"class":924},[67,3072,1957],{"class":73},[67,3074,2116],{"class":431},[67,3076,962],{"class":73},[67,3078,1545],{"class":87},[67,3080,973],{"class":73},[13,3082,2125],{},[150,3084,3085],{},[13,3086,2130],{},[13,3088,2133,3089,2137],{},[27,3090,2136],{},[13,3092,2140,3093,2145],{},[16,3094,2144],{"href":2143},[150,3096,3097],{},[13,3098,2150],{},[38,3100,2154],{"id":2153},[13,3102,2157],{},[46,3104,3105],{"className":909,"code":2160,"language":911,"meta":55,"style":55},[53,3106,3107],{"__ignoreMap":55},[67,3108,3109,3111,3113,3115,3117,3119,3121,3123,3125,3127,3129],{"class":69,"line":70},[67,3110,1497],{"class":924},[67,3112,1102],{"class":73},[67,3114,1197],{"class":80},[67,3116,519],{"class":73},[67,3118,1202],{"class":80},[67,3120,1112],{"class":73},[67,3122,1115],{"class":924},[67,3124,1209],{"class":924},[67,3126,1957],{"class":73},[67,3128,2185],{"class":431},[67,3130,2188],{"class":73},[13,3132,2191],{},[13,3134,2194],{},[46,3136,3137],{"className":909,"code":2197,"language":911,"meta":55,"style":55},[53,3138,3139,3143,3171,3175,3179],{"__ignoreMap":55},[67,3140,3141],{"class":69,"line":70},[67,3142,2204],{"class":918},[67,3144,3145,3147,3149,3151,3153,3155,3157,3159,3161,3163,3165,3167,3169],{"class":69,"line":77},[67,3146,1497],{"class":924},[67,3148,1102],{"class":73},[67,3150,1197],{"class":80},[67,3152,519],{"class":73},[67,3154,1202],{"class":80},[67,3156,1112],{"class":73},[67,3158,1115],{"class":924},[67,3160,1209],{"class":924},[67,3162,1957],{"class":73},[67,3164,2185],{"class":431},[67,3166,1604],{"class":73},[67,3168,2231],{"class":87},[67,3170,1467],{"class":73},[67,3172,3173],{"class":69,"line":94},[67,3174,939],{"emptyLinePlaceholder":309},[67,3176,3177],{"class":69,"line":107},[67,3178,2242],{"class":918},[67,3180,3181,3183,3185,3187,3189,3191,3193,3195,3197,3199,3201,3203,3205],{"class":69,"line":118},[67,3182,1497],{"class":924},[67,3184,1102],{"class":73},[67,3186,1197],{"class":80},[67,3188,519],{"class":73},[67,3190,1202],{"class":80},[67,3192,1112],{"class":73},[67,3194,1115],{"class":924},[67,3196,1209],{"class":924},[67,3198,1957],{"class":73},[67,3200,2185],{"class":431},[67,3202,2267],{"class":73},[67,3204,1545],{"class":87},[67,3206,1467],{"class":73},[13,3208,2274],{},[150,3210,3211],{},[13,3212,2279],{},[38,3214,2283],{"id":2282},[13,3216,2286,3217,2289,3219,2292],{},[27,3218,1197],{},[27,3220,1889],{},[13,3222,2295],{},[46,3224,3225],{"className":909,"code":2298,"language":911,"meta":55,"style":55},[53,3226,3227,3253,3257,3263,3267,3275,3279,3283,3287,3293,3307,3311,3315,3319,3331,3339,3351,3355,3363,3367,3371],{"__ignoreMap":55},[67,3228,3229,3231,3233,3235,3237,3239,3241,3243,3245,3247,3249,3251],{"class":69,"line":70},[67,3230,1497],{"class":924},[67,3232,1102],{"class":73},[67,3234,1197],{"class":80},[67,3236,519],{"class":73},[67,3238,1202],{"class":80},[67,3240,1112],{"class":73},[67,3242,1115],{"class":924},[67,3244,1209],{"class":924},[67,3246,1957],{"class":73},[67,3248,2185],{"class":431},[67,3250,2325],{"class":73},[67,3252,2328],{"class":918},[67,3254,3255],{"class":69,"line":77},[67,3256,939],{"emptyLinePlaceholder":309},[67,3258,3259,3261],{"class":69,"line":94},[67,3260,2337],{"class":924},[67,3262,2340],{"class":73},[67,3264,3265],{"class":69,"line":107},[67,3266,2345],{"class":918},[67,3268,3269,3271,3273],{"class":69,"line":118},[67,3270,2350],{"class":73},[67,3272,1202],{"class":431},[67,3274,2355],{"class":73},[67,3276,3277],{"class":69,"line":528},[67,3278,2360],{"class":924},[67,3280,3281],{"class":69,"line":534},[67,3282,121],{"class":73},[67,3284,3285],{"class":69,"line":540},[67,3286,939],{"emptyLinePlaceholder":309},[67,3288,3289,3291],{"class":69,"line":1138},[67,3290,2337],{"class":924},[67,3292,2375],{"class":73},[67,3294,3295,3297,3299,3301,3303,3305],{"class":69,"line":1157},[67,3296,1099],{"class":924},[67,3298,2382],{"class":80},[67,3300,2385],{"class":924},[67,3302,2388],{"class":80},[67,3304,953],{"class":924},[67,3306,2393],{"class":73},[67,3308,3309],{"class":69,"line":1162},[67,3310,939],{"emptyLinePlaceholder":309},[67,3312,3313],{"class":69,"line":1167},[67,3314,2402],{"class":918},[67,3316,3317],{"class":69,"line":1173},[67,3318,2407],{"class":918},[67,3320,3321,3323,3325,3327,3329],{"class":69,"line":1179},[67,3322,1440],{"class":924},[67,3324,2414],{"class":431},[67,3326,962],{"class":73},[67,3328,1063],{"class":87},[67,3330,2421],{"class":73},[67,3332,3333,3335,3337],{"class":69,"line":1185},[67,3334,2426],{"class":73},[67,3336,2429],{"class":87},[67,3338,91],{"class":73},[67,3340,3341,3343,3345,3347,3349],{"class":69,"line":1221},[67,3342,2436],{"class":73},[67,3344,2439],{"class":80},[67,3346,36],{"class":73},[67,3348,2444],{"class":431},[67,3350,2447],{"class":73},[67,3352,3353],{"class":69,"line":1226},[67,3354,2452],{"class":73},[67,3356,3357,3359,3361],{"class":69,"line":1238},[67,3358,2457],{"class":87},[67,3360,84],{"class":73},[67,3362,2462],{"class":87},[67,3364,3365],{"class":69,"line":1260},[67,3366,531],{"class":73},[67,3368,3369],{"class":69,"line":1265},[67,3370,2471],{"class":73},[67,3372,3373],{"class":69,"line":1270},[67,3374,121],{"class":73},[162,3376,3377],{},[13,3378,2480],{},[13,3380,2483],{},[13,3382,2486,3383,1252],{},[53,3384,157],{},[13,3386,160],{},[13,3388,1005],{},[13,3390,2495,3391,2499],{},[16,3392,2498],{"href":18},[38,3394,2503],{"id":2502},[13,3396,2506],{},[13,3398,2509,3399,2514],{},[16,3400,2513],{"href":2512},[13,3402,2517,3403,2521],{},[53,3404,2520],{},[46,3406,3407],{"className":909,"code":2524,"language":911,"meta":55,"style":55},[53,3408,3409,3413,3445,3451,3455,3459,3465,3469,3473,3481,3485,3489,3493,3497,3503,3513,3537,3541,3547,3551,3559,3563,3567],{"__ignoreMap":55},[67,3410,3411],{"class":69,"line":70},[67,3412,2531],{"class":918},[67,3414,3415,3417,3419,3421,3423,3425,3427,3429,3431,3433,3435,3437,3439,3441,3443],{"class":69,"line":77},[67,3416,1497],{"class":924},[67,3418,1102],{"class":73},[67,3420,1197],{"class":1074},[67,3422,84],{"class":73},[67,3424,2544],{"class":80},[67,3426,519],{"class":73},[67,3428,1202],{"class":1074},[67,3430,84],{"class":73},[67,3432,2553],{"class":80},[67,3434,1112],{"class":73},[67,3436,1115],{"class":924},[67,3438,1209],{"class":924},[67,3440,1957],{"class":73},[67,3442,2185],{"class":431},[67,3444,1394],{"class":73},[67,3446,3447,3449],{"class":69,"line":94},[67,3448,2570],{"class":73},[67,3450,1693],{"class":87},[67,3452,3453],{"class":69,"line":107},[67,3454,1473],{"class":73},[67,3456,3457],{"class":69,"line":118},[67,3458,939],{"emptyLinePlaceholder":309},[67,3460,3461,3463],{"class":69,"line":528},[67,3462,2337],{"class":924},[67,3464,2587],{"class":73},[67,3466,3467],{"class":69,"line":534},[67,3468,2592],{"class":918},[67,3470,3471],{"class":69,"line":540},[67,3472,2597],{"class":918},[67,3474,3475,3477,3479],{"class":69,"line":1138},[67,3476,2350],{"class":73},[67,3478,1202],{"class":431},[67,3480,2606],{"class":73},[67,3482,3483],{"class":69,"line":1157},[67,3484,2360],{"class":924},[67,3486,3487],{"class":69,"line":1162},[67,3488,121],{"class":73},[67,3490,3491],{"class":69,"line":1167},[67,3492,939],{"emptyLinePlaceholder":309},[67,3494,3495],{"class":69,"line":1173},[67,3496,2623],{"class":918},[67,3498,3499,3501],{"class":69,"line":1179},[67,3500,2337],{"class":924},[67,3502,2630],{"class":73},[67,3504,3505,3507,3509,3511],{"class":69,"line":1185},[67,3506,1099],{"class":924},[67,3508,2637],{"class":80},[67,3510,953],{"class":924},[67,3512,2642],{"class":73},[67,3514,3515,3517,3519,3521,3523,3525,3527,3529,3531,3533,3535],{"class":69,"line":1221},[67,3516,1099],{"class":924},[67,3518,1102],{"class":73},[67,3520,1192],{"class":80},[67,3522,519],{"class":73},[67,3524,1202],{"class":80},[67,3526,1112],{"class":73},[67,3528,1115],{"class":924},[67,3530,1209],{"class":924},[67,3532,1957],{"class":73},[67,3534,2665],{"class":431},[67,3536,1218],{"class":73},[67,3538,3539],{"class":69,"line":1226},[67,3540,939],{"emptyLinePlaceholder":309},[67,3542,3543,3545],{"class":69,"line":1238},[67,3544,1127],{"class":924},[67,3546,2340],{"class":73},[67,3548,3549],{"class":69,"line":1260},[67,3550,2682],{"class":918},[67,3552,3553,3555,3557],{"class":69,"line":1265},[67,3554,2687],{"class":73},[67,3556,1202],{"class":431},[67,3558,2355],{"class":73},[67,3560,3561],{"class":69,"line":1270},[67,3562,2696],{"class":924},[67,3564,3565],{"class":69,"line":1283},[67,3566,537],{"class":73},[67,3568,3569],{"class":69,"line":1288},[67,3570,121],{"class":73},[13,3572,2125],{},[168,3574,2710],{"id":2709},[13,3576,3577,2715],{},[53,3578,2520],{},[364,3580,3581,3585],{},[360,3582,2720,3583,2724],{},[27,3584,2723],{},[360,3586,2727,3587,2731],{},[27,3588,2730],{},[46,3590,3591],{"className":909,"code":2734,"language":911,"meta":55,"style":55},[53,3592,3593,3597,3621,3625,3629],{"__ignoreMap":55},[67,3594,3595],{"class":69,"line":70},[67,3596,2741],{"class":918},[67,3598,3599,3601,3603,3605,3607,3609,3611,3613,3615,3617,3619],{"class":69,"line":77},[67,3600,1497],{"class":924},[67,3602,1102],{"class":73},[67,3604,1192],{"class":80},[67,3606,519],{"class":73},[67,3608,1202],{"class":80},[67,3610,1112],{"class":73},[67,3612,1115],{"class":924},[67,3614,1209],{"class":924},[67,3616,1957],{"class":73},[67,3618,2665],{"class":431},[67,3620,2766],{"class":73},[67,3622,3623],{"class":69,"line":94},[67,3624,2771],{"class":73},[67,3626,3627],{"class":69,"line":107},[67,3628,2776],{"class":87},[67,3630,3631],{"class":69,"line":118},[67,3632,973],{"class":73},[150,3634,3635,3637],{},[13,3636,2785],{},[13,3638,2788],{},[38,3640,2792],{"id":2791},[13,3642,3643],{},[16,3644,2498],{"href":18},[296,3646,2799],{},{"title":55,"searchDepth":77,"depth":77,"links":3648},[3649,3650,3651,3652,3653,3654,3657],{"id":2015,"depth":77,"text":2016},{"id":896,"depth":77,"text":897},{"id":2081,"depth":77,"text":2082},{"id":2153,"depth":77,"text":2154},{"id":2282,"depth":77,"text":2283},{"id":2502,"depth":77,"text":2503,"children":3655},[3656],{"id":2709,"depth":94,"text":2710},{"id":2791,"depth":77,"text":2792},{},{"title":144,"description":2812},{"id":1987,"title":1988,"author":8,"body":3661,"date":1999,"description":2000,"extension":307,"image":8,"meta":3669,"navigation":309,"path":18,"seo":3670,"stem":2003,"tags":8,"__hash__":2004},{"type":10,"value":3662,"toc":3667},[3663,3665],[1992,3664],{},[13,3666,1996],{},{"title":55,"searchDepth":77,"depth":77,"links":3668},[],{"avatar":8},{"title":1988,"description":2000},{"id":856,"title":857,"author":3672,"body":3673,"date":1979,"description":1980,"extension":307,"image":8,"meta":4563,"navigation":309,"path":1982,"seo":4564,"stem":1984,"tags":8,"__hash__":1985},{"name":7,"avatar":8},{"type":10,"value":3674,"toc":4551},[3675,3679,3681,3683,3685,3687,3699,3701,3703,3705,3707,3753,3757,3759,3763,3767,3769,3775,3777,3779,3783,3785,3787,3789,3797,4133,4137,4139,4277,4279,4327,4329,4331,4359,4361,4465,4467,4469,4471,4509,4517,4549],[13,3676,3677],{},[16,3678,19],{"href":18},[13,3680,867],{},[13,3682,870],{},[38,3684,874],{"id":873},[13,3686,877],{},[46,3688,3689],{"className":422,"code":880,"language":424,"meta":55,"style":55},[53,3690,3691],{"__ignoreMap":55},[67,3692,3693,3695,3697],{"class":69,"line":70},[67,3694,887],{"class":431},[67,3696,890],{"class":87},[67,3698,893],{"class":87},[38,3700,897],{"id":896},[13,3702,900],{},[13,3704,903],{},[13,3706,906],{},[46,3708,3709],{"className":909,"code":910,"language":911,"meta":55,"style":55},[53,3710,3711,3715,3725,3729],{"__ignoreMap":55},[67,3712,3713],{"class":69,"line":70},[67,3714,919],{"class":918},[67,3716,3717,3719,3721,3723],{"class":69,"line":77},[67,3718,925],{"class":924},[67,3720,928],{"class":73},[67,3722,931],{"class":924},[67,3724,934],{"class":87},[67,3726,3727],{"class":69,"line":94},[67,3728,939],{"emptyLinePlaceholder":309},[67,3730,3731,3733,3735,3737,3739,3741,3743,3745,3747,3749,3751],{"class":69,"line":107},[67,3732,944],{"class":924},[67,3734,947],{"class":924},[67,3736,950],{"class":80},[67,3738,953],{"class":924},[67,3740,956],{"class":924},[67,3742,959],{"class":431},[67,3744,962],{"class":73},[67,3746,965],{"class":87},[67,3748,519],{"class":73},[67,3750,970],{"class":87},[67,3752,973],{"class":73},[150,3754,3755],{},[13,3756,978],{},[38,3758,137],{"id":136},[13,3760,140,3761,145],{},[16,3762,144],{"href":143},[13,3764,987,3765,991],{},[53,3766,990],{},[13,3768,994],{},[150,3770,3771],{},[13,3772,154,3773,36],{},[53,3774,157],{},[13,3776,160],{},[13,3778,1005],{},[162,3780,3781],{},[13,3782,166],{},[168,3784,1013],{"id":1012},[13,3786,1016],{},[13,3788,1019],{},[357,3790,3791,3793,3795],{},[360,3792,1024],{},[360,3794,1027],{},[360,3796,1030],{},[46,3798,3799],{"className":909,"code":1033,"language":911,"meta":55,"style":55},[53,3800,3801,3805,3809,3813,3841,3845,3863,3867,3877,3891,3895,3899,3903,3907,3911,3939,3943,3953,3971,3975,3979,3989,3993,3997,4011,4015,4025,4029,4033,4043,4057,4061,4065,4077,4081,4085,4089,4093,4097,4101,4105,4113,4117,4129],{"__ignoreMap":55},[67,3802,3803],{"class":69,"line":70},[67,3804,1040],{"class":918},[67,3806,3807],{"class":69,"line":77},[67,3808,1045],{"class":918},[67,3810,3811],{"class":69,"line":94},[67,3812,1050],{"class":918},[67,3814,3815,3817,3819,3821,3823,3825,3827,3829,3831,3833,3835,3837,3839],{"class":69,"line":107},[67,3816,1055],{"class":73},[67,3818,1058],{"class":431},[67,3820,962],{"class":73},[67,3822,1063],{"class":87},[67,3824,519],{"class":73},[67,3826,1068],{"class":924},[67,3828,1071],{"class":73},[67,3830,1075],{"class":1074},[67,3832,519],{"class":73},[67,3834,1080],{"class":1074},[67,3836,1083],{"class":73},[67,3838,1086],{"class":924},[67,3840,1089],{"class":73},[67,3842,3843],{"class":69,"line":118},[67,3844,1094],{"class":918},[67,3846,3847,3849,3851,3853,3855,3857,3859,3861],{"class":69,"line":528},[67,3848,1099],{"class":924},[67,3850,1102],{"class":73},[67,3852,1105],{"class":80},[67,3854,519],{"class":73},[67,3856,287],{"class":80},[67,3858,1112],{"class":73},[67,3860,1115],{"class":924},[67,3862,1118],{"class":73},[67,3864,3865],{"class":69,"line":534},[67,3866,939],{"emptyLinePlaceholder":309},[67,3868,3869,3871,3873,3875],{"class":69,"line":540},[67,3870,1127],{"class":924},[67,3872,1071],{"class":73},[67,3874,1132],{"class":924},[67,3876,1135],{"class":73},[67,3878,3879,3881,3883,3885,3887,3889],{"class":69,"line":1138},[67,3880,1141],{"class":924},[67,3882,1144],{"class":73},[67,3884,1147],{"class":431},[67,3886,962],{"class":73},[67,3888,1152],{"class":80},[67,3890,973],{"class":73},[67,3892,3893],{"class":69,"line":1157},[67,3894,537],{"class":73},[67,3896,3897],{"class":69,"line":1162},[67,3898,939],{"emptyLinePlaceholder":309},[67,3900,3901],{"class":69,"line":1167},[67,3902,1170],{"class":918},[67,3904,3905],{"class":69,"line":1173},[67,3906,1176],{"class":918},[67,3908,3909],{"class":69,"line":1179},[67,3910,1182],{"class":918},[67,3912,3913,3915,3917,3919,3921,3923,3925,3927,3929,3931,3933,3935,3937],{"class":69,"line":1185},[67,3914,1099],{"class":924},[67,3916,1102],{"class":73},[67,3918,1192],{"class":80},[67,3920,519],{"class":73},[67,3922,1197],{"class":80},[67,3924,519],{"class":73},[67,3926,1202],{"class":80},[67,3928,1112],{"class":73},[67,3930,1115],{"class":924},[67,3932,1209],{"class":924},[67,3934,1212],{"class":73},[67,3936,1215],{"class":431},[67,3938,1218],{"class":73},[67,3940,3941],{"class":69,"line":1221},[67,3942,939],{"emptyLinePlaceholder":309},[67,3944,3945,3947,3949,3951],{"class":69,"line":1226},[67,3946,1127],{"class":924},[67,3948,1071],{"class":73},[67,3950,1132],{"class":924},[67,3952,1235],{"class":73},[67,3954,3955,3957,3959,3961,3963,3965,3967,3969],{"class":69,"line":1238},[67,3956,1141],{"class":924},[67,3958,1144],{"class":73},[67,3960,1147],{"class":431},[67,3962,962],{"class":73},[67,3964,1249],{"class":80},[67,3966,1252],{"class":73},[67,3968,63],{"class":431},[67,3970,1257],{"class":73},[67,3972,3973],{"class":69,"line":1260},[67,3974,537],{"class":73},[67,3976,3977],{"class":69,"line":1265},[67,3978,939],{"emptyLinePlaceholder":309},[67,3980,3981,3983,3985,3987],{"class":69,"line":1270},[67,3982,1099],{"class":924},[67,3984,1275],{"class":80},[67,3986,953],{"class":924},[67,3988,1280],{"class":73},[67,3990,3991],{"class":69,"line":1283},[67,3992,939],{"emptyLinePlaceholder":309},[67,3994,3995],{"class":69,"line":1288},[67,3996,1291],{"class":918},[67,3998,3999,4001,4003,4005,4007,4009],{"class":69,"line":1294},[67,4000,1297],{"class":924},[67,4002,1300],{"class":73},[67,4004,1115],{"class":924},[67,4006,1209],{"class":924},[67,4008,1307],{"class":431},[67,4010,1310],{"class":73},[67,4012,4013],{"class":69,"line":1313},[67,4014,939],{"emptyLinePlaceholder":309},[67,4016,4017,4019,4021,4023],{"class":69,"line":1318},[67,4018,1127],{"class":924},[67,4020,1071],{"class":73},[67,4022,1132],{"class":924},[67,4024,1327],{"class":73},[67,4026,4027],{"class":69,"line":1330},[67,4028,1333],{"class":918},[67,4030,4031],{"class":69,"line":1336},[67,4032,1339],{"class":918},[67,4034,4035,4037,4039,4041],{"class":69,"line":1342},[67,4036,1345],{"class":924},[67,4038,1071],{"class":73},[67,4040,1132],{"class":924},[67,4042,1352],{"class":73},[67,4044,4045,4047,4049,4051,4053,4055],{"class":69,"line":1355},[67,4046,1358],{"class":924},[67,4048,1144],{"class":73},[67,4050,1147],{"class":431},[67,4052,962],{"class":73},[67,4054,1152],{"class":80},[67,4056,973],{"class":73},[67,4058,4059],{"class":69,"line":1371},[67,4060,531],{"class":73},[67,4062,4063],{"class":69,"line":1376},[67,4064,939],{"emptyLinePlaceholder":309},[67,4066,4067,4069,4071,4073,4075],{"class":69,"line":1381},[67,4068,1384],{"class":73},[67,4070,1115],{"class":924},[67,4072,1209],{"class":924},[67,4074,1391],{"class":431},[67,4076,1394],{"class":73},[67,4078,4079],{"class":69,"line":1397},[67,4080,1400],{"class":73},[67,4082,4083],{"class":69,"line":1403},[67,4084,1406],{"class":73},[67,4086,4087],{"class":69,"line":1409},[67,4088,1412],{"class":73},[67,4090,4091],{"class":69,"line":1415},[67,4092,537],{"class":73},[67,4094,4095],{"class":69,"line":1420},[67,4096,939],{"emptyLinePlaceholder":309},[67,4098,4099],{"class":69,"line":1425},[67,4100,1428],{"class":918},[67,4102,4103],{"class":69,"line":1431},[67,4104,1434],{"class":918},[67,4106,4107,4109,4111],{"class":69,"line":1437},[67,4108,1440],{"class":924},[67,4110,1443],{"class":431},[67,4112,1446],{"class":73},[67,4114,4115],{"class":69,"line":1449},[67,4116,939],{"emptyLinePlaceholder":309},[67,4118,4119,4121,4123,4125,4127],{"class":69,"line":1454},[67,4120,1457],{"class":73},[67,4122,63],{"class":431},[67,4124,1462],{"class":73},[67,4126,211],{"class":80},[67,4128,1467],{"class":73},[67,4130,4131],{"class":69,"line":1470},[67,4132,1473],{"class":73},[150,4134,4135],{},[13,4136,1478],{},[38,4138,1482],{"id":1481},[46,4140,4141],{"className":909,"code":1485,"language":911,"meta":55,"style":55},[53,4142,4143,4147,4167,4171,4175,4195,4199,4203,4223,4227,4231,4255,4259,4263],{"__ignoreMap":55},[67,4144,4145],{"class":69,"line":70},[67,4146,1492],{"class":918},[67,4148,4149,4151,4153,4155,4157,4159,4161,4163,4165],{"class":69,"line":77},[67,4150,1497],{"class":924},[67,4152,1500],{"class":80},[67,4154,953],{"class":924},[67,4156,1209],{"class":924},[67,4158,1212],{"class":73},[67,4160,1509],{"class":431},[67,4162,962],{"class":73},[67,4164,1514],{"class":87},[67,4166,973],{"class":73},[67,4168,4169],{"class":69,"line":94},[67,4170,939],{"emptyLinePlaceholder":309},[67,4172,4173],{"class":69,"line":107},[67,4174,1525],{"class":918},[67,4176,4177,4179,4181,4183,4185,4187,4189,4191,4193],{"class":69,"line":118},[67,4178,1497],{"class":924},[67,4180,1500],{"class":80},[67,4182,953],{"class":924},[67,4184,1209],{"class":924},[67,4186,1212],{"class":73},[67,4188,1540],{"class":431},[67,4190,962],{"class":73},[67,4192,1545],{"class":87},[67,4194,973],{"class":73},[67,4196,4197],{"class":69,"line":528},[67,4198,939],{"emptyLinePlaceholder":309},[67,4200,4201],{"class":69,"line":534},[67,4202,1556],{"class":918},[67,4204,4205,4207,4209,4211,4213,4215,4217,4219,4221],{"class":69,"line":540},[67,4206,1497],{"class":924},[67,4208,1500],{"class":80},[67,4210,953],{"class":924},[67,4212,1209],{"class":924},[67,4214,1212],{"class":73},[67,4216,1571],{"class":431},[67,4218,962],{"class":73},[67,4220,1545],{"class":87},[67,4222,973],{"class":73},[67,4224,4225],{"class":69,"line":1138},[67,4226,939],{"emptyLinePlaceholder":309},[67,4228,4229],{"class":69,"line":1157},[67,4230,1586],{"class":918},[67,4232,4233,4235,4237,4239,4241,4243,4245,4247,4249,4251,4253],{"class":69,"line":1162},[67,4234,1497],{"class":924},[67,4236,1500],{"class":80},[67,4238,953],{"class":924},[67,4240,1209],{"class":924},[67,4242,1212],{"class":73},[67,4244,1601],{"class":431},[67,4246,1604],{"class":73},[67,4248,1514],{"class":87},[67,4250,1609],{"class":73},[67,4252,1612],{"class":87},[67,4254,1467],{"class":73},[67,4256,4257],{"class":69,"line":1167},[67,4258,939],{"emptyLinePlaceholder":309},[67,4260,4261],{"class":69,"line":1173},[67,4262,1623],{"class":918},[67,4264,4265,4267,4269,4271,4273,4275],{"class":69,"line":1179},[67,4266,1628],{"class":924},[67,4268,1212],{"class":73},[67,4270,1633],{"class":431},[67,4272,1604],{"class":73},[67,4274,1514],{"class":87},[67,4276,1467],{"class":73},[13,4278,1642],{},[46,4280,4281],{"className":909,"code":1645,"language":911,"meta":55,"style":55},[53,4282,4283,4287,4291,4299,4303,4307,4311,4315,4323],{"__ignoreMap":55},[67,4284,4285],{"class":69,"line":70},[67,4286,1652],{"class":918},[67,4288,4289],{"class":69,"line":77},[67,4290,74],{"class":73},[67,4292,4293,4295,4297],{"class":69,"line":94},[67,4294,1661],{"class":431},[67,4296,84],{"class":73},[67,4298,1666],{"class":87},[67,4300,4301],{"class":69,"line":107},[67,4302,121],{"class":73},[67,4304,4305],{"class":69,"line":118},[67,4306,939],{"emptyLinePlaceholder":309},[67,4308,4309],{"class":69,"line":528},[67,4310,1679],{"class":918},[67,4312,4313],{"class":69,"line":534},[67,4314,74],{"class":73},[67,4316,4317,4319,4321],{"class":69,"line":540},[67,4318,1688],{"class":431},[67,4320,84],{"class":73},[67,4322,1693],{"class":87},[67,4324,4325],{"class":69,"line":1138},[67,4326,121],{"class":73},[168,4328,1701],{"id":1700},[13,4330,1704],{},[46,4332,4333],{"className":909,"code":1707,"language":911,"meta":55,"style":55},[53,4334,4335],{"__ignoreMap":55},[67,4336,4337,4339,4341,4343,4345,4347,4349,4351,4353,4355,4357],{"class":69,"line":70},[67,4338,1497],{"class":924},[67,4340,1716],{"class":80},[67,4342,953],{"class":924},[67,4344,1209],{"class":924},[67,4346,1212],{"class":73},[67,4348,1725],{"class":431},[67,4350,1728],{"class":73},[67,4352,1731],{"class":87},[67,4354,519],{"class":73},[67,4356,1736],{"class":87},[67,4358,1739],{"class":73},[38,4360,1743],{"id":1742},[46,4362,4363],{"className":909,"code":1746,"language":911,"meta":55,"style":55},[53,4364,4365,4369,4389,4393,4397,4417,4421,4425,4439,4443,4447],{"__ignoreMap":55},[67,4366,4367],{"class":69,"line":70},[67,4368,1753],{"class":918},[67,4370,4371,4373,4375,4377,4379,4381,4383,4385,4387],{"class":69,"line":77},[67,4372,1497],{"class":924},[67,4374,1760],{"class":80},[67,4376,953],{"class":924},[67,4378,1209],{"class":924},[67,4380,1212],{"class":73},[67,4382,1769],{"class":431},[67,4384,962],{"class":73},[67,4386,1514],{"class":87},[67,4388,973],{"class":73},[67,4390,4391],{"class":69,"line":94},[67,4392,939],{"emptyLinePlaceholder":309},[67,4394,4395],{"class":69,"line":107},[67,4396,1784],{"class":918},[67,4398,4399,4401,4403,4405,4407,4409,4411,4413,4415],{"class":69,"line":118},[67,4400,1497],{"class":924},[67,4402,1791],{"class":80},[67,4404,953],{"class":924},[67,4406,1209],{"class":924},[67,4408,1212],{"class":73},[67,4410,1800],{"class":431},[67,4412,962],{"class":73},[67,4414,1805],{"class":87},[67,4416,973],{"class":73},[67,4418,4419],{"class":69,"line":528},[67,4420,939],{"emptyLinePlaceholder":309},[67,4422,4423],{"class":69,"line":534},[67,4424,1816],{"class":918},[67,4426,4427,4429,4431,4433,4435,4437],{"class":69,"line":540},[67,4428,1628],{"class":924},[67,4430,1212],{"class":73},[67,4432,1825],{"class":431},[67,4434,962],{"class":73},[67,4436,1805],{"class":87},[67,4438,973],{"class":73},[67,4440,4441],{"class":69,"line":1138},[67,4442,939],{"emptyLinePlaceholder":309},[67,4444,4445],{"class":69,"line":1157},[67,4446,1840],{"class":918},[67,4448,4449,4451,4453,4455,4457,4459,4461,4463],{"class":69,"line":1162},[67,4450,1628],{"class":924},[67,4452,1212],{"class":73},[67,4454,1849],{"class":431},[67,4456,962],{"class":73},[67,4458,1805],{"class":87},[67,4460,519],{"class":73},[67,4462,1858],{"class":87},[67,4464,973],{"class":73},[38,4466,1864],{"id":1863},[13,4468,1867],{},[13,4470,1870],{},[46,4472,4473],{"className":909,"code":1873,"language":911,"meta":55,"style":55},[53,4474,4475,4499,4505],{"__ignoreMap":55},[67,4476,4477,4479,4481,4483,4485,4487,4489,4491,4493,4495,4497],{"class":69,"line":70},[67,4478,1497],{"class":924},[67,4480,1102],{"class":73},[67,4482,1884],{"class":80},[67,4484,519],{"class":73},[67,4486,1889],{"class":80},[67,4488,1112],{"class":73},[67,4490,1115],{"class":924},[67,4492,1209],{"class":924},[67,4494,1212],{"class":73},[67,4496,1900],{"class":431},[67,4498,1394],{"class":73},[67,4500,4501,4503],{"class":69,"line":77},[67,4502,1907],{"class":73},[67,4504,1666],{"class":87},[67,4506,4507],{"class":69,"line":94},[67,4508,1473],{"class":73},[13,4510,1916,4511,1919,4513,1922,4515,1926],{},[53,4512,1884],{},[53,4514,1889],{},[53,4516,1925],{},[46,4518,4519],{"className":909,"code":1929,"language":911,"meta":55,"style":55},[53,4520,4521,4525],{"__ignoreMap":55},[67,4522,4523],{"class":69,"line":70},[67,4524,1936],{"class":918},[67,4526,4527,4529,4531,4533,4535,4537,4539,4541,4543,4545,4547],{"class":69,"line":77},[67,4528,1497],{"class":924},[67,4530,1102],{"class":73},[67,4532,1192],{"class":80},[67,4534,519],{"class":73},[67,4536,1202],{"class":80},[67,4538,1112],{"class":73},[67,4540,1115],{"class":924},[67,4542,1209],{"class":924},[67,4544,1957],{"class":73},[67,4546,1960],{"class":431},[67,4548,1963],{"class":73},[296,4550,1966],{},{"title":55,"searchDepth":77,"depth":77,"links":4552},[4553,4554,4555,4558,4561,4562],{"id":873,"depth":77,"text":874},{"id":896,"depth":77,"text":897},{"id":136,"depth":77,"text":137,"children":4556},[4557],{"id":1012,"depth":94,"text":1013},{"id":1481,"depth":77,"text":1482,"children":4559},[4560],{"id":1700,"depth":94,"text":1701},{"id":1742,"depth":77,"text":1743},{"id":1863,"depth":77,"text":1864},{},{"title":857,"description":1980},{"id":4,"title":5,"author":4566,"body":4567,"date":305,"description":306,"extension":307,"image":8,"meta":4767,"navigation":309,"path":310,"seo":4768,"stem":312,"tags":8,"__hash__":313},{"name":7,"avatar":8},{"type":10,"value":4568,"toc":4761},[4569,4573,4575,4582,4584,4586,4591,4593,4633,4635,4640,4642,4644,4648,4650,4656,4658,4662,4664,4668,4672,4677,4679,4709,4711,4741,4747,4755,4759],[13,4570,4571],{},[16,4572,19],{"href":18},[13,4574,22],{},[13,4576,25,4577,36],{},[27,4578,4579],{},[16,4580,35],{"href":31,"target":32,"rel":4581},[34],[38,4583,41],{"id":40},[13,4585,44],{},[46,4587,4589],{"className":4588,"code":50,"language":51},[49],[53,4590,50],{"__ignoreMap":55},[13,4592,58],{},[46,4594,4595],{"className":61,"code":62,"language":63,"meta":55,"style":55},[53,4596,4597,4601,4611,4621,4629],{"__ignoreMap":55},[67,4598,4599],{"class":69,"line":70},[67,4600,74],{"class":73},[67,4602,4603,4605,4607,4609],{"class":69,"line":77},[67,4604,81],{"class":80},[67,4606,84],{"class":73},[67,4608,88],{"class":87},[67,4610,91],{"class":73},[67,4612,4613,4615,4617,4619],{"class":69,"line":94},[67,4614,97],{"class":80},[67,4616,84],{"class":73},[67,4618,102],{"class":87},[67,4620,91],{"class":73},[67,4622,4623,4625,4627],{"class":69,"line":107},[67,4624,110],{"class":80},[67,4626,84],{"class":73},[67,4628,115],{"class":80},[67,4630,4631],{"class":69,"line":118},[67,4632,121],{"class":73},[13,4634,124],{},[46,4636,4638],{"className":4637,"code":128,"language":51},[49],[53,4639,128],{"__ignoreMap":55},[13,4641,133],{},[38,4643,137],{"id":136},[13,4645,140,4646,145],{},[16,4647,144],{"href":143},[13,4649,148],{},[150,4651,4652],{},[13,4653,154,4654,36],{},[53,4655,157],{},[13,4657,160],{},[162,4659,4660],{},[13,4661,166],{},[168,4663,171],{"id":170},[13,4665,4666,177],{},[27,4667,176],{},[13,4669,4670,183],{},[27,4671,182],{},[46,4673,4675],{"className":4674,"code":187,"language":51},[49],[53,4676,187],{"__ignoreMap":55},[13,4678,192],{},[46,4680,4681],{"className":61,"code":195,"language":63,"meta":55,"style":55},[53,4682,4683,4687,4697,4705],{"__ignoreMap":55},[67,4684,4685],{"class":69,"line":70},[67,4686,74],{"class":73},[67,4688,4689,4691,4693,4695],{"class":69,"line":77},[67,4690,206],{"class":80},[67,4692,84],{"class":73},[67,4694,211],{"class":80},[67,4696,91],{"class":73},[67,4698,4699,4701,4703],{"class":69,"line":94},[67,4700,218],{"class":80},[67,4702,84],{"class":73},[67,4704,223],{"class":87},[67,4706,4707],{"class":69,"line":107},[67,4708,121],{"class":73},[13,4710,230],{},[46,4712,4713],{"className":61,"code":233,"language":63,"meta":55,"style":55},[53,4714,4715,4719,4729,4737],{"__ignoreMap":55},[67,4716,4717],{"class":69,"line":70},[67,4718,74],{"class":73},[67,4720,4721,4723,4725,4727],{"class":69,"line":77},[67,4722,206],{"class":80},[67,4724,84],{"class":73},[67,4726,248],{"class":80},[67,4728,91],{"class":73},[67,4730,4731,4733,4735],{"class":69,"line":94},[67,4732,255],{"class":80},[67,4734,84],{"class":73},[67,4736,260],{"class":87},[67,4738,4739],{"class":69,"line":107},[67,4740,121],{"class":73},[13,4742,4743,270,4745,274],{},[27,4744,269],{},[53,4746,273],{},[13,4748,4749,280,4751,284,4753,288],{},[27,4750,279],{},[53,4752,283],{},[53,4754,287],{},[13,4756,4757,294],{},[27,4758,293],{},[296,4760,298],{},{"title":55,"searchDepth":77,"depth":77,"links":4762},[4763,4764],{"id":40,"depth":77,"text":41},{"id":136,"depth":77,"text":137,"children":4765},[4766],{"id":170,"depth":94,"text":171},{},{"title":5,"description":306},{"id":316,"title":317,"author":4770,"body":4771,"date":644,"description":645,"extension":307,"image":8,"meta":5009,"navigation":309,"path":647,"seo":5010,"stem":649,"tags":8,"__hash__":650},{"name":7,"avatar":8},{"type":10,"value":4772,"toc":5001},[4773,4778,4780,4782,4784,4786,4788,4792,4794,4798,4802,4808,4826,4830,4832,4834,4836,4838,4858,4860,4870,4926,4930,4932,4940,4990,4992,4994,4999],[13,4774,323,4775,330],{},[16,4776,329],{"href":326,"rel":4777},[328],[38,4779,334],{"id":333},[13,4781,337],{},[13,4783,340],{},[13,4785,343],{},[38,4787,347],{"id":346},[150,4789,4790],{},[13,4791,352],{},[13,4793,355],{},[357,4795,4796],{},[360,4797,362],{},[364,4799,4800],{},[360,4801,368],{},[357,4803,4804,4806],{"start":77},[360,4805,373],{},[360,4807,376],{},[364,4809,4810,4814,4818,4822],{},[360,4811,381,4812],{},[53,4813,334],{},[360,4815,386,4816],{},[53,4817,389],{},[360,4819,392,4820],{},[53,4821,395],{},[360,4823,398,4824],{},[53,4825,401],{},[357,4827,4828],{"start":107},[360,4829,406],{},[13,4831,409],{},[13,4833,412],{},[38,4835,416],{"id":415},[13,4837,419],{},[46,4839,4840],{"className":422,"code":423,"language":424,"meta":55,"style":55},[53,4841,4842],{"__ignoreMap":55},[67,4843,4844,4846,4848,4850,4852,4854,4856],{"class":69,"line":70},[67,4845,432],{"class":431},[67,4847,435],{"class":87},[67,4849,438],{"class":87},[67,4851,441],{"class":80},[67,4853,444],{"class":87},[67,4855,447],{"class":87},[67,4857,450],{"class":87},[38,4859,454],{"id":453},[357,4861,4862,4864,4866],{},[360,4863,459],{},[360,4865,462],{},[360,4867,465,4868,469],{},[53,4869,468],{},[46,4871,4872],{"className":61,"code":472,"filename":468,"language":63,"meta":55,"style":55},[53,4873,4874,4878,4884,4890,4900,4914,4918,4922],{"__ignoreMap":55},[67,4875,4876],{"class":69,"line":70},[67,4877,74],{"class":73},[67,4879,4880,4882],{"class":69,"line":77},[67,4881,483],{"class":80},[67,4883,486],{"class":73},[67,4885,4886,4888],{"class":69,"line":94},[67,4887,491],{"class":80},[67,4889,486],{"class":73},[67,4891,4892,4894,4896,4898],{"class":69,"line":107},[67,4893,498],{"class":80},[67,4895,84],{"class":73},[67,4897,503],{"class":87},[67,4899,91],{"class":73},[67,4901,4902,4904,4906,4908,4910,4912],{"class":69,"line":118},[67,4903,510],{"class":80},[67,4905,513],{"class":73},[67,4907,516],{"class":87},[67,4909,519],{"class":73},[67,4911,522],{"class":87},[67,4913,525],{"class":73},[67,4915,4916],{"class":69,"line":528},[67,4917,531],{"class":73},[67,4919,4920],{"class":69,"line":534},[67,4921,537],{"class":73},[67,4923,4924],{"class":69,"line":540},[67,4925,121],{"class":73},[357,4927,4928],{"start":107},[360,4929,547],{},[38,4931,551],{"id":550},[357,4933,4934,4936,4938],{},[360,4935,556],{},[360,4937,559],{},[360,4939,562],{},[46,4941,4942],{"className":61,"code":565,"filename":566,"language":63,"meta":55,"style":55},[53,4943,4944,4948,4954,4960,4970,4978,4982,4986],{"__ignoreMap":55},[67,4945,4946],{"class":69,"line":70},[67,4947,74],{"class":73},[67,4949,4950,4952],{"class":69,"line":77},[67,4951,483],{"class":80},[67,4953,486],{"class":73},[67,4955,4956,4958],{"class":69,"line":94},[67,4957,491],{"class":80},[67,4959,486],{"class":73},[67,4961,4962,4964,4966,4968],{"class":69,"line":107},[67,4963,589],{"class":80},[67,4965,84],{"class":73},[67,4967,594],{"class":87},[67,4969,91],{"class":73},[67,4971,4972,4974,4976],{"class":69,"line":118},[67,4973,601],{"class":80},[67,4975,84],{"class":73},[67,4977,606],{"class":87},[67,4979,4980],{"class":69,"line":528},[67,4981,531],{"class":73},[67,4983,4984],{"class":69,"line":534},[67,4985,537],{"class":73},[67,4987,4988],{"class":69,"line":540},[67,4989,121],{"class":73},[38,4991,622],{"id":621},[13,4993,625],{},[13,4995,628,4996,632],{},[16,4997,395],{"href":395,"rel":4998},[328],[296,5000,635],{},{"title":55,"searchDepth":77,"depth":77,"links":5002},[5003,5004,5005,5006,5007,5008],{"id":333,"depth":77,"text":334},{"id":346,"depth":77,"text":347},{"id":415,"depth":77,"text":416},{"id":453,"depth":77,"text":454},{"id":550,"depth":77,"text":551},{"id":621,"depth":77,"text":622},{},{"title":317,"description":645},1777837163306]